Better practice to throw custom PHP errors using procedural way - php

I know this question may be asked previously but I want to show my code and I would like to know that whether am doing a simple thing or complicating the code? Moreover answers say use try and catch but am going with procedural method so I would like to know that am I going right?
What I do it, for example a contact form
<?php
if(isset($_POST['contact'])) {
$throw_error = array();
//First Block Is Validation
if($_POST['first_name'] == '' || $_POST['last_name'] == '') {
$throw_error['field_blank'] = 'Fields Cannot Be Blank';
} elseif(strlen($_POST['first_name']) < 3) {
$throw_error['char_len'] = 'First Name Cannot Be Less Than 3 Characters';
}
//Second Block Is Process If No Errors Are Found
if(empty($throw_error)) {
$first_name = $_POST['first_name'];
//Don't worry about the sanitizing part, am doing it
//Process the form ahead and then redirect using header()
}
} elseif(!empty($throw_error)) { //Third Block To Throw Error If Any Errors Found
if(isset($throw_error['field_blank'])) {
echo $throw_error['field_blank'];
} elseif(isset($throw_error['char_len'])) {
echo $throw_error['char_len'];
}
}
?>
<form>
<input type="text" name="first_name" />
<input type="text" name="last_name" />
<input type="submit" value="Submit" name="contact" />
</form>

I would also recommend using Try/Catch. You can still use it in procedural blocks.
If you are dead set against it, this code looks like it will do what you want it to do, but it's over-engineered. Since the user can either have a field_blank or char_len error, you only need a single string error variable.
$error = NULL;
if($_POST['first_name'] == '' || $_POST['last_name'] == '') {
$error = 'Fields Cannot Be Blank';
} elseif(strlen($_POST['first_name']) < 3) {
$error = 'First Name Cannot Be Less Than 3 Characters';
}
...
if(!empty($error)) {
echo $error;
}
If you need to catch and display multiple non-exclusive errors, you can use the array you cited in your sample code and just iterate over the values rather than making a giant if/elseif block.
} elseif(!empty($throw_error)) { //Third Block To Throw Error If Any Errors Found
foreach($throw_error as $key => $message) {
echo $message.'<br>';
}
}

A try/catch you be great here. It eliminates all necessary for a throw_error array, as well as cuts down dramatically on the code.
try{
$first_name = '';
if(isset($_POST['contact'])) {
if($_POST['first_name'] == '' || $_POST['last_name'] == '') {
throw new Exception('Fields Cannot Be Blank');
} elseif(strlen($_POST['first_name']) < 3) {
throw new Exception('First Name Cannot Be Less Than 3 Characters');
}
$first_name = $_POST['first_name'];
}
}catch(Exception $e){
echo $e->getMessage();
}
If you were looking to pass an array to this catch statement, the easist way that I have found, is to serialize the array, then unserialize once complete. This will allow you to print all errors at once:
try{
$first_name = '';
if(isset($_POST['contact'])) {
if($_POST['first_name'] == '' || $_POST['last_name'] == '') {
$throw_error[] = 'Fields Cannot Be Blank';
}
if(strlen($_POST['first_name']) < 3) {
$throw_error[] = 'First Name Cannot Be Less Than 3 Characters';
}
if(isset($throw_error)){
throw new Exception(serialize($throw_error));
}
$first_name = $_POST['first_name'];
}
}catch(Exception $e){
$errors = unserialize($e->getMessage());
foreach($errors as $error){
echo $error.'<br>';
}
}

Related

PHP show full list of errors in a array

I use OOP and i wanted to ask you guys how this would be done! I keep trying but its still not working ;(
Here is my class file:
class Signup {
// Error
public $error = array();
public function validate($username, $email_mobile, $password) {
if(!empty($username) || !empty($email_mobile) || !empty($password)){
if(strlen($username) < 3 || strlen($username) > 50){
$this->error = "Username is too short or too long!";
return $this->error;
}elseif(strlen($email_mobile) < 3 || strlen($email_mobile) > 50) {
$this->error = "Email is too short or too long!";
return $this->error;
}elseif(strlen($password) < 3 || strlen($password) > 50){
$this->error = "Password is too short or too long!";
return $this->error;
}
} else {
$this->error = "Please fill are required feilds";
return $this->error;
}
}
Here is my signup file
$error[] = $signup->validate($username, $email_mobile, $password);
<?php
// require('lib/function/signup.php');
if(isset($error)){
var_dump($error);
foreach ($error as $value) {
echo $value . "<br>";
}
}
?>
I know That im calling the $error in the same file and not the property error. But i dont know how to send this array to the other file! Please help me! Also i have Called everything and the problem is just with my code(i think), i only included my file and made a var to call my signup class
It is never too early in your development career to study coding standards. Jump straight to PSR-12, and adopt all of these guidelines to write beautiful, professional code.
Use data type declarations in your classes where possible, it will improve the data integrity throughout your project(s).
You appear to prefer returning an array of errors. For this reason, I see no benefit in caching the errors long-term in a class property. This coding style is fine to do, but you could choose to return nothing (void) and instead populate a class property $errors, then access it directly after the $signup->validate() call via $signup->errors or use a getter method.
The empty() checks are too late in the flow. Once the values have been passed to the class method, these values must already be declared. For this reason empty() is needless overhead to check for mere "falsiness". Just check the values' string length.
Your data quality checks seem a little immature (email and password checks should be much more complex), but I won't confuse you with any new complexity, but I do expect that your validation rules will increase as you realize that users cannot be trusted to put good values in forms without be forced to do so. For this reason, it is probably unwise to use a loop to check the value lengths because you will eventually need to write individual rules for certain values.
A possible write up:
class Signup
{
public function validate(
string $username,
string $email,
string $password
): array
{
$errors = [];
$usernameLength = strlen($username);
if ($usernameLength < 3 || $usernameLength > 50) {
$errors[] = "Username must be between 3 and 50 characters";
}
$emailLength = strlen($email);
if ($emailLength < 3 || $emailLength > 50) {
$errors[] = "Email must be between 3 and 50 characters";
}
$passwordLength = strlen($password);
if ($passwordLength < 3 || $passwordLength > 50) {
$errors[] = "Password must be between 3 and 50 characters";
}
return $errors;
}
}
When calling this method...
$signup = new Signup();
$errors = $signup->validate(
$_POST['username'] ?? '',
$_POST['email'] ?? '',
$_POST['password'] ?? ''
);
if ($errors) {
echo '<ul><li>' . implode('</li><li>', $errors) . '</li></ul>';
} else {
echo 'No errors';
}
You should add elements to the array, instead of overwriting it, and returning, on all the branches.
class Signup {
public $errors = [];
public function validate($username, $email_mobile, $password) {
if (empty($username)) {
$this->error[] = "Username cannot be empty";
} else {
$strlenUsername = strlen($username);
if ($strlenUsername < 3 || $strlenUsername > 50){
$this->errors[] = "Username is too short or too long!";
}
}
if (empty($email_mobile)) {
$this->error[] = "Email cannot be empty";
} else {
$strlenEM = strlen($email_mobile);
if ($strlenEM < 3 || $strlenEM > 50) {
$this->errors[] = "Email is too short or too long!";
}
}
if (empty($password)) {
$this->errors[] = "Password cannot be empty";
} else {
$strlenPass = strlen($password);
if ($strlenPass < 3 || $strlenPass > 50) {
$this->errors[] = "Password is too short or too long!";
}
}
return $this->errors;
}
}
If you always keep the same constrains for the three fields, you can shorten it:
class Signup {
public function validate($username, $email_mobile, $password) {
$errors = [];
$fields = [
'Username' => $username,
'Email' => $email_mobile,
'Password' => $password
];
foreach($fields as $key => $value) {
if (empty($value)) {
$errors[] = "$key cannot be empty";
} else {
$strlen = strlen($value);
if ($strlen < 3 || $strlen > 50) {
$errors[] = "$key is too short or too long!";
}
}
}
return $errors;
}
}
The above code guesses at what you are trying to do, if you just wanted a fix for not getting any results on $error see the original answer below.
Original answer.
Updating your code to this should give you the results you expect.
class Signup {
// Error
public $error = array();
public function validate($username, $email_mobile, $password) {
if (!empty($username) || !empty($email_mobile) || !empty($password)){
$strlenUsername = strlen($username);
$strlenEM = strlen($email_mobile);
$strlenPass = strlen($password);
if ($strlenUsername < 3 || $strlenUsername > 50){
$this->error[] = "Username is too short or too long!";
} elseif ($strlenEM < 3 || $strlenEM > 50) {
$this->error[] = "Email is too short or too long!";
} elseif ($strlenPass < 3 || $strlenPass > 50){
$this->error[] = "Password is too short or too long!";
}
} else {
$this->error[] = "Please fill are required feilds";
}
return $this->error;
}
}
Keep in mind that, since you are using if-else you will always have, at most, one element in the array, it is hard to tell what you are trying to do with certainty, so I didn't change the logic and just fixed the most obvious problem.
If you want to add error messages to the array, get rid of the else keyword on the conditionals.
If you want to only receive one error message, consider using a string instead of an array.

Display error if empty field - PHP

I want to display an error on the same page if any field is empty.
I've got this, which works but the empty error is displayed as soon as the page is loaded instead of appearing once empty fields are submitted.
<?php
// Required field names
$required = array('triangleSide1', 'triangleSide2', 'triangleSide3');
// Loop over field names, make sure each one exists and is not empty
$error = false;
foreach($required as $field)
{
if (empty($_POST[$field]))
{
$error = true;
}
}
if ($error)
{
echo "ALL FIELDS ARE REQUIRED";
}
else
{
echo header('Location: formSuccess.php');
}
?>
Any ideas? -- UPDATE // IVE TRIED ALL ANSWERS, nothing has worked so far
Wrap everything you check on post in this:
if (strtolower($_SERVER['REQUEST_METHOD']) == 'post')
{
// Your code containing checks here
}
This way, it will only trigger when a POST request is used.
If you have an input you know will always be submitted with the form, such as a hidden one:
<input type='hidden' name='formsubmit' value='1'>
Then you can test for this before validating the other inputs
if($_POST["formsubmit"]) {
// Required field names
$required = array('triangleSide1', 'triangleSide2', 'triangleSide3');
// Loop over field names, make sure each one exists and is not empty
$error = false;
foreach($required as $field) {
if (empty($_POST[$field])) {
$error = true;
}
}
if ($error) {
echo "ALL FIELDS ARE REQUIRED";
} else {
header('Location: formSuccess.php');
}
}
Also you don't echo the return of header()
OR another way ( I have something similar in one of my pages)
function check_presence($value){
return isset($value) && $value!=="";
}
function validate($required){
global $error
foreach($required as $field){
$value = trim($_POST[$field]);
if (!check_presence($value)){
$error = true;
}
}
return $error;
}
then on the page containing the form and its validation code
$required = array('triangleSide1', 'triangleSide2', 'triangleSide3');
if(isset($_POST["submit"]){
$error = validate($required);
if ($error){
echo "ALL FIELDS ARE REQUIRED";
}
}
Try isset instest of empty!!!
if (empty($_POST[$field]))
Become
if (isset($_POST[$field]))

Header Redirect after form Validation in PHP

I am trying this code as part of form processing:
<?php
if(isset($_POST['senderEmail']))
{
try
{
require '_php/_security/validation.php'; //SEE BELOW
$rules = array(
'senderEmail' => 'validEmail',
'emailTextbox' => 'validTextbox',
);
$validation = new Validation();
if ($validation->validate($_POST, $rules) == TRUE) {
require("_php/database/dbProcessing.php"); //Form Proccessing for database inclusion
}
else {
foreach($validation->emailErrors as $error){
$emailErrors[] = $error;
$_SESSION['$emailErrors'] = $emailErrors;
header('Location:indexmobile.php#emailErrors');
die('ABORT!');
}
}
}
catch (PDOException $e)
{
$error = 'Error adding elements to database: ' . $e->getMessage();
echo "Error: " . $error;
exit();
}
exit();
}
?>
The validation.php where I do my validation has this:
<?php
class Validation {
public $errors = array();
public function validate($data, $rules) {
$valid = TRUE;
foreach ($rules as $fieldname => $rule) {
$callbacks = explode('|', $rule);
foreach ($callbacks as $callback) {
$value = isset($data[$fieldname]) ? $data[$fieldname] : NULL;
if ($this->$callback($value, $fieldname) == FALSE) $valid = FALSE;
}
}
return $valid;
}
public function validEmail($value, $fieldname) {
$valid = !empty($value);
if ($valid == FALSE) {
$this->emailErrors[] = "The $fieldname is required";
return $valid;
} else {
$valid = filter_var($value, FILTER_VALIDATE_EMAIL);
if ($valid == FALSE) $this->emailErrors[] = "The $fieldname needs to be a valid email";
return $valid;
}
}
public function validTextbox($value, $fieldname) {
$valid = !empty($value);
if ($valid == FALSE) {
$this->emailErrors[] = "The $fieldname is required";
return $valid;
} else {
$whitelist = '/^[a-zA-Z0-9 ,\.\+\\n;:!_\-#]+$/';
$textarea = strip_tags($value);
$textarea = mysql_real_escape_string($textarea);
$valid = preg_match($whitelist, $textarea);
if ($valid == FALSE) $this->errors[] = "The $fieldname contains invalid characters";
return $valid;
}
}
}
Upon using this, Im have issues with the redirect (I think). It seems further that Im having errors in validation. My questions are thus:
Am I doing the header redirect correctly? I've read that " header() must be called before any actual output is sent,.." So is this the reason why this redirect is incorrect? how to make a redirect if i need to show/send something to the redirected page?
function validTextbox always ends up an error that the field is empty. Why so?
Is my entire process of form validation a good way of validating form fields (which i learned from watching an online tutorial)? What is a better way?
Is there something wrong with error reporting in this case?
Thank you for those who replies. I am new to PHP and trying my best to learn the language.
1 - There are several ways to pass on a message to the page you are redirecting to. One is through $_GET like this
$message="Some message for the next page.";
$message=urlencode($message);
header("Location:page.php?message=".$message);
then on page.php
if(!empty($_GET['message']))
{
$_GET['message'];
}
similarly you can also use the session (less secure)
$_SESSION['message']='some other message';
then on page.php
if (!empty($_SESSION['message']))
{
echo $_SESSION['message'];
unset($_SESSION['message']);
}
2 - I would have to see what you are passing to your validate function. You should do a var_dump of $_POST and add that to your question.
3 - It depends on your criteria. If you are just checking for emptiness its overkill. I don't know what text you need / consider valid, but a regex is a reasonable way of enforcing validation.
4 - See #2.

email validation in php

I'm trying to validate my username as an email address, however PHP isn't letting me do this! what's wrong here?
//This checks if all the fields are filled or not
if (!empty($_POST['username']) ||
!empty($_POST['password']) ||
!empty($_POST['repassword']) ||
!empty($_POST['user_firstname']) ||
!empty($_POST['user_lastname']) ){
header('Location: register.php?msg=You didn\'t complete all of the required fields');
}
if (filter_var($_POST['username'], FILTER_VALIDATE_EMAIL) === false){
$errors[] = 'The email address you entered is not valid';
}
here is the form i used in register.php
<form action="createuser.php" method="post" name="registration_form" id="registration_form">
<label>Email</label>
<input name="username" type="text" id="username" size="50" maxlength="50" /><br />
Typo?
header('Location: register.php?msg=You didn't complete all of the required fields');
^---unescaped embedded quote
Your empty logic is also faulty. You're checking if any fields are NOT empty (e.g. filled out) and then complaining that they're not filled out. remove the ! to invert the logic.
if (empty(...) || empty(...) || etc...)
instead of this use regular expression for validating your email address
function check_email_address($email) {
// First, we check that there's one # symbol,
// and that the lengths are right.
if (!preg_match("^[^#]{1,64}#[^#]{1,255}$", $email)) {
// Email invalid because wrong number of characters
// in one section or wrong number of # symbols.
return false;
}
// Split it into sections to make life easier
$email_array = explode("#", $email);
$local_array = explode(".", $email_array[0]);
for ($i = 0; $i < sizeof($local_array); $i++) {
if
(!preg_match("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&
↪'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$",
$local_array[$i])) {
return false;
}
}
// Check if domain is IP. If not,
// it should be valid domain name
if (!preg_match("^\[?[0-9\.]+\]?$", $email_array[1])) {
$domain_array = explode(".", $email_array[1]);
if (sizeof($domain_array) < 2) {
return false; // Not enough parts to domain
}
for ($i = 0; $i < sizeof($domain_array); $i++) {
if
(!preg_match("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|
↪([A-Za-z0-9]+))$",
$domain_array[$i])) {
return false;
}
}
}
return true;
}
and then check if it return true redirect it to location if not then simply throw an error
You would not get to Validate the email because your if statement is wrong .. it is checking if any of the post is not empty.
Replace it with
if (empty($_POST['username']) || empty($_POST['password']) || empty($_POST['repassword']) || empty($_POST['user_firstname']) || empty($_POST['user_lastname'])) {
For starters, look at the syntax highlighting for why you're getting parse errors.
header('Location: register.php?msg=You didn't complete all of the required fields');
needs to become:
header('Location: register.php?msg=You didn\'t complete all of the required fields');
How about you use javascript window.location? Sometimes header function is sensitive.And also put a submit button in your form since by default fields are empty when loaded.
if(isset($_POST['your_submit_button_name'])){
if (empty($_POST['username']) ||
empty($_POST['password']) ||
empty($_POST['repassword']) ||
empty($_POST['user_firstname']) ||
empty($_POST['user_lastname']) ){
?>
<script>
window.location = 'register.php?msg=You didn\'t complete all of the required fields';
</script>
<?php
}
if (filter_var($_POST['username'], FILTER_VALIDATE_EMAIL) === false){
$errors[] = 'The email address you entered is not valid';
}
}
NOTE: I remove "!" before your empty function since youre trapping the fields that are empty.
Try to use this solution:
$FormData = $_POST;
if(isset($FormData['button_name'])){
$Errors = array();
foreach ($$FormData as $key => $value) {
if(empty($value)) $Errors[] = 'Some message';
if($key = 'username'){
if(filter_var($value, FILTER_VALIDATE_EMAIL){
$Errors[] = 'The email address you entered is not valid';
}
}
}
if(empty($Errors)){
// #todo Do some action
} else {
header('Location: register.php?msg=You didn\'t complete all of the required fields');
}
}
function check_email($check) {
$expression = "/^[a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.([a-zA-Z]{2,4})$/";
if (preg_match($expression, $check)) {
return true;
} else {
return false;
}
}
Now use this method as :
if(!check_email($_REQUEST['ContactEmail'])){
$register_error .="Enter the correct email address!<br />";
$reg_error=1;
}

Multiple conditions in PHP

I know this is embarrassing easy but I cannot get this to work right now, keep getting syntax errors, I just added in a jquery code that pre-fills in a form filed and when you select the form field it will clear the default value. The result though is if a user submits the form without changing the default value, I need to see if it exist in addition to my normal string sanitations
In this snippet below of PHP I need to run 2 conditions on $fname but below will not work, can someone help please
$fname = 'first name';
if (trim($fname) == '') && ($fname != 'first name') {
$err .= "error";
}else{
$err .= "all good";
}
For karim79
this code below from your example, exactly like this gives me this error
Fatal Error: Can't use function return value in write context on line 5
<?PHP
$fname = '';
if(empty(trim($fname))) {
echo "First name is empty";
}
?>
$fname = 'first name';
if (trim($fname) == '' || $fname != 'first name') {
$err .= "error";
} else {
$err .= "all good";
}
I would prefer to use strcmp:
if (trim($fname) == '' || strcmp($fname,'first name') !== 0) {
$err .= "error";
} else {
$err .= "all good";
}
If the case of the first name is not important, you should consider using strcasecmp instead. Also note you can use empty to test for the empty string:
$fname = '';
$fname = trim($fname);
if(empty($fname)) {
echo "First name is empty";
} else {
echo "Not empty";
}
When using empty, beware the following (from the manual):
Note: empty() only checks variables as
anything else will result in a parse
error. In other words, the following
will not work: empty(trim($name)).
$fname = 'first name';
if (trim($fname) == '' || $fname == 'first name') {
$err .= "error";
}else{
$err .= "all good";
}
PS: I assumed you want to raise an error if the string is either empty or the standard value. If that's wrong let me know.
I would NOT recommend using empty() for anything. It has some tricky return patterns, including telling you that a 0 is empty, and things of that nature. This, unfortunately, is a shortcoming of PHP.
Instead, try this algorithm (The following assumes your form POSTs):
<?php
$err = array();
// this is for sticklers..with E_STRICT on, PHP
// complains about uninitialized indexes
if( isset($_POST['name']) )
{
$name = trim($_POST['name']);
}
else
{
$name = '';
}
if( strlen($name) == 0 )
{
$err[] = "First name is required.";
}
// after validation is complete....
if( count($err) > 0 )
{
echo "There are errors!";
// probably something more elaborate here, like
// outputting an ordered list to display each error
print_r($err);
}
else
{
echo "It's all good!";
}
?>

Categories