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
Related
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
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
)
I'm trying to play with a class and not understand how it works. Some people explained how to pass variables between a function. My problem at the moment is errors. And how to extract errors from the class and print to the screen. My output is username only. How to get errors?
class form
{
protected $username;
protected $password;
protected $errors = array();
function __construct($username, $password){
$this->username = $username;
$this->password = $password;
}
public function get_errors()
{
return $this->errors;
}
public function getPassword(){
return $this->password;
}
public function getUserName() {
return $this->username;
return $this->errors = "No MySQL connection.";
}
}
$test = new form('name1', 'passw2');
echo $test->getUserName();
You can not return two time inside a function. But you can achieve what you want like below:-
public function getUserName() {
$this->errors = "No MySQL connection.";
return $this->username.'<br/>'.$this->errors;
}
Note:- this is the solution but your code have no mean. You have to do some useful stuff
try throw exception
public function getUserName() {
if($this->errors) {
throw new Exception($this->errors);
}
return $this->username;
}
$test = new form('name1', 'passw2');
try {
echo $test->getUserName();
} catch(Exception $error) {
echo 'Error:'.$error->getMessage();
}
If you get error you can simple catching this error and output to web,console or error log;
class form
{
protected $username;
protected $password;
protected $errors = array();
function __construct($username, $password){
$this->username = $username;
$this->password = $password;
}
public function getErrors()
{
return $this->errors;
}
public function getPassword()
{
return $this->password;
}
public function getUserName()
{
/* Add some an error to an error's array */
$this->errors[] = "No MySQL connection.";
return $this->username;
}
}
$test = new form('name1', 'passw2');
echo $test->getUserName();
var_dump($test->getErrors()); /* Get errors from a class */
I'm from the C# environment and I'm starting to learn PHP in school.
I'm used to set my properties in C# like this.
public int ID { get; set; }
What's the equivalent to this in php?
Thanks.
There is none, although there are some proposals for implementing that in future versions.
For now you unfortunately need to declare all getters and setters by hand.
private $ID;
public function setID($ID) {
$this->ID = $ID;
}
public function getID() {
return $this->ID;
}
for some magic (PHP likes magic), you can look up __set and __get magic methods.
Example
class MyClass {
private $ID;
private function setID($ID) {
$this->ID = $ID;
}
private function getID() {
return $this->ID;
}
public function __set($name,$value) {
switch($name) { //this is kind of silly example, bt shows the idea
case 'ID':
return $this->setID($value);
}
}
public function __get($name) {
switch($name) {
case 'ID':
return $this->getID();
}
}
}
$object = new MyClass();
$object->ID = 'foo'; //setID('foo') will be called
Thanks for your answers everyone. It helped me to create something like this:
In my parent class:
public function __get($name){
if (ObjectHelper::existsMethod($this,$name)){
return $this->$name();
}
return null;
}
public function __set($name, $value){
if (ObjectHelper::existsMethod($this,$name))
$this->$name($value);
}
ObjectHelper::existsMethod is a method which just check if given protected method exists.
private $_propertyName = null;
protected function PropertyName($value = ""){
if (empty($value)) // getter
{
if ($this-> _propertyName != null)
return $this->_propertyName;
}
else // setter
{
$this-> _propertyName = $value;
}
return null;
}
So I can use something like this in any class:
$class = new Class();
$class->PropertyName = "test";
echo $class->PropertyName;
I was inspired by C# :)
What do you think about this, guys?
Here is my ObjectHelper if someone would like to use it:
namespace Helpers;
use ReflectionMethod;
class ObjectHelper {
public static function existsMethod($obj, $methodName){
$methods = self::getMethods($obj);
$neededObject = array_filter(
$methods,
function ($e) use($methodName) {
return $e->Name == $methodName;
}
);
if (is_array($neededObject))
return true;
return false;
}
public static function getMethods($obj){
$var = new \ReflectionClass($obj);
return $var->getMethods(ReflectionMethod::IS_PROTECTED);
}
}
Mchi is right, but there is another way of doing it by using single function
private $ID;
public function ID( $value = "" )
{
if( empty( $value ) )
return $this->ID;
else
$this->ID = $value;
}
But yeah this approach is pretty much inline with what you do in c#. but this is only an alternative
Or try using php's __set and __get in your class more info here
http://php.net/manual/en/language.oop5.overloading.php
Another exampled using Variable function name
class MyClass {
private $ID;
protected $ID2;
private function setID($ID) {
$this->ID = $ID;
}
private function getID() {
return $this->ID;
}
private function setID2($ID2) {
$this->ID2 = $ID2;
}
private function getID2() {
return $this->ID2;
}
public function __set($name,$value) {
$functionname='set'.$name;
return $this->$functionname($value);
}
public function __get($name) {
$functionname='get'.$name;
return $this->$functionname();
}
}
$object = new MyClass();
$object->ID = 'foo'; //setID('foo') will be called
$object->ID2 = 'bar'; //setID2('bar') will be called
private $ID;
public function getsetID($value = NULL)
{
if ($value === NULL) {
return $this->ID;
} else {
$this->ID = $value;
}
}
I know I am a bit late to the party on this question, but I had the same question/thought myself. As a C# developer who does PHP, when the job requires, I want to have a simple way to create properties just I would be able to in C#.
I whipped up a first draft this afternoon which allows you to create the backing fields and specify their accessors or have pure accessors with no backing field. I will update my answer as the code evolves and provide a link when I get it to the state where it can be imported as a composer package.
For simplicity, I created the functionality as a PHP trait so you can drop it in to any class you want instead of having to extend a base class. Eventually I hope to extend this functionality to discern between external public calls to the properties and protected/private calls.
Here is the code for the trait itself:
trait PropertyAccessorTrait
{
private static $__propertyAccessors = [];
/* #property string $__propertyPrefix */
public function __get($name)
{
$this->__populatePropertyAcessors($name);
return $this->__performGet($name);
}
public function __set($name, $value)
{
$this->__populatePropertyAcessors($name);
$this->__performSet($name, $value);
}
public function __isset($name)
{
// TODO: Implement __isset() method.
}
public function __unset($name)
{
// TODO: Implement __unset() method.
}
protected function __getBackingFieldName($name)
{
if (property_exists(self::class, '__propertyPrefix')) {
$prefix = $this->__propertyPrefix;
} else {
$prefix = '';
}
return $prefix . $name;
}
protected function __canget($name)
{
$accessors = $this->__getPropertyAccessors($name);
return $accessors !== null && isset($accessors['get']);
}
protected function __canset($name)
{
$accessors = $this->__getPropertyAccessors($name);
return $accessors !== null && isset($accessors['set']);
}
protected function __performGet($name)
{
if (!$this->__canget($name)) {
throw new \Exception('Getter not allowed for property: ' . $name);
}
$accessors = $this->__getPropertyAccessors($name)['get'];
/* #var \ReflectionMethod $method */
$method = $accessors['method'];
if (!empty($method)) {
return $method->invoke($this);
}
return $this->{$this->__getBackingFieldName($name)};
}
protected function __performSet($name, $value)
{
if (!$this->__canset($name)) {
throw new \Exception('Setter not allowed for property: ' . $name);
}
$accessors = $this->__getPropertyAccessors($name)['set'];
/* #var \ReflectionMethod $method */
$method = $accessors['method'];
if (!empty($method)) {
return $method->invoke($this, $value);
}
$this->{$this->__getBackingFieldName($name)} = $value;
}
protected function __getPropertyAccessors($name)
{
return isset(self::$__propertyAccessors[$name])
? self::$__propertyAccessors[$name]
: null
;
}
protected function __getAccessorsFromDocBlock($docblock)
{
$accessors = [];
if (!empty(trim($docblock))) {
$doclines = null;
if (!empty($docblock)) {
$doclines = explode("\n", $docblock);
}
if (!empty($doclines)) {
foreach ($doclines as $line) {
if (preg_match('/#(get|set)\\s+(public|private|protected)/', $line, $matches)) {
$accessors[$matches[1]]['visibility'] = $matches[2];
}
}
}
}
return $accessors;
}
protected function __populatePropertyAcessors($name)
{
if ($this->__getPropertyAccessors($name) !== null) return;
try {
$property = new \ReflectionProperty(self::class, $this->__getBackingFieldName($name));
} catch (\ReflectionException $ex) {
$property = null;
}
$accessors = [];
if ($property != null) {
$accessors = $this->__getAccessorsFromDocBlock($property->getDocComment());
}
try {
$methodName = 'get' . ucfirst($name);
$method = new \ReflectionMethod(self::class, $methodName);
$method->setAccessible(true);
$accessors = array_merge($accessors, $this->__getAccessorsFromDocBlock($method->getDocComment()));
} catch (\ReflectionException $ex) {
$method = null;
}
if ($method !== null || isset($accessors['get'])) {
$accessors['get']['method'] = $method;
}
try {
$methodName = 'set' . ucfirst($name);
$method = new \ReflectionMethod(self::class, $methodName);
$method->setAccessible(true);
$accessors = array_merge($accessors, $this->__getAccessorsFromDocBlock($method->getDocComment()));
} catch (\ReflectionException $ex) {
$method = null;
}
if ($method !== null || isset($accessors['set'])) {
$accessors['set']['method'] = $method;
}
self::$__propertyAccessors[$name] = $accessors;
}
}
Here is a quick unit test I created using the Codeception format:
<?php
class PropertyAssesorTraitTestClass
{
use PropertyAccessorTrait;
private $__propertyPrefix = '_';
/**
* #get public
* #set public
*/
private $_integer = 1;
/**
* #get public
*/
private $_getonly = 100;
/**
* #set public
*/
private $_setonly;
private $_customDoubler;
private function getCustomDoubler()
{
return $this->_customDoubler * 2;
}
private function setCustomDoubler($value)
{
$this->_customDoubler = $value * 2;
}
public $publicField = 1234;
/**
* #return int
* #get public
*/
private function getPureAccessor()
{
return $this->publicField;
}
/**
* #param $value
* #set public
*/
private function setPureAccessor($value)
{
$this->publicField = $value;
}
private $_purePrivate = 256;
}
$I = new UnitTester($scenario);
$I->wantTo('Ensure properties are accessed correctly');
$instance = new PropertyAssesorTraitTestClass();
$I->assertSame(1, $instance->integer);
$instance->integer = 2;
$I->assertSame(2, $instance->integer);
$instance->integer = $instance->integer + 1;
$I->assertSame(3, $instance->integer);
$instance->integer++;
$I->assertSame(4, $instance->integer);
$I->assertSame(100, $instance->getonly);
$I->expectException('Exception', function () use ($instance) { $instance->getonly = 50; });
$instance->setonly = 50;
$I->expectException('Exception', function () use ($instance) { $a = $instance->setonly; });
$instance->customDoubler = 100;
$I->assertSame(400, $instance->customDoubler);
$I->assertSame(1234, $instance->publicField);
$instance->pureAccessor = 1000;
$I->assertSame(1000, $instance->publicField);
$instance->publicField = 1234;
$I->assertSame(1234, $instance->publicField);
$I->assertSame(1234, $instance->pureAccessor);
$I->expectException('Exception', function () use ($instance) { return $instance->purePrivate; });
I like to use this pattern:
class foo
{
//just add p as prefix to be different than method name.
protected $pData;
public funtion __construct() {}
public funtion __destruct() {}
public funtion __clone() {}
public function Data($value == "")
{
if ($value != "") {
$this->pData = $value;
}
return $this->pData;
}
}
$myVar = new foo();
//for SET
$myVar->Data("A Value");
//for GET
$item = $myVar->Data();
class MyClass
{
private $name = null;
public function __construct($name = null)
{
$this->name = $name;
}
public function __set($name, $value)
{
if (property_exists($this, $name)) {
$this->name = $value;
}
return $this;
}
public function __get($name)
{
if (property_exists($this, $name)) {
return $this->$name;
}
return null;
}
}
this is PHP ; you don't need get set
class MyClass {
public $ID;
}
$object = new MyClass();
$object->ID = 'foo';
echo $object->ID;
will work
I have a form that has this code in it, so I can echo the errors as I check the fields from a class:
<?php if( isset($_POST['send'])){
$new_user = new Register();
$new_user->check_required_fields($_POST);
$new_user->display_errors();
}
?>
and the class is:
<?php
class Register extends Database
{
public $fname;
public $lname;
public $uname;
public $email;
public $pass1;
public $pass2;
public $year;
public $month;
public $day;
public $required_array;
public $error;
public $errors = array();
public function check_required_fields($required_array)
{
if(in_array('', $required_array)) {
$errors[] = "One or more fields are missing";
//var_dump($errors);
}
else
{
$errors[] = "All fields are ok";
$this->fname = $required_array['fname'];
$this->lname = $required_array['lname'];
$this->uname = $required_array['lname'];
$this->email = $required_array['email'];
$this->pass1 = $required_array['pass1'];
$this->pass2 = $required_array['pass2'];
$this->year = $required_array['year'];
$this->month = $required_array['month'];
$this->day = $required_array['day'];
}
}
public function display_errors ($errors)
{
foreach ($errors as $error){
echo $error;
}
}
For some reason it will not display the $errors array and I am not sure why? I would be greatful for any help, thanks.
Try using
$this->errors
in both check_required_fields and display_errors.
public function display_errors ($errors)
{
foreach($errors as $error){
echo $error;
}
}
the "$errors" you use in the foreach statement is the one in the function display_errors's parameter list, and when you invoke the function, you didn't give any parameter, so this variable would be empty
you should use $this->errors in the foreach statement