Closed jackttcoms closed 6 years ago
There is a "default" routing mechanism which will decode every URL into the following format:
/ControllerName/MethodName/param-1/param-2/...
for example:
This will automatically look for Controller "User" then call method "admin" passing it param "1"
URL: /user/admin/1
Every Controller should have a "default method" called "index". This will be used when calling /user
as it is equal to calling /user/index
but looks cleaner.
If you want to use redirect('')
then you must redirect to your Controller name or other Controller/Method as needed. For example, I want to redirect to /user/index
you would use redirect('/user')
CUSTOM ROUTING is processed prior to the default routing functionality. It allows you to craft URLs for unique situations and include some RegEx capabilities too. I will use your "Language" question for an example.
$route['german/user/1' = 'user/get/$1/german'];
The above prefixes the English default URL of /user/1
with a German lang tag. So we need a custom URL route that will pass into our Controller->Method
a param of "german" which will be handled accordingly to output in German text.
I see that but your example is for multiple languages? I think its much easier for the time being just to do a define language in the public/index.php and then do a load_helper or something where it will fetch the correct language file and then i somehow echo it via an array but as your MVC doesn't let me do $l['something'] i'm unsure how to approach it.
Thanks
Also what do you think looks better to use for pagination? https://github.com/jasongrimes/php-paginator https://github.com/onassar/PHP-Pagination
How did you do it in the past? If you did it via a url Parma you can easily add that using routing. If it is a preference, say after login, you could set it in the session and look up the $l value each time any controller loads.Using sessions is how I’d do it allowing the user to choose their language. If it’s for SEO purpose then a router url as shown before is better.
Sent from my iPad
On Jul 3, 2018, at 2:51 PM, jackttcoms notifications@github.com wrote:
I see that but your example is for multiple languages? I think its much easier for the time being just to do a define language in the public/index.php and then do a load_helper or something where it will fetch the correct language file and then i somehow echo it via an array but as your MVC doesn't let me do $l['something'] i'm unsure how to approach it.
Thanks
— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.
In the past i would have a folder called languages and then have file called en.php, es.php then in the config.php I would have this ->
$myLang = "en";
include_once('lang/' . $myLang . '.php');
then inside the en.php i would have an array...
$l = array
(
"something"=>"Something",
"something1"=>"Something 1"
);
and then on every page I would simply go $l['something'] which then echos 'Something'!
Usually i would use sessions and do the language bit like that so they can toggle between the two but with what i'm creating i just need a simple way where you type en then it goes to the English file on es for the Spanish file and then it automatically translates all the buttons etc. but tbh i feel like i'm just over complicating it. Also which pagination do you feel would be the best suited for your framework?
https://github.com/jasongrimes/php-paginator https://github.com/onassar/PHP-Pagination
Thanks
There is a global configuration file where you can set your language setting - see: /app/config/config.php
where you could do this:
$config['lang_default'] = 'en';
$config['lang_en'] = ['something' => 'Something', ... ]
$config['lang_es'] = ['something' => 'Something', ... ]
if($config['lang_default'] = 'es') {
define($l, $config['lang_es']);
} else {
define($l, $config['lang_en']);
}
Regarding pagination:
You will just need to be aware that this library parses the url so your MVC and this lib must coordinate url structure. Easy to do, just upfront planning like /controller/method/param1/param2/paginationNum
And, if you add a new MVC param later you will need to adjust the pagination parser as the url pattern will change of course.
https://github.com/jasongrimes/php-paginator
This library seems to use GET params so you could do /controller/method/param?page=1
https://github.com/onassar/PHP-Pagination
That said, any other "controlling values" for these pagination libs will need to be passed down from teh controller to the view as needed... just another "payload" value as we spoke in the past about.
Hi, Thanks very much for your quick replies atm but I already tried that (config.php) regarding languages and it did not work. But in my one, i will add a require 'es/en.php';
file which has the array in there! Maybe i'm doing something wrong...
In the app/config/config.php add this code:
$config['lang_default'] = 'en';
$config['lang_en'] = ['something' => 'Something'];
$config['lang_es'] = ['something' => 'Something'];
if($config['lang_default'] = 'es') {
define($l, $config['lang_es']);
} else {
define($l, $config['lang_en']);
}
Views File:
<h1><?php echo $l['something']; ?></h1>
And the error that i love so much... Undefined variable: l in /customers/a/d/5/domain.com/httpd.www/app/views/index.php on line 26
and Notice: Undefined variable: l in /customers/a/d/5/domain.com/httpd.www/app/config/config.php on line 69
Controller:
$data = [
'getSettings' => $getSettings,
'getCategories' => $getCategories,
'title' =>$l['something']
];
Also i'm adding email notifications atm but basically right now, i have my email helper that looks like this:
<?php
// Import PHPMailer classes into the global namespace
// These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
//Load Composer's autoloader
require '../vendor/autoload.php';
function sendEmail($recipientEmail, $recipientName, $subject, $body){
$mail = new PHPMailer(true);
//Server settings
$mail->SMTPDebug = 0; // Enable verbose debug output 0: no debug info 2,3: debug info
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = "smtp.gmail.com"; // Specify main and backup SMTP servers
$mail->Username = "email@gmail.com"; // SMTP username
$mail->Password = ""; // SMTP password
$mail->Port = 465; // TCP port to connect to 587
$mail->SMTPSecure = "ssl"; // Enable TLS encryption, `ssl` also accepted
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
//Recipients
$mail->setFrom('hello@domain.com', 'Noreply');
$mail->addAddress($recipientEmail, $recipientName); // Add a recipient
//$mail->addAddress('ellen@example.com'); // Name is optional
//$mail->addReplyTo('info@example.com', 'Information');
//$mail->addCC('cc@example.com');
//$mail->addBCC('bcc@example.com');
//Attachments
//$mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
//$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
//Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = $subject;
$mail->Body = $body;
//$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
if($mail->send()){
//echo 'Message has been sent';
return true;
}
else{
//echo $mail->ErrorInfo;
return false;
}
}
?>
And what I used to do was go in the model and in the if return true statement i would add the email bit like this:
public function mailer(){
//Load Composer's autoloader
require_once '.../vendor/phpmailer/autoload.php';
return $mail = new PHPMailer\PHPMailer\PHPMailer(true); // Passing `true` enables exceptions
}
if(!$query->error()){
// send the token email to the user
$mail = $this->mailer();
try {
//Server settings
$mail->SMTPDebug = 0; // Disable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = SMTP_HOST; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = SMTP_USER; // SMTP username
$mail->Password = SMTP_PASS; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = SMTP_PORT; // TCP port to connect to
//Recipients
$mail->setFrom(SMTP_FROM_EMAIL, SMTP_FROM_NAME);
$mail->addAddress($email, SITENAME . ' user'); // Add a recipient
//Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Restore your password | ' . SITENAME;
$mail->Body = 'Visit this link to reset your password.. please note that this link is valid for only one time. <br /> ' . $link;
$mail->AltBody = "Visit this link to reset your password.. please note that this link is valid for only one time. \n " . $link;
$mail->send();
return true;
} catch (Exception $e) {
return false;
}
}
but with your framework, the insert queries are like this so:
$this->db->insert('msi_users', $data1);
return true;
So how do you suggest i approach it with your framework and the reason i'm asking you is because as you built it so you know where things work best :)
RE: Pagination, do you think the 2nd one would be best suited yo your framework?
Thanks again very much!!!
Whoops! The code sample I provided has a typo in both "define" functions. It should have been like the following code. In place of your $l use LANG (or what ever you want to use as a defined global constant. You can access those values from anyplace, Controller, Model, View, Helper, etc.
$config['lang_default'] = 'en';
$config['lang_en'] = ['something' => 'Something-1'];
$config['lang_es'] = ['something' => 'Something-2'];
if($config['lang_default'] = 'es') {
define('LANG', $config['lang_es']);
} else {
define('LANG', $config['lang_en']);
}
RE: Pagination, do you think the 2nd one would be best suited yo your framework? YES, easier I feel.
Regarding Email - Are you asking how to store data about the sent email into a database using $this->db->insert('msi_users', $data1)
? If so, I would do this as two steps in the Controller, 1) send the email using this loaded Mailer Class, 2) store the data into your table. "Seperation of concern".
Vendor will not work! I have been trying to do PHPMailer library all day but it will not work! It just won't send! All the details are correct for logging in so i don't know why its not working! Please can you take a look! Am i doing something wrong? For testing purposes i have made a simple form where you submit the email and then you get an email but unfortunately the final bit has not gone to plan as it does not send an email! All the files are in the helper folder and then in a folder called vendor!
Controller:
public function reset()
{
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
$data = [
'email' => $email,
'email_err' => '',
];
if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
$data['email_err'] .= 'Invalid email address';
}
if(!$this->user->getUserByEmail($email) && filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
$data['email_err'] .= 'Email address does not exist';
}
if(!empty($data['email_err'])) {
$this->view('user/reset', $data);
} else {
try
{
$this->email->sendMail($data['email']);
$this->view('user/login');
}
catch(\Exception $ex) // Global exception again here
{
echo $ex->getMessage();
die();
// Later on, maybe pass the message into a "email not sent" view:
$this->view('common/error'); // Or whatever your view name is
}
}
} else {
$data = [
'email' => '',
'email_err' => ''
];
$this->view('user/reset', $data);
}
}
Model:
<?php if (!defined('BASE_PATH')) exit('No direct script access allowed');
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require HELPERS_PATH.'vendor/autoload.php';
class Emails extends Model
{
private $db;
public function __construct()
{
$this->db = new Model();
}
public function sendMail($email)
{
$mail = new PHPMailer(true); // Passing `true` enables exceptions
try {
//Server settings
$mail->isSMTP(); // Set mailer to use SMTP
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
$mail->SMTPDebug = 2; // Enable verbose debug output
$mail->Host = 'smtp.gmail.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'email@gmail.com'; // SMTP username
$mail->Password = '**********'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
//Recipients
$mail->setFrom('mail@example.com');
$mail->addAddress($email); // Add a recipient // Name is optional
// $mail->addReplyTo('mail@example.com');
//Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Forgotten password';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
} catch (Exception $e) {
throw new \Exception($e->errorMessage()); // Wrap it into a global exception
} catch (\Exception $e) { // Global exception - see the leading slash
throw $e;
}
}
}
View:
<form action="<?php echo FULL_ROOT . '/user/reset'; ?>" method="POST">
<?php echo flash('restore_state'); ?>
<div class="form-group row">
<label for="EmailInput" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" name="email" class="form-control" id="EmailInput" placeholder="Type your email" value="<?php echo $data['email']; ?>" />
<a class='text text-danger'><?php echo $data['email_err']; ?></a>
</div>
</div>
<div class="form-group row">
<div style="margin-left: calc(16.6666667% + 15px);">
<button type="submit" class="btn">Send me a link</button>
</div>
</div>
</form>
I feel like this is incorrect because the point of using a model is to strictly draw or grab data from the database. That whole PHPMailer code should actually be in the controllers as it doesnt work in the helpers :(
To clarify, are you saying that you CAN send and email from your server using another method but it ONLY does not work in the MVC? I ask b/c once I had a server that was built without a mail demon so PHP itself could not pass mail to anything? Meaning, is it the server or the code?
On Fri, Jul 6, 2018 at 11:56 AM jackttcoms notifications@github.com wrote:
Vendor will not work! I have been trying to do PHPMailer library all day but it will not work! It just won't send! All the details are correct for logging in so i don't know why its not working! Please can you take a look! Am i doing something wrong? For testing purposes i have made a simple form where you submit the email and then you get an email but unfortunately the final bit has not gone to plan as it does not send an email!
Controller:
public function reset() { if($_SERVER['REQUEST_METHOD'] == 'POST') {
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL); $data = [ 'email' => $email, 'email_err' => '', ]; if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) { $data['email_err'] .= 'Invalid email address'; } if(!$this->user->getUserByEmail($email) && filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) { $data['email_err'] .= 'Email address does not exist'; } if(!empty($data['email_err'])) { $this->view('user/reset', $data); } else {
try { $this->email->sendMail($data['email']); $this->view('user/login'); } catch(\Exception $ex) // Global exception again here { echo $ex->getMessage(); die();
// Later on, maybe pass the message into a "email not sent" view: $this->view('common/error'); // Or whatever your view name is
}
} } else { $data = [ 'email' => '', 'email_err' => '' ]; $this->view('user/reset', $data); }
}
Model:
<?php if (!defined('BASE_PATH')) exit('No direct script access allowed');
use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception;
require HELPERS_PATH.'vendor/autoload.php';
class Emails extends Model { private $db;
public function __construct() { $this->db = new Model(); }
public function sendMail($email) { $mail = new PHPMailer(true); // Passing
true
enables exceptions try { //Server settings $mail->isSMTP(); // Set mailer to use SMTP $mail->SMTPDebug = SMTP::DEBUG_SERVER; $mail->SMTPDebug = 2; // Enable verbose debug output $mail->Host = 'smtp.gmail.com'; // Specify main and backup SMTP servers $mail->SMTPAuth = true; // Enable SMTP authentication $mail->Username = 'email@gmail.com'; // SMTP username $mail->Password = '**'; // SMTP password $mail->SMTPSecure = 'tls'; // Enable TLS encryption,ssl
also accepted $mail->Port = 587; // TCP port to connect to//Recipients $mail->setFrom('mail@example.com'); $mail->addAddress($email); // Add a recipient // Name is optional // $mail->addReplyTo('mail@example.com'); //Content $mail->isHTML(true); // Set email format to HTML $mail->Subject = 'Forgotten password'; $mail->Body = 'This is the HTML message body <b>in bold!</b>'; $mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; $mail->send();
} catch (Exception $e) { throw new \Exception($e->errorMessage()); // Wrap it into a global exception } catch (\Exception $e) { // Global exception - see the leading slash throw $e; } } }
View:
— You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/sonicsleuth/mvc-framework-php/issues/10#issuecomment-403074762, or mute the thread https://github.com/notifications/unsubscribe-auth/ACmuEzJgGBLgQzKtP7jFl7g7B0W31Ygjks5uD4i1gaJpZM4U_1pi .
--
Richard Soares Sr. Software Engineer / Architect
LinkedIn: https://www.linkedin.com/in/richard-soares-0859a610/
The standard PHP Mail function works fine with your framework fine but the PHPMailer library just does not work!
When I use the first function from my helper it just keeps loading and then when it times out no error is returned but it’s odd because on my old code it worked fine but I don’t know if it’s something to do with your framework or something? But it’s very odd and has confused me because I can’t see what I’m doing wrong!
The server supports everything but maybe could I send you my code or you have a go at implementing the PHPMailer library in the sample blog because it’s very odd but using the packages vendor autoload is a basic and important feature to being able to extend the script!
Thanks again very much!
If you have access to the Server Mail Logs check them to see if there is a clue there. Also check your PHP error logs, server logs for clues. And, the issues list for the package itself for insight.
When adding a package into any "host framework" it's typically the package that needs debugging if it's not working (meaning the package itself or the code you wrote or some other dependency of the package). I don't really have time to debug other package code right now as I'm traveling between cities and countries for my job (big project).
Unfortunately my server does not have an automatic error log! This means i would need to create one so i have quickly done a simple error class like so:
<?php
/**
* Logger class
*/
class Logger{
/**
* Constructor
*
*/
private function __construct(){}
public static function log($header="", $message="", $filename="", $linenum=""){
$logfile = APPLICATION_PATH . "logs/log.txt";
$date = date("d/m/Y G:i:s");
$err = $date." | ".$filename." | ".$linenum." | ".$header. "\n";
$message = is_array($message)? implode("\n", $message): $message;
$err .= $message . "\n*******************************************************************\n\n";
// log/write error to log file
error_log($err, 3, $logfile);
}
}
Also I have a much more simple mail class now!
<?php
use Snipworks\SMTP\Email;
require_once HELPERS_PATH."mail/src/email.php";
function sendEmail($email){
$mail = new Email('smtp.gmail.com', 465);
$mail->setProtocol(Email::SSL); //SSL or TLS can be used. Or if there's other protocol you have
$mail->setLogin('email@gmail.com', '*********');
$mail->addTo($email, '<receiver name>'); //receiver's name is optional
$mail->setFrom('<sender email>', '<sender name>'); //sender's name is optional
$mail->setSubject('Test subject');
$mail->setMessage('<b>test message</b>', true); //argument 2=true (send HTML mail) | default: false (plain text)
echo (($mail->send()) ? 'Mail has been sent' : 'Error sending email') . PHP_EOL;
print_r($mail->getLog()); //display SMTP log
}
But i get the same odd loading error where it just keeps loading and then returns no error message. Could it be because it is inside the app folder or that i'm doing it through a helper or something in the .htaccess is preventing it? Should i try it inside the controller instead?
I have placed it inside the helpers folder and removed composer now so its just a folder called mail with the script in so folder structure = ROOT/app/helpers/mail/src/[file] so everything is lined up but its odd!
Thanks again and good luck with your project! Your job sounds really interesting!
Having your mAil function as a helper is correct. The logger should also be a helper too. Then you can require them in your controller and use them as any other helpers.
The htacess file will manage routing for the urls. Is the email doing any url reloading that would not conform to /controller/method/param?
Clarify “it just keeps loading” so I have an idea of the issue.
Cheers!
On Sun, Jul 8, 2018 at 7:28 AM jackttcoms notifications@github.com wrote:
Wow good luck with your project! Hope it all goes well!
Unfortunately my server does not have an automatic error log! This means i would need to create one so i have quickly done a simple error class like so:
<?php /**
- Logger class */ class Logger{ /**
- Constructor
*/ private function __construct(){} public static function log($header="", $message="", $filename="", $linenum=""){ $logfile = APPLICATION_PATH . "logs/log.txt"; $date = date("d/m/Y G:i:s"); $err = $date." | ".$filename." | ".$linenum." | ".$header. "\n"; $message = is_array($message)? implode("\n", $message): $message; $err .= $message . "\n***\n\n"; // log/write error to log file error_log($err, 3, $logfile); } }
I have placed it inside the core folder but regarding your framework where would be the best place to initiate it so that i can call it in the controller/model etc.
Also I have a much more simple mail class now!
<?php
use Snipworks\SMTP\Email; require_once HELPERS_PATH."mail/src/email.php";
function sendEmail($email){
$mail = new Email('smtp.gmail.com', 465); $mail->setProtocol(Email::SSL); //SSL or TLS can be used. Or if there's other protocol you have $mail->setLogin('email@gmail.com', '*****'); $mail->addTo($email, '
'); //receiver's name is optional $mail->setFrom(' ', ' '); //sender's name is optional $mail->setSubject('Test subject'); $mail->setMessage('test message', true); //argument 2=true (send HTML mail) | default: false (plain text) echo (($mail->send()) ? 'Mail has been sent' : 'Error sending email') . PHP_EOL;
print_r($mail->getLog()); //display SMTP log
}
But i get the same odd loading error where it just keeps loading and then returns no error message. Could it be because it is inside the app folder or that i'm doing it through a helper or something in the .htaccess is preventing it? Should i try it inside the controller instead?
I have placed it inside the helpers folder and removed composer now so its just a folder called mail with the script in so folder structure = ROOT/app/helpers/mail/src/[file] so everything is lined up but its odd!
Thanks again and good luck with your project! Your job sounds really interesting!
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/sonicsleuth/mvc-framework-php/issues/10#issuecomment-403281042, or mute the thread https://github.com/notifications/unsubscribe-auth/ACmuExPkL5w5b8kjfLLHMWZ5wQcAw73sks5uEezqgaJpZM4U_1pi .
--
Richard Soares Sr. Software Engineer / Architect
LinkedIn: https://www.linkedin.com/in/richard-soares-0859a610/
Ok thanks very much and I’m simply submitting a form to a helper so in the controller it’s sendEmail($email); but basically what happens is once submitting the “spinning circle” spins for around 1 minute then it just returns the URL https://domain.com/user/reset to a blank page.
After the form submits to your url and it’s processed by the email helper are you them returning a View or are you using the url endpoint like an API call where you need to return some Jason data?
On Sun, Jul 8, 2018 at 9:55 AM jackttcoms notifications@github.com wrote:
Ok thanks very much and I’m simply submitting a form to a helper so in the controller it’s sendmail($email); but basically what happens is once submitting the “spinning circle” spins for around 1 minute then it just returns the URL https://domain.com/user/reset to a blank page.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/sonicsleuth/mvc-framework-php/issues/10#issuecomment-403289431, or mute the thread https://github.com/notifications/unsubscribe-auth/ACmuEzSVxayiA49XFGf6zPoi6P7MXjBBks5uEg9cgaJpZM4U_1pi .
--
Richard Soares Sr. Software Engineer / Architect
LinkedIn: https://www.linkedin.com/in/richard-soares-0859a610/
All the code that I’m using is in the above messages! In the helper I have a print_r but I’m sure even if it does not have a return it would still send the email but I really don’t know! Maybe for debugging purposes should I try downloading the latest version and just do a quick email feature to see if it’s interfering with something I have already coded?
The controller is this:
public function reset() { if($_SERVER['REQUEST_METHOD'] == 'POST') {
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
$data = [
'email' => $email,
'email_err' => '',
];
if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
$data['email_err'] .= 'Invalid email address';
}
if(!$this->user->getUserByEmail($email) && filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
$data['email_err'] .= 'Email address does not exist';
}
if(!empty($data['email_err'])) {
$this->view('user/reset', $data);
} else {
sendMail($data['email']); $this->view('user/login'); }
// Later on, maybe pass the message into a "email not sent" view:
$this->view('common/error'); // Or whatever your view name is
}
}
} else {
$data = [
'email' => '',
'email_err' => ''
];
$this->view('user/reset', $data);
}
}
Have you tried setting breakpoints for debugging by walking thru the reset()
method simply doing a print_r($_POST
) or print_r($data)
to verify what is captured and where it might get derailed? I would do that to see what comes in and where is it branching and breaking.
The $_POST submits this:
Array ( [email] => jack@email.com )
And the $data has:
Array ( [email] => jack@email.com [email_err] => )
Its really just odd! I have requested the auto-generated error log from my host!
I fixed it :)
Basically it does not like gmail smtp so i tried my own hosting one and it works amazing so sorry for wasting your time and may i ask what your big project is? Thanks again!
Glad to see it worked out. Those types of bugs are huge time-sucks. I have had issues with Gmail too. I am head of development (VP) for equity securities of a crypto-currency wallet company called Uphold.com and deal with a large team of developers across the globe. A huge responsibility daily/nightly due to time zones.
Anyhow, have a good time.
Wow! Very nice, very interesting job - would u say crypto currency is worth investing in atm? Thanks
Cryptocurrency is like any other world currency just virtual so you can invest and ride the volatile ups/downs or just buy stuff too. Our wallet lets you hold multiple crypto and USD and move them between each other. We use a "card" model to help nubes better understand the monetary value.
Very nice and i must admit i am a nube at cryptocurrency but its because i have never bothered to read into it! I might create an account on your platform :)
Also can i ask you a quick question regarding the pagination, in your example you kept referring to it as $this->PaginationHelper($users);
but where do you get the $this from as its a helper, i thought you do the $this->load_helper(['email']);
then in that helper you have functions() and then in your code you would refer to it as PaginationHelper($users);
and not $this->PaginationHelper($users);
but can you explain that for me! Thanks very much!
You are correct. I rushed the answer. The corrected advice is below. Helpers are loaded in this way so that they can be used across classes and other functions, they sort-of become super functions.
// Load Helper Files
$this->load_helper(['myhelper']);
// Use Helper functions directly.
mySpecialHelper($parmas);
Note: you can load multiple helpers all at once b/c load_helper() accepts an array, like so:
$this->load_helper(['helperOne, helperTwo, helperThree']);
Quick question regarding security, I have built a simple shopping cart but with my model code that gets the data it wouldn't work when i placed $array in the bind array so I was just wondering how I secure this as it could be manipulated! Thanks
public function getItemsFromCart($array)
{
//$array = 1,2
//$bind = [':in' => $array];
$sql = 'SELECT id,price,name FROM msi_items WHERE id IN ('.$array.')';
$results = $this->db->selectExtended($sql);
return $results;
}
Thanks
Use the PHP implode() function to convert your array into a delimited string list which will be what the SQL IN() function needs like so:
$bind = [':in' => implode( ",", $array); // result is: (string) "1,2,3,4,5,6"
MySQL does not automagically process arrays.
As for security the lower level PDO functionality will auto-protect from SQL injection attempts.
Thanks, I already tried that tho and it only ever showed one result even tho the array->string was 1,2,3 which is why i did my method above which works but I always like to bind data for security but when I bind it, it only sees the first number. But as i'm using custom routing for this and using the :num that is security on its own surely by only allowing numbers? Thanks
public function getItemsFromCart($array)
{
$arraystring = implode(',',$array);
$bind = [':in' => $arraystring];
$sql = 'SELECT id,price,name FROM msi_items WHERE id IN (:in)';
$results = $this->db->selectExtended($sql, $bind);
return $results;
}
The only way that works:
public function cart()
{
$this->item = $this->model('Items');
$getSettings = $this->setting->getAll();
$getCategories = $this->setting->getCategories();
if( !empty($_SESSION['cart']) ){
$array = implode(',',$_SESSION['cart']);
$getCartItems = $this->item->getItemsFromCart($array);
$totalPrice = $this->computeTotalPriceCart($getCartItems);
} else{
$totalPrice = 0;
$getCartItems = FALSE;
}
$data = [
'getSettings' => $getSettings,
'getCategories' => $getCategories,
'title' => 'Cart',
'getItems' => $getCartItems,
'total' => $totalPrice
];
$this->view('cart', $data);
}
public function getItemsFromCart($array)
{
//$bind = [':in' => $arraystring];
$sql = 'SELECT id,price,name FROM msi_items WHERE id IN ('.$array.')';
$results = $this->db->selectExtended($sql);
return $results;
}
Thanks
Oh dw this guide: https://phpdelusions.net/pdo#in
The updated implode line below accomplished the same as the looping example from the guide you reference. You should be able to bind then. In place of binding in the string with ? (question mark) use ! (exclamation mark). The ! will bind the data without wrapping it in quotes, it's literal placement. This is supported by PDO natively.
$array = array(1,2,3,4,5);
$arraystring = '"' . implode('","',$array) . '"'; // new format for imploding
echo 'String: ' . $arraystring;
// output: String: "1","2","3","4","5"
// the delimiter is now (dblQuote Comma dblQuote) then wrap the whole imploded string in dblQuotes.
Thanks very much and can i ask you a coding question regarding a maintenance system, what would you say is the best way to approach it where you can disable the entire site but login page and then once logged in you can access entire site etc or if you know a better more simple way and also this is probably the easiest question ever but i have added a country select field that gets all the countries from the db but that data could be manipulated by using the development tools so how would you suggest i reinforce and make it so that if they edit the option value there is some kind of prevention mechanism! Thanks
Data Protection - Add a column that contains a unique ID like a custom PIN or hash. For example, a report containing a list of users should never reference the ID of the table because an end-user could change it or cycle thru them, 1,2,3,4. Instead, for each user give them a unique PIN and reference that in your backend business logic. For your country menu set a table column named "menu_id" and make the value (string) "USA" + some random number (ie: USA872625345)
Maintenance System -
So you are saying i should encrypt the ID for the view and then decrypt it in the controller? Thanks
Don't encrypt/decrypt the table record ID as that's wasteful overhead. In place, make a new column that has some unique (non-sequenced) identifier (aka: a tough ID) for any table that you may have to expose those records publically.
A common example is Users. You would not want to list their real record IDs on the web page or menu lists. Example: I make PIN keys for Users like 82726-88252-09962 which consist of rand-rand-time number parts.
You will do lookups based on THAT id not the actual record ID for query input coming from public users (never expose table IDs publicly). That said, you CAN do lookups from real record IDs for backend logic as needed (away from the public).
For your Country table, you could use SHA256 of the Country name and set it into a new menu_id column. That would seem quickest to refactor your code/process/logic I'd say.
Ok, thanks very much for that and are you saying for frontend public access I should never do WHERE id = :id
? and then if you look at Themeforest, they have the item id in the link! https://themeforest.net/item/murbani-minimal-portfolio-wordpress-theme/**22311309** so is this bad practice?
Also regarding the countries, wouldn't it be better to simply do a !in_array? Base it off of the countries array and if the id has been tampered with then record the ip address or say "nice try"
Also can I ask you a question regarding an achievement/badge system! I'm attempting to build one just for experience but would you say I have the right approach?
In the table I would have:
id | name | image | status | type | range0 | range1
1 | badge name | img.png | 1 | 2 | 10 | 29
Then in the controller I get the badges from the model which gets all badges that are active then in the view I do a foreach with the badges variable then inside do a switch/case system with if statements that vary depending on db value and then echo the badge.
Would you say this is the right approach or how would you suggest I do this?
Thanks
ThemeForest - Protecting a record ID from being sequenced is best practice when you DO NOT want someone trying to hack you. However, in some cases like ThemeForest they appear to allow this because they are (sort of) exploiting search engines to gain SEO page ranking. In other words, they know Google will notice this number and try sequencing it looking for more page content. If you do this manually you will see new content with new links appear - good for TF allowing Google to find those links. Seach Engines also backtrace URLs looking for content, so /users/1 may give a single user, but /users/ might list all users. Something to be aware of when exposing/hiding content from search bots.
Country IDs - You could do an in_array comparison when the data arrives. There are many ways to solve this type of issue.
Badges - You approach is good but I would just move the Loop/Switch into the Controller then pass a variable to the View containing the final strings. Either way is technically ok but I prefer keeping as much of the logic in the Controller vs View. The reason is b/c on a larger team another developer might be in charge of the View and you want to minimize s/he from breaking the logic.
Thanks ever so much! One other quick question, as i'm using SMTP, i'm currently just entering the details in the helper file but how would you suggest I do it so that its able to get the details from the db? So almost like another file with define('EMAIL_HOST', $data['getSettings'][0]['smtphost']);
and then in the helper file I can just go connect->host = EMAIL_HOST;
etc. but my question is as my email file is a helper how would you suggest I connect it to a database.
Sorry if I have worded that badly. Thanks again.
Accessing a DB for a specific concern thru a Helper file is perfectly fine. Think of Helper files as any miscellaneous tasks that need to be performed that just don't fit well into a Controller/Model.
Ok thanks very much. So would you suggest I create a file or in the public folder index.php do a define there? How would I approach this without risking security etc. I'm just thinking how do I get that data across basically or how I materialise it so right now I understand perfectly how to get the define bit of code to the helper my question is getting the settings table data into the define seeing as right now the only way to get data across is the controller which then places it onto the view but I can't see how I get that data placed into a file that is not the view. Sorry for sounding stupid, I just want to make sure everything is secure but at least I understand arrays now and now understand the MVC structure around 80% now! Still a bit rusty on certain things like what is mentioned above but I definitely am rather enjoying the MVC structure and how it saves me so much more time compared to writing pure php like I used to :)
Also, I have created a category/subcategory system as you can see here below, but where there is the echo I tried to do a $html and then $html. etc. and then return the $html instead of the echo as I felt it would be more optimised but that did not want to work so can you please jusr check out the code below and see why it does not work with a variable!
/*
* @param $cat
* @param $id
* @return category
*
* Loads Categories Menu Dropdown.
*/
function sub($cat, $id)
{
$html = '<div class="dropdown-menu" role="menu">';
$html. = '<a class="dropdown-item hide-me" role="presentation" href="#"><i class="fas fa-fire mr-2"></i> Most Popular</a>';
$html. = '<div class="dropdown-divider hide-me" role="presentation"></div>';
foreach($cat as $category) {
if($category['parent_id'] == $id){
$html. = '<a class="dropdown-item" role="presentation" href="'.FULL_ROOT.'/category/'.$category['id'].'/'.slugify($category['name']).'"><i class="'.$category['icon'].' mr-2"></i>'.$category['name'].'</a>';
}
}
$html. = '</div>';
return $html;
}
----------------
/*
* @param $cat
* @param $id
* @return category
*
* Loads Categories Menu Dropdown.
*/
function sub($cat, $id)
{
echo '<div class="dropdown-menu" role="menu">';
echo '<a class="dropdown-item hide-me" role="presentation" href="#"><i class="fas fa-fire mr-2"></i> Most Popular</a>';
echo '<div class="dropdown-divider hide-me" role="presentation"></div>';
foreach($cat as $category) {
if($category['parent_id'] == $id){
echo '<a class="dropdown-item" role="presentation" href="'.FULL_ROOT.'/category/'.$category['id'].'/'.slugify($category['name']).'"><i class="'.$category['icon'].' mr-2"></i>'.$category['name'].'</a>';
}
}
echo '</div>';
}
And then inside the view, I have this piece of code but unfortunately when I did the $html and returned it, it did not appear so do you know why this is?
<?php
$id = '';
echo '<ul class="nav navbar-nav mr-auto">';
foreach($data['getCategories'] as $category){
if($category['parent_id'] == 0){
echo '<li class="dropdown">';
echo '<a class="dropdown-toggle nav-link dropdown-toggle pl-0" data-toggle="dropdown" aria-expanded="false" href="#">'.$category['name'].'</a>';
$id = $category['id'];
sub($data['getCategories'], $id);
echo '</li>';
}
}
echo '</ul>';
?>
Thanks again very very much!
One last question on issue no 10 and then I think I'll start a new one as its a tad long (43) but regarding this...
A common example is Users. You would not want to list their real record IDs on the web page or menu lists. Example: I make PIN keys for Users like 82726-88252-09962 which consist of rand-rand-time number parts.
Are you basically saying I do this? 'pin' => rand().'-'.rand().'-'.time(),
which produces this: 620551908-1048593110-1532342311
?
Thanks in advance!
NOTE: mt_rand() maybe better?
YES, exactly that approach for a PIN. Optionally, you could remove the "-" as the hyphen is only there to help Users "read" their PIN when provided to them, say for verification of login.
Since PHP 7.1 mt_rand
has superseded rand
completely, and rand
was made an alias for mt_rand
.
Ok thanks very much, I have changed it to 'pin' => rand(1000, 9999).rand(10,99).time(),
so it will always generate 16 characters and then for user presentation added a function that places dashes after every 4 characters:
function dashpin($str) {
return implode("-", str_split($str, 4));
}
Thanks
If i do not use the custom router and then go $id = '' if $id == '' then redirect to '' it redirects fine but when i use the custom router it does not work and just takes me to the homepage but not as a redirect.
Controller Code:
Custom Route:
Do you know why this is?
Also what would you say is the best way to implement languages? Because I used to do an array with the variable $l and then would echo like $l['something'] but as it does not work the same with your MVC how would you suggest i approach it without using a database?
Thanks in advance!