Why is stdClass namespaced? - php

Argument 1 passed to nms\aclass::__construct() must be an instance
of nms\stdClass, instance of stdClass given
The __construct() function looks like public function __construct(stdClass $aclass)
And I get the error, I am passing in an instance of stdClass from the global namespace, not one from within the same namespace,
I also get the solution: public function __construct(\stdClass $aclass)
But what I don't get is why? I don't think it is even possible to overwrite stdClass is it? so would what is the difference between \stdClass and \nms\stdClass?

Sure it's possible to override stdClass inside of a namespace.
namespace Example;
class stdClass {
public function __construct() {
echo "Overridden!";
}
}
$global = new \stdClass();
$local = new stdClass;
Outputs:
Overridden!
Hence, if you want the original, you'll need to use the /stdClass global namespace. Much like with /Exceptions.

Related

PHP - how to get the "use (...)" section using reflection [duplicate]

When you create a method that returns a closure in PHP:
class ExampleClass {
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
The result of print_r contains this (the class whose method created the closure) and static, which appears to be the values bound within the use () statement of the closure:
$instance = new ExampleClass();
$closure = $instance->test();
print_r($closure);
Producing:
Closure Object (
[static] => Array (
[example] => 10
)
[this] => ExampleClass Object()
)
However I cannot for the life of me work out how to capture these values. It is not possible to use any form of property accessor (e.g. $closure->static or $closure->{'static'}) without receiving the following:
PHP Fatal error: Uncaught Error: Closure object cannot have properties in XYZ.
Array access notation obviously does not work either:
PHP Fatal error: Uncaught Error: Cannot use object of type Closure as array in XYZ.
JSON encoding the object, besides this making the values useless were they objects, provides an empty JSON object {} and using the ReflectionFunction class does not provide access to these items.
The closure documentation does not provide any means of accessing these values at all either.
Outside of doing something shameful like output buffering and parsing print_r or similar, I cannot actually see a way to get these values.
Am I missing something obvious?
Note: The use-case is for implementing memoization and these values would be extremely beneficial in identifying whether or not the call matched a previous cached call.
It seems you may have overlooked some of the ReflectionFunction methods.
Take a look at the ReflectionFunction::getClosureThis() method. I tracked it down by looking through the PHP 7 source code by doing a search for the zend_get_closure_this_ptr() which is defined in zend_closures.c.
The manual currently doesn't have a lot of documentation for this function. I'm using 7.0.9; try running this code based on your example:
class ExampleClass {
private $testProperty = 33;
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
$instance = new ExampleClass();
$closure = $instance->test();
print_r($closure);
$func = new ReflectionFunction($closure);
print_r($func->getClosureThis());
You should get output similar to
Closure Object
(
[static] => Array
(
[example] => 10
)
[this] => ExampleClass Object
(
[testProperty:ExampleClass:private] => 33
)
)
ExampleClass Object
(
[testProperty:ExampleClass:private] => 33
)
Regarding the closure static variables, these are returned with ReflectionFunction::getStaticVariables():
php > var_dump($func->getStaticVariables());
array(1) {
["example"]=>
int(10)
}
In order to get value of $example youn can try this
<?php
class ExampleClass {
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
$instance = new ExampleClass();
$number = call_user_func($instance->test(),null);
I found this solution into a Laravel framework and works for me.
call_user_func helps you.

Reading "this" and "use" arguments from a PHP closure

When you create a method that returns a closure in PHP:
class ExampleClass {
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
The result of print_r contains this (the class whose method created the closure) and static, which appears to be the values bound within the use () statement of the closure:
$instance = new ExampleClass();
$closure = $instance->test();
print_r($closure);
Producing:
Closure Object (
[static] => Array (
[example] => 10
)
[this] => ExampleClass Object()
)
However I cannot for the life of me work out how to capture these values. It is not possible to use any form of property accessor (e.g. $closure->static or $closure->{'static'}) without receiving the following:
PHP Fatal error: Uncaught Error: Closure object cannot have properties in XYZ.
Array access notation obviously does not work either:
PHP Fatal error: Uncaught Error: Cannot use object of type Closure as array in XYZ.
JSON encoding the object, besides this making the values useless were they objects, provides an empty JSON object {} and using the ReflectionFunction class does not provide access to these items.
The closure documentation does not provide any means of accessing these values at all either.
Outside of doing something shameful like output buffering and parsing print_r or similar, I cannot actually see a way to get these values.
Am I missing something obvious?
Note: The use-case is for implementing memoization and these values would be extremely beneficial in identifying whether or not the call matched a previous cached call.
It seems you may have overlooked some of the ReflectionFunction methods.
Take a look at the ReflectionFunction::getClosureThis() method. I tracked it down by looking through the PHP 7 source code by doing a search for the zend_get_closure_this_ptr() which is defined in zend_closures.c.
The manual currently doesn't have a lot of documentation for this function. I'm using 7.0.9; try running this code based on your example:
class ExampleClass {
private $testProperty = 33;
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
$instance = new ExampleClass();
$closure = $instance->test();
print_r($closure);
$func = new ReflectionFunction($closure);
print_r($func->getClosureThis());
You should get output similar to
Closure Object
(
[static] => Array
(
[example] => 10
)
[this] => ExampleClass Object
(
[testProperty:ExampleClass:private] => 33
)
)
ExampleClass Object
(
[testProperty:ExampleClass:private] => 33
)
Regarding the closure static variables, these are returned with ReflectionFunction::getStaticVariables():
php > var_dump($func->getStaticVariables());
array(1) {
["example"]=>
int(10)
}
In order to get value of $example youn can try this
<?php
class ExampleClass {
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
$instance = new ExampleClass();
$number = call_user_func($instance->test(),null);
I found this solution into a Laravel framework and works for me.
call_user_func helps you.

PHP type declaration (typehint) in function

As I understand, there is no way (even in PHP 7) to force function to take typehint of its parameter as an array of objects.
I think there is a workaroud to do that by defining another object as Traversable, which would be the container for all MyObject that would be otherwise in the array and setting the typehint to that Traversable.
But it would be so cool, if I could do this:
public function foo(MyObject[] $param) {}
So my question is, is there any reason why PHP doesn't implement this?
you can also
$arrYourObjectType = new YourObjectType[];
Then if the object array is your return type for the function, in your phpdoc, to type hint the return value, in the phpdoc above your function:
/**
* #param $whatever
* #return array ...$arrYourObjectType
**/
public function someFunction($whatever){
$arrYourObjectType[] = new YourObjectType[];
$x=0;
foreach($arrValues as $value)
{
$objYourObjectType = new YourObjectType();
$objYourObjectType->setSomething($value[0])
->setSomethingElse($value[1]);
(and so on)
//we had to set the first element to a new YourObjectType so the return
//value would match the hinted return type so we need to track the
//index
$arrYourObjectType[$x] = $objYourObjectType;
$x++;
}
return $arrYourObjectType;
}
Then in IDE's such as php storm, when using a class containing that function the return value of the function will be treated like an array of your object (properly hinted) and the IDE will expose the object methods on each element of the object array properly.
You can do things easy/dirty without all this, but phpStorm won't hint the methods on the elements of your object array properly.
If feeding an array of YourObjectType to a function...
/**
*#param YourObjectType ...$arrYourObjectType
**/
public function someFunction(YourObjectType...$arrYourObjectType){
foreach($arrYourObjectType as $objYourObject)
{
$someval = $objYourObject->getSomething();//will be properly hinted in your ide
}
}
It's all about the ellipses when feeding and retrieving object arrays :-)
Edit: I had a few things wrong with this because I did it from memory... corrected... Sorry bout this...
I don't understand well your question but if you want to insert data inside a object you can do:
<?php
class Insert
{
public $myobject = array();
public function foo($insert_in_object, $other_param_in_object) {
$this->myobject[] = $insert_in_object;
$this->myobject[] = $other_param_in_object;
return $this->myobject;
}
}
$start = new Insert();
$myobject = $start->foo('dog', 'cat');
var_dump($myobject)
?>

How to programmatically find public properties of a class from inside one of it's methods

I've got a class Foo with public and protected properties. Foo needs to have a non-static method, getPublicVars() that returns a list of all the public properties of Foo (this is just an example, I know from outside the Foo object calling get_object_vars() will accomplish this and there is no need for my getPublicVars() method).
Note: This must also return dynamically declared properties assigned at runtime to the class instance (object) that aren't defined in the class's definition.
Here's the example:
class Foo{
private $bar = '123';
protect $boo = '456';
public $beer = 'yum';
//will return an array or comma seperated list
public function getPublicVars(){
// thar' be magic here...
}
}
$foo = new Foo();
$foo->tricky = 'dynamically added var';
$result = $foo->getPublicVars();
var_dump($result); // array or comma list with 'tricky' and 'beer'
What is the most concise way to get the only the public properties of an object from inside a class's own methods where both public and protected are visible?
I've looked at:
What is the best way to look inside a PHP class instance (object) to see all of its available public properties and methods?
But this doesn't seem to address my question as it points to using get_object_vars() from outside the object.
As you already realized, PHP's build in get_object_vars is scope-sensitive. You want the public object properties only.
So from that function to the public variant is not a large step:
function get_object_public_vars($object) {
return get_object_vars($object);
}
Calling this get_object_public_vars will give you only the public properties then because it is place out of scope of the current object.
If you need more fine-grained control, you can also make use of the ReflectionObject:
(new ReflectionObject($this))->getProperties(ReflectionProperty::IS_PUBLIC);
Which has the benefit that you don't need to introduce another function in the global namespace.
Does not work with php version >=7
As such, I can't really recommend solution any longer.
Use reflection instead
To get the public properties from within the class
$publicProperties = call_user_func('get_object_vars', $this);
the "trick" is that get_object_vars is being called from the scope of call_user_func and not the scope of the object
no need for reflection, stand-alone functions, closures, etc
Another (PHP 7.* compatible) way is to cast $this to an array and filter out any binary keys. This is a little less verbose than using Reflection.
return array_filter(
(array) $this,
static fn(string $key): bool => strpos($key, "\0") !== 0, ARRAY_FILTER_USE_KEY,
);
Using the ReflectionClass, you can do this easily. For example, below, I make an associative array of all the public properties.
$rc = new \ReflectionClass($this);
//get all the public properties.
$props = $rc->getProperties(\ReflectionProperty::IS_PUBLIC);
$ret = [];
foreach($props as $p) {
//get the name and value of each of the public properties.
$ret[$p->getName()] = $p->getValue($this);
}
You can wrap it into a closure and bind it to nowhere, then you'll have an outer scope view to the local public properties.
public function getPublicVars(){
return \Closure::bind(fn($obj) => get_object_vars($obj),null,null)($this);
}
According to this article (written by Vance Lucas), you can create a new call scope inside your "Foo" class definition using an "anonymous" function, and then you can call get_object_vars() from within. This allow you to get only the public properties from inside your class, even if these have been created dynamically later from the outside.
So adapted to your example it would be:
<?php
class Foo {
private $bar = '123';
protected $boo = '456';
public $beer = 'yum';
// return an array of public properties
public function getPublicVars(){
$publicVars = create_function('$obj', 'return get_object_vars($obj);');
return $publicVars($this);
}
}
$foo = new Foo();
$foo->tricky = 'dynamically added var';
$result = $foo->getPublicVars();
print_r($result);
and the output will be:
Array
(
[beer] => yum
[tricky] => dynamically added var
)
There is a second example in the article mentioned above that shows another way to do the same using the so-called "closures" (from php 5.3) but for some reason it doesn't work for me with php v5.4 so the private and protected properties remains included in the resulting array.

Instantiating classes with params in singleton factory

I have a class that produces singleton classes. (Note that this is overly simplified code for the purpose of this question, for example it doesn't check that the filepath exists)
class Singleton
{
public function Load($classname, $params)
{
$filepath = 'classes/'.$classname.'.php';
require_once($filepath);
return $classname();
}
}
Now say that I wanted to pass an array of parameters that can vary in size to the constructor of the class being created. What is the best way to do this? I envision something along the lines of call_user_func_array but for classes?
You can achieve some interesting results with the use of PHP's Reflection library.
function Load( $class, $args )
{
$reflection = new ReflectionClass( $class );
$object = $reflection->newInstanceArgs( $args );
return $object;
}
This is simplified and implies use of the __autoload function, nor does it check for namespaces if you use them, plus it'll create a new instance of the class every time you call it, so you'll need to implement an array of objects to keep track of which ones you've created already, etc...
And for basic documentation: $class is a string with the name of the class you're wishing to instantiate, and $args is an array of arguments that you'll pass to the __construct( ) method.
not tested, but why not just load them into the constructor? ie return $classname($params); with your constructor set up like __construct($params = false). You can then check if params is passed or not, making your constructor parameters optional...
This does mean all your classes need to have the same constructor though.
class Foo {
public function __construct($params = false) {
if($params === false)
echo 'not passed';
else
print_r($params);
}
}
$class = 'Foo';
$foo = new $class(array('one', 'two'));
$foo2 = new $class();
outputs:
Array ( [0] => one [1] => two )
not passed

Categories