Global check for valid properties in a PHP stdClass? - php

Is it possible to check properties from a PHP stdClass? I have some models which are being generated as an stdClass. When using them I would like to check if the properties I'm calling exist in some kind of Core-class. I've noticed __get is ignored by the stdClass...
How can properties from a stdClass be checked if they exist in the object?

StdClass objects contain only porperties, not code. So you can't code anything from "within" them. So you need to work around this "shortcomming". Depending on what generates these classes this can be done by "overloading" the data (e.g. with a Decorator) providing the functionality you've looking for:
class MyClass
{
private $subject;
public function __construct(object $stdClass)
{
$this->subject = $stdClass;
}
public function __get($name)
{
$exists = isset($this->subject->$name);
#...
}
}
$myModel = new MyClass($model);

Use get_object_vars() to iterate through the stdClass object, then use the property_exists() function to see if the current property exists in the parent class.

Just cast it to an array
$x = (array) $myStdClassObject;
Then you can use all the common array functions

Related

What can the third section be in -> chaining sequence?

I've seen two like these:
$this->propertyName;
$this->methodName();
And I know the code should look like this:
class myClass{
public $propertyName;
public function methodName(){
// statements
}
}
Recently I saw a code like this:
$this->CI->form_validation->set_message('investigate', '{field} ' . lang('wrong'));
What is CI (a method?)? What's form_validation? What's set_message? Are these nested methods? How does its code look like?
A method can return an object. You can assign this object to a variable and then call methods on it:
$objB = $objA->getObjectB();
$objB->someMethod();
Or you can skip the assignment and just inline it;
$objA->getObjectB()->someMethod();
As long as your methods return objects, you can just keep stacking them up:
$objA->getObjectB()->getObjectC()->getObjectD()->getObjectE();
The same holds true for object properties. A public property can hold another object:
$objA->objB = new objectB();
$objA->objB->someMethodOnObjectB();
So methods that return an object and public properties that contain an object can be stacked like this. You can mix them too:
$objA->getObjectB()->somePropertyOnObjectB->someMethod();
Also see Fluent Interface. It's common for objects to return instances of themselves for mutator methods. This allows you to turn this:
$obj = new Object();
$obj->setFoo('foo');
$obj->setBar('bar');
$obj->setBaz('baz');
$obj->doSomething();
Into this:
$obj = new Object();
$obj->setFoo('foo')->setBar('bar')->setBaz('baz')->doSomething();
And in PHP 5.6+, you don't even have to assign the object to a variable, you can dereference the new call directly:
(new Object())->setFoo('foo')->setBar('bar')->setBaz('baz')->doSomething();
CI is a object. In this exact context it is a class property, object type. Theoretically you may have also a method/function that return an object. Something like:
$ClassInstance->MethodThatReturnAnObject()->ObjectProperty = 'bla';
or even
$ClassInstance->MethodThatReturnAnObject()->ObjectMethod();
And the chain may continue with more levels.

PHP return array if breaking chain in singleton

I've built a singleton class with chaining methods (to be used in a template).
To make chaining work I need to return new static. It allows the next chain to be added. The problem I have is that I don't want to return the static object if there are no more chains.
Example
<?php
class bread {
public static $array;
public static function blueprints() {
static::$array = array('some', 'values');
return new static;
}
public static function fields() {
return static::$array;
}
}
$blueprints = bread::blueprints();
$fields = bread::blueprints()->fields();
print_r($blueprint) // Returns object - FAIL
print_r($fields ) // Returns array - OK
In the example above I want $blueprints to return an array, because there are no more methods chained on it.
How can that be done?
The simple answer is you cannot do what you want.
Method chaining is not a special thing for Php.
For your example
bread::blueprints()->fields();
This is not different than:
$tmp = bread::blueprints();
$tmp->fields();
So because of the Php does not know the context where the result will be used of it cannot change the return type.
Here is another version of this question:
Check if call is method chaining
However, your class can implement ArrayAccess interface.This will allow you to treat the object like an array without casting and you get total control over how the members are used.
You can try this:
$blueprints = (array)bread::blueprints();

$this acting alone in the php code

I have been confused by $this.I know $this->somevaribale used for refering global values...But i have seen a code like
class ClassName
{
private $array; //set up a variable to store our array
/*
* You can set your own array or use the default one
* it will set the $this->array variable to whatever array is given in the construct
* How the array works like a database; array('column_name' => 'column_data')
*/
function __construct($array = array('fruit' => 'apple', 'vegetable' => 'cucumber')) {
$this->array = $array;
}
/*
* Loops through the array and sets new variables within the class
* it returns $this so that you may chain the method.
*/
public function execute() {
foreach($this->array AS $key => $value) {
$this->$key = $value; //we create a variable within the class
}
return $this; //we return $this so that we can chain our method....
}
}
Here $this is called alone ...Am really confused with this..When i remove $this and replaced with $this->array i get error..
So my question is what is the use of calling $this alone and what it represents.
Thanx for the help.
$This is a reference for PHP Objects. You can learn more about objects and how $this works in the PHP manual here.
A class is a kind of "blueprint" of an object, and vice versa, and object is an instance of a class. When $this is used within the class, it refers to itself.
$hi = new ClassName();
$hi->execute()->method()->chaining()->is_like_this();
$hi refers to a ClassName object, and the function execute() returns the object itself.
$ha = $hi->execute();
// $ha refers to a ClassName object.
Method chaining (fluent interfaces) enables one to tidy up the code if one normally calls many methods of that object:
$hi->doSome();
$hi->doAnotherThing();
$hi->thirdMethodCall();
$hi->etcetera();
will become
$hi->doSome()
->doAnotherThing()
->thirdMethodCall()
->etcetera();
A couple of corrections to the terms you use:
$this is a reference to the "current" object, not "global values"
you're not "calling" anything here; functions are called, you're just using $this (which, again, is a variable holding an object)
So, return $this returns the current object as return value of the method. This is usually just done to facilitate fluent interfaces, a style where you can write code like:
$foo->bar()->baz()
Because bar() returns an object (the $this object), you can call its method baz() right afterwards.

Is there equivalent for __toString() method for other simple types in PHP?

_toString() is called when an object is used as string. How can I do something similar for numerical values, something like __toInt(), or __toArray(). Do such methods exist? Is there a work around? Is it a bad idea to use something like that even if there is a workaround for it?
There is no __toArray magic-method (just check the ones that exist here), but then, there shouldn't be, IMO.
Though people have asked for a magic toArray method, it doesn't look like such a method will be implemented any time soon.
Considering what objects are for, and how we use them, a toInt method wouldn't make much sense, and since all objects can be cast to an array, and can be iterated over, I see very little point in using __toArray anyway.
To "convert" on object to an array, you can use either one of the following methods:
$obj = new stdClass;
$obj->foo = 'bar';
var_dump((array) $obj);
//or
var_dump(json_decode(json_encode($obj), true));
This can be done with both custom objects, as stdClass instances alike.
As far as accessing them as an array, I can't see the point. Why write a slow magic method to be able to do something like:
$bar = 'foo';
$obj[$bar];
if you can do:
$obj->{$bar}
or if you can do:
foreach($obj as $property => $value){}
Or, if you need something a tad more specific, just implement any of the Traversable interfaces.
And for those rare cases, where you want an object to produce an array from specific properties in a very particular way, just write a method for that and call that method explicitly.
class ComplexObject
{
private $secret = null;
private $childObject = null;
public $foo = null;
//some methods, then:
public function toArray()
{//custom array representation of object
$data = array();
foreach($this->childObject as $property => $val)
{
if (!is_object($this->childObject->{$property}))
{
$data[$property] = $val;
}
}
$data['foo'] = $this->foo;
return $data;
}
//and even:
public function toJson()
{
return json_encode($this->toArray());
}
}
Ok, you have to call these methods yourself, explicitly, but that's not that hard, really... is it?

How to Add a PHP Property to a SimpleXMLElement?

I have a subclass of a SimpleXMLElement that I want to a class properties to that will define some default values for an attribute of created child-nodes.
In order to set this values, I attempted to override addChild with the following method:
public function addChild($name, $value = '')
{
$child = parent::addChild($name, $enc_val);
error_log(print_r($this->default_link_type, true));
$child->set_default_val($this->default_val);
return $child;
}
The problem is the expression: $this->default_val doesn't return the value of the property, but instead creates a new empty child object and returns it.
Can anyone think of a way of overriding this behvior for certain properties? Or think of any hack that will allow me to have essentially a global state for all of these SimpleXMLElement subclasses that doesn't involve writing to a file, key-value store etc.?
EDIT: The below doesn't fully work because now when do call asXML() all the elements have the config property as a child node. So I'm still after a solution.
I have finally found the answer by experimenting with various classes/methods in PHP's Reflection API.
You can add this to the SimpleXMLElement sublass to a get the value of a property of the current object:
protected function get_property($name)
{
$rc = new ReflectionClass($this);
$props = $rc->getDefaultProperties();
if (!isset($props[$name])) {
throw new InvalidArgumentException(
'$name does not hold the value of a valid property!'
);
}
return $props[$name];
}
Using methods such as ReflectionClass::getProperty() will not work.

Categories