Similar question has been asked few days ago about error handling. People explained to me how to get errors from class. And i understand it how to create error names and validate in __construct section but still struggling with multiple functions
class magic
{
/**
* #param string $name
* #param string $surname
* #param int $age
* #throws Exception
*/
public function __construct($name, $surname, $age)
{
$errors = [];
if (empty($name)) {
$errors[] = 'Name is required.';
}
if (empty($surname)) {
$errors[] = 'Surname is required.';
}
if (!empty($errors)) {
throw new Exception(implode('<br />', $errors));
}
$this->name = $name;
$this->surname = $surname;
$this->age = $age;
}
public function printFullname()
{
echo $this->name . ' ' . $this->surname;
}
}
another file:
include 'class.php';
try {
$test = new magic('', '', '33');
$test->printFullname();
} catch (Exception $exc) {
echo $exc->getMessage(); //error messages
}
It works but problem with another function in this class:
class magic
{
/**
* #param string $name
* #param string $surname
* #param int $age
* #throws Exception
*/
public function __construct($name, $surname, $age)
{
$errors = [];
if (empty($name)) {
$errors[] = 'Name is required.';
}
if (empty($surname)) {
$errors[] = 'Surname is required.';
}
if (!empty($errors)) {
throw new Exception(implode('<br />', $errors));
}
$this->name = $name;
$this->surname = $surname;
$this->age = $age;
}
public function printFullname()
{
echo $this->name . ' ' . $this->surname;
}
public function auth()
{
//authentication goes here
if...
$errors[] = 'Error1';
else
$errors[] = 'Error2';
etc...
}
}
another file:
include 'class.php';
try {
$test = new magic('', '', '33');
$test->auth();
} catch (Exception $exc) {
echo $exc->getMessage(); //error messages
}
My function auth() working and return errors as if then echo but i would like to do with array.
I think what you are doing is unnecessary.
By the way you've written the constructor parameters, you are automatically saying that those parameters are required and must not be empty, since you haven't set a default value for them.
As for errors in multiple functions, I'd suggest you to look up at custom Exceptions. Create a custom Exception for every specific error (if you need to apply different actions or different types of errors) and then catch them as you would do with an Exception.
If you want to get errors from the exception as an array you should create your own exception class:
class MagicException extends Exception
{
private $errors;
function __construct($message, array $errors, $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
$this->errors = $errors;
}
function getErrors()
{
return $this->errors;
}
}
Usage:
try {
$errors = [];
// some code..
$errors[] = 'Example error';
if ($errors) {
throw new MagicException('Something went wrong', $errors);
}
} catch (MagicException $e) {
// #todo: handle the exception
print_r($e->getErrors());
}
Output:
Array
(
[0] => Example error
)
Related
I have the following class
class FormValidator{
public function __construct() {}
public function __destruct(){}
private $value;
public function Value($value){
$this->value = trim($value);
return $this;
}
public function Required(){
if(empty($this->value)){
return false;
}
else{
return $this;
}
}
public function MinLength($length){
$len = strlen($this->value);
if($len < $length){
return false;
}
else{
return $this;
}
}
}
In my php code, I'm calling -
$validator = new FormValidator();
$result = $validator->Value("")->Required()->MinLength(5)->SomeOtherMethod();
The above line gives the error Call to a member function MinLength() on a non-object ...
UPDATE: I require to stop to call MinLength() if Required() returns false.
How can I make my statement functioning?
You should make use of exceptions instead, which would handle errors while the methods themselves would always return the current instance.
This becomes:
<?php
class FormValidationException extends \Exception
{
}
class FormValidator
{
private $value;
public function Value($value): self
{
$this->value = trim($value);
return $this;
}
/**
* #return $this
* #throws FormValidationException
*/
public function Required(): self
{
if (empty($this->value)) {
throw new \FormValidationException('Value is required.');
}
return $this;
}
/**
* #param int $length
* #return $this
* #throws FormValidationException
*/
public function MinLength(int $length): self
{
$len = strlen($this->value);
if ($len < $length) {
throw new \FormValidationException("Value should be at least {$length} characters long.");
}
return $this;
}
}
Usage:
$validator = new FormValidator();
try {
$result = $validator->Value("lodddl")->Required()->MinLength(5);
} catch (\FormValidationException $e) {
echo 'Error: ', $e->getMessage();
}
Demo: https://3v4l.org/OFcPV
Edit: since OP is using PHP 5.2 (sadly), here's a version for it, removing \s before root namespace, return type declarations and argument types.
Demo for PHP 5.2: https://3v4l.org/cagWS
Instead of working with Exceptions (the solution of #Jeto), you can also work with an array holding all errors.
A benefit of this solution is that you'll get multiple errors in one run, instead of breaking at the first error.
<?php
class FormValidator
{
private $value;
private $_errors = array();
public function Value($value)
{
$this->value = trim($value);
return $this;
}
/**
* #return $this
*/
public function Required()
{
if (empty($this->value)) {
$this->_errors[] = 'Value is required';
}
return $this;
}
/**
* #param int $length
* #return $this
*/
public function MinLength($length)
{
$len = strlen($this->value);
if ($len < $length) {
$this->_errors[] = "Value should be at least {$length} characters long.";
}
return $this;
}
public function hasErrors(){
return (count($this->_errors) > 0);
}
public function getErrors(){
return $this->_errors;
}
}
$validator = new FormValidator();
$validator->Value("1234")->Required()->MinLength(5);
if($validator->hasErrors()){
echo implode('<br>',$validator->getErrors());
}
Example here
cause method Required() returns false not Class object:
if(empty($this->value)){
return false;
}
You must change your code to.
$result = $validator->Value("");
if($result->Required()){ // if is not false do
$result->MinLength(5)->SomeOtherMethod();
}else{
// do anything if value is empty.
}
In the following methods you are calling to a method on a boolean value.
Required();
MinLength();
In order to solve this problem in the MinLength method:
if($len < $length){
// As a flag
$this->failed = true;
return $this;
}
and the SomeOtherMethod():
public function SomeOtherMethod() {
if (! $this->failed) {
// do something...
} else {
// do nothing...
}
}
Do the same for the Requied() method
Hi there still new to PHP and struggling with something really basic and it's frustrating me cause I can't see the error. I have read the PHP manual on passing array of objects.
class Customer{
public $companyId;
public $customerId;
public $name;
public function __construct($companyId,$customerId,$name)
{
$this->companyId = $companyId;
$this->customerId = $customerId;
$this->name = $name;
}
}
class CustomersDB
{
...
/**
* #return Customer[]
*/
public function getCustomers($search_str): array {
$resultObj = array();
$result = NULL;
try {
if (! $this->db) {
die('Database handle not defined') ;
}
if ($search_str && ! empty($search_str)) {
$result = $this->ListCustomers(Utils::COMPANY_ID, $search_str, $this->db);
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$_tmp = new Customer($row['CompanyID'],
$row['CustomerID'],
$row['CustomerName']);
// $resultObj.push($_tmp);
$resultObj[] = $_tmp;
}
}
} catch (Exception $e) {
// echo Utils::logMsgtoWeb($e->getTraceAsString());
} finally {
$result = NULL;
}
return $resultObj;
}
}
use Respect\Rest\Routable;
class Customers implements Routable {
/**
*
* Can pass in a partial string to search for a customer
* or pass in an ID for a specific match.
*/
public function get($searchStr){
// header('Content-type: application/json');
$result = $this->custdb.getCustomers($searchStr); // ERRORS HERE
if ($result && ! empty($result)) {
return json_encode( $result);
} else {
return NULL;
}
}
}
I get this error: PHP Recoverable fatal error: Object of class Scheduler\db\CustomersDB could not be converted to string in Customers.php.
Any help would be appreciated.
I have a class called members, i have an example below. What i am asking is how do i set the values of title. So for example , i only allow Mr, Mrs, Miss and any other values will throw out an error stating Only Mr,Mrs,Miss is allowed , Firstname must be John..
class Member
{
private $title;
private $firstname;
public function __construct( $title )
{
$this->title = $title;
}
public function showProfile()
{
echo "<dl>";
echo "<dt>Title:</dt><dd>$this->title</dd>";
echo "</dl>";
}
}
$data = new Member( "Mrr" );
$data->showProfile();
You can try this , hope this will be helpful.
Try this code snippet here
<?php
ini_set("display_errors", 1);
class Member
{
private $title;
public function __construct($title)
{
if(!in_array($title, ["Mr","Mrs","Miss"]))
{
throw new Exception("Only Mr,Mrs,Miss are allowed!");
//or you can simple echo out your message instead of exception
}
$this->title = $title;
}
public function showProfile()
{
echo "<dl>";
echo "<dt>Title:</dt><dd>$this->title</dd>";
echo "</dl>";
}
}
$data = new Member("Mrr");
Optionally you can set a variable for this error with in the class, which prevent further execution of methods of class script. You can also do it like this
Solution 2:
Try this code snippet here
<?php
ini_set("display_errors", 1);
class Member
{
private $title;
private $error=false;
public function __construct($title)
{
if(!in_array($title, ["Mr","Mrs","Miss"]))
{
$this->error=true;
}
$this->title = $title;
}
public function showProfile()
{
if($this->error!==true)
{
echo "<dl>";
echo "<dt>Title:</dt><dd>$this->title</dd>";
echo "</dl>";
}
else
{
echo "Only Mr,Mrs,Miss is allowed!";
}
}
}
$data = new Member("Mrr");
$data->showProfile();
Make a setter
function setTitle($newTitle){
if(in_array($newTitle, array('Mr', 'Miss', 'Mrs' ))
$this->title=$newTitle;
else
echo 'ERROR';
}
And then call it from the constructor
I didnt like any of the answers.
Here's mine. I think you should use a mutator in your solution. The member class should be decoupled from the setter.
class Member
{
private $title;
public function setTitle($title)
{
$this->title = $title;
}
public function showProfile()
{
return sprintf("<dl><dt>Title</dt><dt><dd>%s</dd></dt></dl>" , $this->title );
}
}
class TitleProperty
{
protected $name = 'title';
protected $allowed_allowed = ['mr', 'mrs', 'miss'];
public $errors = [];
/**
*#param Member $member
*#param string $value
*/
public function __construct( Member $member, $value )
{
if(!in_array($value, $this->allowed_allowed )){
$this->errors[] = "Only Mr,Mrs,Miss is allowed";
}
else{
$member->setTitle( $value );
}
}
}
$member = new Member();
$property = new TitleProperty($member, 'hello');
if($property->errors){
print_r($property->errors);
}
else{
echo 'title set.';
}
There you go
I still playing with PHP and OOP. But not understand how to pull back errors from the class.
index file
include 'class.php';
$test = new magic('', '', '33');
$test->getfullname();
foreach ($test->get_errors() as $error) {
echo $error . '<br>';
}
class:
class magic
{
private $name;
private $surname;
private $age;
private $errors = array();
function __construct($name, $surname, $age)
{
$this->name = $name;
$this->surname = $surname;
$this->age = $age;
}
public function get_errors()
{
return $this->errors;
}
public function getname()
{
if (!empty($this->name)) {
return true;
} else {
array_push($this->errors, 'Please check name');
return false;
}
}
public function getsurname()
{
if (!empty($this->surname)) {
return true;
} else {
array_push($this->errors, 'Please check surname');
return false;
}
}
public function getfullname()
{
if (($this->getname()) && ($this->getsurname())) {
echo $this->name . ' ' . $this->surname;
}
}
}
My question is why when name or surname is empty then returning please check name or surname but when both are empty then return only first? How to candle these type errors in PHP class and what is best practice to do that?
I don't think i can use try/catch exceptions in this scenario.
I suggest handling errors in the constructor and throwing exception.
class magic
{
/**
* #param string $name
* #param string $surname
* #param int $age
* #throws Exception
*/
public function __construct($name, $surname, $age)
{
$errors = [];
if (empty($name)) {
$errors[] = 'Name is required.';
}
if (empty($surname)) {
$errors[] = 'Surname is required.';
}
if (!empty($errors)) {
throw new Exception(implode('<br />', $errors));
}
$this->name = $name;
$this->surname = $surname;
$this->age = $age;
}
public function printFullname()
{
echo $this->name . ' ' . $this->surname;
}
}
client:
include 'class.php';
try {
$test = new magic('', '', '33');
$test->printFullname();
} catch (Exception $exc) {
echo $exc->getMessage(); //error messages
}
There's no reason you can't use exceptions in this scenario, it's what they are designed for, much more elegant than this kind of $this->geterrors(); stuff.
http://php.net/manual/en/language.exceptions.php
I'm relatively new in programming. I'm trying to catch and display errors in my aplication. With global variable is simple:
$errors = '';
class Name {
/**
* Validate form
*/
public function validate_form() {
global $errors;
(...)
if ( empty($_POST["blabla"]) ) {
$errors = 'Error';
}
(...)
return;
}
/**
* Display errors
*/
public function show_error() {
global $errors;
if(!empty($errors)) return '<div class="error">' . PHP_EOL . htmlspecialchars($errors) .'</div>';
}
}
...but i read that you should not use global variables. How can i do the same thing without global variable?
Sorry for my english ;)
How about not making it global, ie:
<?php
class Name {
public $errors;
/*
* Validate form
*/
public function validate_form() {
(...)
if ( empty($_POST["blabla"]) ) {
$this->errors = 'Error';
}
(...)
return;
}
}
Then everytime you run a fucntion in that class, check if an error was generated:
$obj = new Name()->validate_form();
if(isset($obj->errors)){
//oops, an error occured, do something
}
You can throw Exceptions
<?php
class Name {
/**
* Validate form
*/
public function validate_form() {
(...)
if ( empty($_POST["blabla"]) ) {
throw new RuntimeException( 'Error' );
}
(...)
return;
}
$obj = new Name();
/**
* Display errors
*/
public function show_error($e) {
return '<div class="error">' . PHP_EOL . htmlspecialchars($e->getMessage()) .'</div>';
}
}
// TEST
try {
$obj->validate_form();
}
catch(Exception $e) {
$obj->show_error($e);
}