This is a syntax question I think... I have an array of classnames, that I use in a factory to generate objects by object type code:
$array = ['a' => '\namespace\AClass', 'b' => '\namespace\BClass'];
I can instantiate these classes from the string name just fine:
$classname = $array['a'];
return new $classname($arg1, $arg2);
What I am trying to do is call a static method of the class named in the array or string, without having to initialize the object - something like:
$classname = $array['a'];
return $classname::formatArg($arg1);
Obviously, this doesn't work since $classname is a string, so how do I tell PHP I am trying to access the object with that name?
Check out this post. How can I call a static method on a variable class?
It look like your code is ok in php 5.3. There's also some ideas how to deal with your problem if you are < 5.3.
Related
I have 2 classes MyClass and MyClass2. I need to call a new instance of MyClass using reflection, passing to the constructor an instance of MyClass2. This works fine until I try using the reference in MyClass2 constructor, $classObject in this case will be null.
Why is this problem occurring? Knowing that this does not happen while testing a similar function call between two function within the same class without reflection!!
$className = 'MyClass';
$args = array(new MyClass2());
$classReflection = new ReflectionClass($className);
$classObject = $classReflection->newInstanceArgs($args);
MyClass
public function __construct(&$myClass2)
The straightforward solution is to modify MyClass's constructor so it no longer requires a reference:
public function __construct($myClass2) { }
As deceze notes in his comment above, there's generally no need to pass objects by reference; they are always passed by object identifier, which functions as a pointer and ensures all variables to which an object is assigned operate directly on that object's data.
However, your example illustrates some unusual behaviour in PHP. Like vuliad says, your code as written fails on PHP 7 with this warning:
PHP Warning: Parameter 1 to MyClass::__construct() expected to be a reference, value given
This is surprising, because the PHP manual says,
Since PHP 5, new returns a reference automatically...
So $args should hold an array that contains a reference, as MyClass's constructor expects. But the only way I can get your original code to work is by first assigning the new instance of MyClass2 to a variable, like this:
$newClass2 = new MyClass2();
$args = array(&$newClass2);
$classReflection = new ReflectionClass($className);
$classObject = $classReflection->newInstanceArgs($args);
This is a solution, too. But again, passing objects by reference is unnecessary, so I recommend simply changing the MyClass constructor.
You can do this via arguments unpacking:
$classObject = new $className(...$args);
This is really interesting case, for php7.0+ we can see Error:
Warning: Parameter 1 to MyClass::__construct() expected to be a reference, value given in /in/Bgjlj on line 15
try here https://3v4l.org/Bgjlj
i get a resultset from a class that manages WSDL Data.
I didn't write the code to the class, i only use it.
I call a function to create an ID with the service and want to work with that ID later in the same script.
My Resultset looks like this:
Array
(
[0] => SaveResult Object
(
[id:protected] => newgeneratedID
[success:protected] => 1
)
)
So I tried $response[0]->id to get the ID i need.
Now I get a fatal error.
PHP Fatal error: Cannot access protected property SaveResult::$id
I know it´s a noob question, but I don't get why I can print_r the object but not get the values inside.
You cannot use any of protected data from another space except the same object.
But you can edit the SaveResult object and add getter for id:
public function getId() {
return $this->id;
}
There ought to be a method you can call in the SaveResult class which lets you access the data, something like:
$response[0]->getId();
See the documentation/source code of the class.
You can read a protected property with the ReflectionProperty interface.
The HandyMan component from the phptoolcase library has a handy method to read inaccessible objects properties.
$value = PtcHandyMan::getProperty( $your_object , 'propertyName');
Static property from a singleton class:
$value = PtcHandyMan::getProperty( 'myCLassName' , 'propertyName');
Very simple and usefull, though it is only adviced in few situations as protected/private properties are shouldn't be used outside of their scope.
You can find the HandyMan class here: http://phptoolcase.com/guides/ptc-hm-guide.html
When I call this function, and add a constructor to my class, all my class properties are already set. How is that possible -- I thought you had to construct a class before you could set its properties?
I guess that PDO uses some internal code to create an object without invoking the constructor. However it is possible to instance a new object without calling the constructor even in pure PHP, all you have to do is to deserialize an empty object:
class SampleClass {
private $fld = 'fldValue';
public function __construct() {
var_dump(__METHOD__);
}
// getters & setters
}
$sc = unserialize(sprintf('O:%d:"%s":0:{}', strlen('SampleClass'), 'SampleClass'));
echo $sc->getFld(); // outputs: fldValue, without calling the construcotr
As of PHP 5.4.0+ ReflectionClass::newInstanceWithoutConstructor() method is available in reflection API.
In php, any array can be cast to an object. My assumption is pdo creates an associative array an then jus casts it. I dont know if he constuctor is called on cast...
Actually, a cast isnt the right word, a conversion occurs behind the scenes. Read this. Blurb on what happens: http://php.net/manual/en/language.types.object.php
Here's what I want to do:
public function all($model) {
$query = 'SELECT ' . implode(', ', $model::$fields) ....;
}
Called like this:
$thing->all(Account);
I get this error:
Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM in /home/mark/public_html/*/account.php on line 15
When inspecting $model with var_dump it turns out its a string. In the the first example if I change $model to Account on the $query line it works fine.
How can a take a string and turn it back into a class?
Edit: Updated example and title to reflect the problem isn't with self.
Solution: Since I'm not using PHP5.3, I had to resort to using eval() to get what I wanted. Thanks everybody!
Classes are not first-class citizens in PHP, as such they may not be stored in variables, passed as function arguments, or returned from functions.
However, PHP will let you simulate a first-class citizen by using a string containing the name of the class, in certain situations:
$class = "Account";
$instance = new $class(); // You can create instances
call_user_func(array($class, 'frobnicate')); // You can call static functions
That's about all in PHP < 5.3. However, with PHP 5.3, you can also:
$class::frobnicate(); // cleanly call static functions
$fields = $class::$fields; // access static variables
I have also experienced receiving such Fatal Error: Class 'MyClass' not found when you're class has a specific namespace, then it's probably the namespacing. You need to also mention the namespace in your String variable.
$class = "App\MyClass"; // mention the namespace too
$instance = new $class();
See Wikipedia on the scope resolution operator. Especially see the section on PHP and Hebrew.
You cannot use self this way : it can only be used in a static context (i.e. inside a static method) to point to the class -- and not its name.
If you are working with non-static methods (seems you are), you should use $this, instead of self.
Actually, before PHP 5.3, you cannot use a static method/data with a "dynamic" (i.e contained in a variable) class name -- see the examples on the page Static Keyword : they only work with PHP 5.3, for that kind of manipulation.
Which means a portion of code like this one :
class ClassA {
public static $data = 'glop';
}
$className = 'ClassA';
var_dump($className::$data);
Will not work with PHP < 5.3
I find this similar line works in my Laravel app:
$thing->all(new Account);
Try '$this' instead of self.
Self does work this way in PHP. PHP thinks it encounters an unknown constant, which it can't find, and then it assumes it's a string containing 'self'.
Edit: Can you post the class and the code where you instantiate the object?
Is there any way to call a php class (eg. $var = new className) and have var store the value returned by the className function?
Or, is there a way to call a class and not have it execute the function with the same name?
The function of the same name as the class was they way 'constructors' in php 4 worked.
This function is called automatically when a new object instance is created.
In php 5, a new magic function __construct() is used instead.
If your using php5 and don't include a '__construct' method, php will search for an old-style constructor method.
http://www.php.net/manual/en/language.oop5.decon.php
So if you are using php5, add a '__construct' method to your class, and php will quit executing your 'method of the same name as the class' when a new object is constructed.
It is possible in PHP5 using magical method __toString(); to return a value from the class instance/object.
simply
class MyClass{
function __construct(){
// constructor
}
function __toString(){
// to String
return 5;
}
}
$inst = new MyClass();
echo $inst; // echos 5
Constructors don't return value (in fact you can't do that). If you want to get a value from the instance of the class, use the __toString() magical method.
Constructors don't return values, they are used to instantiate the new object you are creating. $var will always contain a reference to the new object using the code you provided.
To be honest, from your question, it sounds like you don't understand the intention of classes.
$var = new classname will always return an instance of classname. You can't have it return something else.
Read this...
http://www.php.net/manual/en/language.oop5.php