When generating an object this way AND executing a method, PHP gives an error.
class A {
static public function b() {
$o = new get_called_class(); // works
$class = get_called_class();
$o = new $class; // works
$o = (new $class)->method(); // works
$o = (new get_called_class())->method(); // doesn't work
// error message: Class '...\get_called_class' not found
$o = (new (get_called_class()))->method(); // doesn't work
// error message: syntax error, unexpected '('
}
}
Why does the last lines fail?
How to write it in one line?
Unfortunately you can't do it directly with the function's return value, but you can save it into a variables and use the variable. You can also use static or self constants.
$class = get_called_class();
$o = (new $class())->method();
$o = (new static())->method();
$o = (new self())->method();
Not possible at all. If you want to use an instance, store it in a variable.
class MyClass {
public function method(): string {
return "Hello World";
}
}
$instance = new MyClass();
$result = $instance->method();
You could work around if you do not need an instance by using a static method.
class MyClass {
public static function method(): string {
return "Hello World";
}
}
$result = MyClass::method();
Related
It doesn't seem to work:
$ref = new ReflectionObject($obj);
if($ref->hasProperty('privateProperty')){
print_r($ref->getProperty('privateProperty'));
}
It gets into the IF loop, and then throws an error:
Property privateProperty does not exist
:|
$ref = new ReflectionProperty($obj, 'privateProperty') doesn't work either...
The documentation page lists a few constants, including IS_PRIVATE. How can I ever use that if I can't access a private property lol?
class A
{
private $b = 'c';
}
$obj = new A();
$r = new ReflectionObject($obj);
$p = $r->getProperty('b');
$p->setAccessible(true); // <--- you set the property to public before you read the value
var_dump($p->getValue($obj));
Please, note that accepted answer will not work if you need to get the value of a private property which comes from a parent class.
For this you can rely on getParentClass method of Reflection API.
Also, this is already solved in this micro-library.
More details in this blog post.
getProperty throws an exception, not an error. The significance is, you can handle it, and save yourself an if:
$ref = new ReflectionObject($obj);
$propName = "myProperty";
try {
$prop = $ref->getProperty($propName);
} catch (ReflectionException $ex) {
echo "property $propName does not exist";
//or echo the exception message: echo $ex->getMessage();
}
To get all private properties, use $ref->getProperties(ReflectionProperty::IS_PRIVATE);
In case you need it without reflection:
public function propertyReader(): Closure
{
return function &($object, $property) {
$value = &Closure::bind(function &() use ($property) {
return $this->$property;
}, $object, $object)->__invoke();
return $value;
};
}
and then just use it (in the same class) like this:
$object = new SomeObject();
$reader = $this->propertyReader();
$result = &$reader($object, 'some_property');
Without reflection, one can also do
class SomeHelperClass {
// Version 1
public static function getProperty1 (object $object, string $property) {
return Closure::bind(
function () use ($property) {
return $this->$property;
},
$object,
$object
)();
}
// Version 2
public static function getProperty2 (object $object, string $property) {
return (
function () use ($property) {
return $this->$property;
}
)->bindTo(
$object,
$object
)->__invoke();
}
}
and then something like
SomeHelperClass::getProperty1($object, $propertyName)
SomeHelperClass::getProperty2($object, $propertyName)
should work.
This is a simplified version of Nikola Stojiljković's answer
It doesn't seem to work:
$ref = new ReflectionObject($obj);
if($ref->hasProperty('privateProperty')){
print_r($ref->getProperty('privateProperty'));
}
It gets into the IF loop, and then throws an error:
Property privateProperty does not exist
:|
$ref = new ReflectionProperty($obj, 'privateProperty') doesn't work either...
The documentation page lists a few constants, including IS_PRIVATE. How can I ever use that if I can't access a private property lol?
class A
{
private $b = 'c';
}
$obj = new A();
$r = new ReflectionObject($obj);
$p = $r->getProperty('b');
$p->setAccessible(true); // <--- you set the property to public before you read the value
var_dump($p->getValue($obj));
Please, note that accepted answer will not work if you need to get the value of a private property which comes from a parent class.
For this you can rely on getParentClass method of Reflection API.
Also, this is already solved in this micro-library.
More details in this blog post.
getProperty throws an exception, not an error. The significance is, you can handle it, and save yourself an if:
$ref = new ReflectionObject($obj);
$propName = "myProperty";
try {
$prop = $ref->getProperty($propName);
} catch (ReflectionException $ex) {
echo "property $propName does not exist";
//or echo the exception message: echo $ex->getMessage();
}
To get all private properties, use $ref->getProperties(ReflectionProperty::IS_PRIVATE);
In case you need it without reflection:
public function propertyReader(): Closure
{
return function &($object, $property) {
$value = &Closure::bind(function &() use ($property) {
return $this->$property;
}, $object, $object)->__invoke();
return $value;
};
}
and then just use it (in the same class) like this:
$object = new SomeObject();
$reader = $this->propertyReader();
$result = &$reader($object, 'some_property');
Without reflection, one can also do
class SomeHelperClass {
// Version 1
public static function getProperty1 (object $object, string $property) {
return Closure::bind(
function () use ($property) {
return $this->$property;
},
$object,
$object
)();
}
// Version 2
public static function getProperty2 (object $object, string $property) {
return (
function () use ($property) {
return $this->$property;
}
)->bindTo(
$object,
$object
)->__invoke();
}
}
and then something like
SomeHelperClass::getProperty1($object, $propertyName)
SomeHelperClass::getProperty2($object, $propertyName)
should work.
This is a simplified version of Nikola Stojiljković's answer
I have a question close to this:
How to create constructor with optional parameters?
It is clear that we can make optional params like this:
function myFunction($param='hello')
but I want to use it in a class's method with $this->something instead of 'hello', it looks like this:
public function myFunction($param=$this->property)
but I get a:
Parse error: syntax error, unexpected '$this'
Is it possible to get it?
you need to set to null and check afterward
class example {
private $something = "something";
public function myFunction($a = null)
{
if($a === null)
$a = $this->something;
// more code goes here
return $a;
}
}
$test = new example();
print $test->myFunction();
// prints "something"
print $test->myFunction("hello");
// prints "hello"
You can do it like this
$Obj = new myclass();
class myclass{
var $data = 'tested';
function __construct(){
$this->testFunction();
}
public function testFunction($param = null){
if( $param == '' || $param == null){
$param = $this->data;
}
echo $param;
}
}
i have something like this:
class foo
{
//code
}
$var = new foo();
$var->newVariable = 1; // create foo->newVariable
$var->otherVariable = "hello, im a variable"; //create foo->otherVariable
i can get in class foo a list of all variables defined outside by user (newVariable, otherVariable,etc)? Like this:
class foo
{
public function getUserDefined()
{
// code
}
}
$var = new foo();
$var->newVariable = 1; // create foo->newVariable
$var->otherVariable = "hello, im a variable"; //create foo->otherVariable
var_dump($var->getUserDefined()); // returns array ("newVariable","otherVariable");
Thanks!.
Yes, using get_object_vars() and get_class_vars():
class A {
var $hello = 'world';
}
$a = new A();
$a->another = 'variable';
echo var_dump(get_object_vars($a));
echo '<hr />';
// Then, you can strip off default properties using get_class_vars('A');
$b = get_object_vars($a);
$c = get_class_vars('A');
foreach ($b as $key => $value) {
if (!array_key_exists($key,$c)) echo $key . ' => ' . $value . '<br />';
}
What is your goal? Imo it's not very good practice (unless you really know what you are doing). Maybe it's good idea consider create some class property like "$parameters" and then create setter and getter for this and use it in this way:
class foo {
private $variables;
public function addVariable($key, $value) {
$this->variables[$key] = $value;
}
public function getVariable($key) {
return $this->variables[$key];
}
public function hasVariable($key) {
return isset($this->variables[$key]);
}
(...)
}
$var = new foo();
$var->addVariable('newVariable', 1);
$var->addVariable('otherVariable', "hello, im a variable");
And then you can use it whatever you want, for example get defined variable:
$var->getVariable('otherVariable');
To check if some var is already defined:
$var->hasVariable('someVariable')
get_class_vars() http://php.net/manual/en/function.get-class-vars.php
You question is not clear though.
$var->newVariable = 1;
there are two possible contex of above expression
1) you are accessing class public variables.
like
class foo
{
public $foo;
public function method()
{
//code
}
}
$obj_foo = new foo();
$obj_foo->foo = 'class variable';
OR
2) you are defining class variable runtime using _get and _set
class foo
{
public $foo;
public $array = array();
public function method()
{
//code
}
public function __get()
{
//some code
}
public function __set()
{
// some code
}
}
$obj_foo = new foo();
$obj_foo->bar= 'define class variable outside the class';
so in which context your question is talking about?
I have a class like this:
class someClass {
public static function getBy($method,$value) {
// returns collection of objects of this class based on search criteria
$return_array = array();
$sql = // get some data "WHERE `$method` = '$value'
$result = mysql_query($sql);
while($row = mysql_fetch_assoc($result)) {
$new_obj = new $this($a,$b);
$return_array[] = $new_obj;
}
return $return_array;
}
}
My question is: can I use $this in the way I have above?
Instead of:
$new_obj = new $this($a,$b);
I could write:
$new_obj = new someClass($a,$b);
But then when I extend the class, I will have to override the method. If the first option works, I won't have to.
UPDATE on solutions:
Both of these work in the base class:
1.)
$new_obj = new static($a,$b);
2.)
$this_class = get_class();
$new_obj = new $this_class($a,$b);
I have not tried them in a child class yet, but I think #2 will fail there.
Also, this does not work:
$new_obj = new get_class()($a,$b);
It results in a parse error: Unexpected '('
It must be done in two steps, as in 2.) above, or better yet as in 1.).
Easy, use the static keyword
public static function buildMeANewOne($a, $b) {
return new static($a, $b);
}
See http://php.net/manual/en/language.oop5.late-static-bindings.php.
You may use ReflectionClass::newInstance
http://ideone.com/THf45
class A
{
private $_a;
private $_b;
public function __construct($a = null, $b = null)
{
$this->_a = $a;
$this->_b = $b;
echo 'Constructed A instance with args: ' . $a . ', ' . $b . "\n";
}
public function construct_from_this()
{
$ref = new ReflectionClass($this);
return $ref->newInstance('a_value', 'b_value');
}
}
$foo = new A();
$result = $foo->construct_from_this();
Try using get_class(), this works even when the class is inherited
<?
class Test {
public function getName() {
return get_class() . "\n";
}
public function initiateClass() {
$class_name = get_class();
return new $class_name();
}
}
class Test2 extends Test {}
$test = new Test();
echo "Test 1 - " . $test->getName();
$test2 = new Test2();
echo "Test 2 - " . $test2->getName();
$test_initiated = $test2->initiateClass();
echo "Test Initiated - " . $test_initiated->getName();
When running, you'll get the following output.
Test 1 - Test
Test 2 - Test
Test Initiated - Test