Is there a way to get all the methods of an instantiated standard class object? I'm talking about an object that has some methods and properties on it, not a fresh stdClass object. ReflectionClass seems to work only on classes.
Try get_class_methods(), sounds like what you're describing, if I understand you correctly.
You can use get_object_vars to get a list of all of the properties, and then iterate over them (or array_filter them) and determine which of them is_callable:
$myClass = new StdClass;
$myClass->someFunc = function($a) {
return $a - 1;
};
$myClass->someProperty = 42;
$properties = get_object_vars($myClass);
$methods = array_filter($properties, 'is_callable');
I'm not sure if it's my 5.4.39 version of PHP or not, but using the above example and instead doing var_dump(get_class_methods($myClass)); as #Mike suggested returns an empty array.
Related
Here is my code: Demo
class myclass1 {
public $myvariable;
}
$obj1 = new myclass1;
$obj2 = $obj1;
$obj1->myvariable = 'something';
echo $obj2->myvariable; //=> something
As you see, I've initialized something to the first object, but surprisingly it will be also applied on the second object. Why really? Actually I need to have two different value in $myvariable for both classes, not the same value.
How can I do that?
That's how OOP works. Actually all you need to know is about pass-by-reference. Take a look at this:
In your code, both $obj1 and $obj2 are using same memory point. So any change on $obj1 will be seen also on the $obj2. To separate them from each other you need to use clone:
$obj2 = clone $obj1;
By cloning an object you are actually making a copy of it. So the new object won't refer to the old one.
I've created an object factory where I pass the object name as the first parameter and then an array of dependencies as the second parameter. I already have it working but but I feel there has to be a simple php function to allow for the dynamic instantiation of the object.
$shinyObject = ObjectFactory::get('Model\MyObject', array('\lib\DependencyOne', '\lib\DependencyTwo'))
The purpose of this factory is to retrieve an object thats serialized in session if it exists, if not then create a new instance of the object and then save in session. I want to know if there is a php function to instantiate a new object dynamically with dependencies.
As far as I understand, what you're looking after is a dependency injection framework.
PHP doesn't offer such thing out of the box.
There are, however, nice external libraries such as PHP-DI that provide this kind of functionality. Since you already created such library yourself, I don't think you're going to need it, but I think it was worth mentioning anyway - you can look at how some things are done (for instance, how to deal with singletons, etc.).
The nice thing about PHP-DI is that objects themselves specify what they need, and main object factory takes care of everything, by constructing a map of dependencies (perhaps that is what you meant by "easier" approach - you don't actually need to pass list of dependent objects in PHP-DI).
If I were to make such thing myself, I'd implement ObjectFactory::define($key, array $deps) that would be called once per object, and then use just ObjectFactory::get($key) whenever I need, without having to know anything about $$key's dependencies.
Just use new keyword:
$foo = 'Bar'
$bar = new $foo;
or you can generate a string and use eval().
Edit
In response to Justin Kiang's concerns, here is an example:
class A
{
}
class Foo
{
public $a;
public function __construct(A $a)
{
$this->a = $a;
}
}
function create($class, array $dependencies)
{
$str = "\$bar = new $class(";
foreach ($dependencies as $dependency)
{
$str .= "unserialize('" . serialize($dependency) . "'), ";
}
$str = trim($str);
$str = trim($str, ",") . ");";
eval($str);
return $bar;
}
$a = new A;
var_dump(create('Foo', [$a]));
It results as follows:
object(Foo)[2]
public 'a' =>
object(A)[3]
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
Is there a simple way to remove a member from an object? Not just set it to null, but actually remove it.
Thanks! :)
Edit: I've already tried unset(), and setting the member variable to null obviously doesn't work. I suppose I could convert the object to an array, then remove the array key in question, and convert back to an object, but blech... There's got to be an easier way!
You are using RedBean. Just checked it out. And these bean objects don't have actual properties.
unset($bean->field);
Does not work, because ->field is a virtual attribute. It does not exist in the class. Rather it resides in the protected $bean->properties[] which you cannot access. RedBean only implements the magic methods __get and __set for retrieving and setting attributes.
This is why the unset() does not work. It unsets a property that never existed at that location.
$obj = new stdClass;
$obj->answer = 42;
print_r($obj);
unset($obj->answer);
print_r($obj);
Works fine for me. Are you sure you 're doing it right?
Update:
It also works for properties defined in classes:
class Foo {
public $bar = 42;
}
$obj = new Foo;
print_r($obj);
unset($obj->bar);
print_r($obj);
within you object you can define a magic method called __unset
class Test
{
public $data = array();
public function __unset($key)
{
unset($this->data[$key]);
}
}
And Jon summed up the other factors nicely.
RedBean has a removeProperty method on beans.
Possibly unset().
No you cannot, nor in the Runkit module do I see a way to accomplish that, even if ways to remove methods/functions/constants exist.
With RedBean 4 you can use
unset($bean->someproperty);
Do you want to unset the property merely because you do not want it stored in the database?
If so, just declare the property as private in the class.
Kudos to this answer: Not saving property of a php-redbean to database
So by implementing Iterator, ArrayAccess, and Countable built-in interfaces, we have control over what happens inside an object when it's used in foreach loops or if a property is accessed as if it were an array index ($object['id']).
For example, if you wanted, you could set it up so $object['version'] += 1 could automatically increment version field in the database.
What's missing is casting the object to array. Is there any interface or class that allows control over what happens when you do: (array) $object? Any built-in interface or class at all, no matter how obscure? For example: if I wanted (array) $object to return $this->propertyArray instead of the normal object to array conversion of dumping all public object properties?
Note: something like requiring calling $object->toArray() by method name doesn't count, as the idea is to minimize the outside differences between an array and object as much as possible.
no there is not , because toArray() is not an magic function like __toString(); where casting works e.g
$foo = (string) $myObect;
you have to specify toArray() and inside it return your array , may be in future __toArray() might come.
You could add a method like this
public function toArray() {
return get_object_vars( $this );
}
See here. Or check SplFixedArray::toArray.