Static Method call from unknown object - php

I want to call a static method from one of my objects. This is no problem if I know the name of the object, but in this case, I don't.
I have an array with several object names and I want to call the method from one of this arrays elements. So, it looks something like this:
function call_method($key) {
$tmp = array('key1' => 'objectname1','key2' => 'objectname2','key3' => 'objectname3');
if(array_key_exists($key, $tmp)) {
$tmp::static_method();
}
}
But, this solution is not working. Does somebody know how to get this working?

$tmp is an array, so it has no static methods associated with it. You need to look up the value and use that:
// this will work for newer versions of PHP
$klass = $tmp[$key];
$klass::static_method();
// in some older versions, you may need to use call_user_func:
call_user_func(array($klass, 'static_method') /*, your args here */);

Right now, you are trying to call the static function on that array. You should do :
if(array_key_exists($key, $tmp)) {
$tmp[$key]::static_method();
}
Thought you specified the names "object" in the array, I am assuming they are class names. Static functions cannot be called with instances.

Related

Class-Wide accessible static array, trying to push to it, but keeps coming back empty

class UpcomingEvents {
//Variable I'm trying to make accessible and modify throughout the class methods
private static $postObjArr = array();
private static $postIdArr = array();
private static $pinnedPost;
//My attempt at a get method to solve this issue, it did not
private static function getPostObjArr() {
$postObjArr = static::$postObjArr;
return $postObjArr;
}
private static function sortByDateProp($a, $b) {
$Adate = strtotime(get_field('event_date',$a->ID));
$Bdate = strtotime(get_field('event_date',$b->ID));
if ($Adate == $Bdate) {
return 0;
}
return ($Adate < $Bdate) ? -1 : 1;
}
private static function queryDatesAndSort($args) {
$postQuery = new WP_Query( $args );
if( $postQuery->have_posts() ) {
while( $postQuery->have_posts() ) {
$postQuery->the_post();
//Trying to push to the array, to no avail
array_push(static::getPostObjArr(), get_post());
}
}
//Trying to return the array after pushing to it, comes back empty
return(var_dump(static::getPostObjArr()));
//Trying to sort it
usort(static::getPostObjArr(), array(self,'sortByDateProp'));
foreach (static::getPostObjArr() as $key => $value) {
array_push(static::$postIdArr, $value->ID);
}
}
}
I'm trying to access $postObjArr within the class, and push to it with the queryDatesAndSort(); method. I've tried a couple of things, most recent being to use a get method for the variable. I don't want to make it global as it's bad practice I've heard. I've also tried passing by reference I.E
&static::$postObjArr;
But when it hits the vardump, it spits out an empty array. What would be the solution and best practice here? To allow the class methods to access and modify a single static array variable.
static::$postObjArr[] = get_post()
I didn't think it would of made a difference, but it worked. Can you explain to me why that worked but array.push(); Did not?
Arrays are always copy-on-write in PHP. If you assign an array to another variable, pass it into a function, or return it from a function, it's for all intents and purposes a different, new array. Modifying it does not modify the "original" array. If you want to pass an array around and continue to modify the original array, you'll have to use pass-by-reference everywhere. Meaning you will have to add a & everywhere you assign it to a different variable, pass it into a function, or return it from a function. If you forget your & anywhere, the reference is broken.
Since that's rather annoying to work with, you rarely use references in PHP and you either modify your arrays directly (static::$postObjArr), or you use objects (stdClass or a custom class) instead which can be passed around without breaking reference.

How to receive specific interface's array in PHP class method?

I want to receive array of MyInterface as the in the below code.
public function saveMultiple(
\Path\To\MyInterface $attachLinks[]
);
The above code doesn't work.
So please don't tell me that just remove \Path\To\MyInterface and to use a variable $attachLinks. I'm already aware of that but this is something which I require.
There are no generic types in php, so you can not specify type «array of something».
But you may do a trick. Check types of elements in array.
array_walk($attachLinks, function (\Path\To\MyInterface $item) {});
If you wrap it in assert, you will be able to disable this check.
assert('array_walk($attachLinks, function (\Path\To\MyInterface $item) {})');
So far this is what can be done using PHP7. Till date passing arrays with specific type is not possible.
public function saveMultiple(
array $attachLinks
);
It'll now at least make sure that the method only gets array as parameter.
Maybe you can use some type of setter like:
private $attachLinks = [];
public function setter(MyInterface $var)
{
$this->attachLinks[] = $var;
}
And than use a $this->attachLinks in your function
public function saveMultiple() {
print_r($this->attachLinks);
}

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?

Symfony 2 / Php : json_encode

I've been looking to a solution to my problem for a while without success so I'm asking here.
How can we return a json-encoded result on an array of objects (or just an object) containing private properties ?
Indeed, when you use json_encode($myObject), it won't display the private or protected properties, which are present everywhere in the model when using Symfony...
I'm surprised I couldn't find any method like json_encode that would call getters instead of properties themselves.
Any idea ?
EDIT
In that case I would rather do a unique function that looks like :
public function toArray() {
$vars = get_object_vars($this);
$result = array();
foreach ($vars as $key => $value) {
if (is_object($value)) {
$result[$key] = toArray($value);
} else {
$result[$key] = $value;
}
}
return $result;
}
in order to avoid rewriting every property name everytime...
But anyway I think I'll just create an array containing the vars I need, so that I won't touch the model (which is generated code).
Have you try GetSetMethodNormalizer ?
http://api.symfony.com/2.0/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.html
Ex. https://stackoverflow.com/a/6709828/520114
Right now there is no way for this. Only php serialize/unserialize handles the true serialisation of objects.
You'll have to implement them yourselve, or rather let objects return their json values themselves.
You will have to implement your own method toArray() where you expose all your private values in an array:
public function toArray()
{
return array(
'property1' => $this->myproperty1,
'property2' => $this->myproperty2
);
}
And call it like this:
json_encode(MyObject->toArray());
[Edit: this question is not about doctrine, but since you mention both symfony2 and the model, you can consider using Array Hydration for your model: http://www.doctrine-project.org/docs/orm/2.0/en/reference/dql-doctrine-query-language.html#array-hydration ]

php arrays with only one type

I'm looking to create an array or list with elements of a certain type (eg objects the implement a certain interface). I know I can create an object that does the same thing implementing Traversable and Iterator, or override ArrayObject. But maybe there's another way I have missed.
Do you mean something like:
$array=Array();
foreach ($itemsToAdd as $item) {
if ($item instanceof NameOfwantedInterface) {
Array_push($array,$item);
}
}
If you don't, them I'm sorry - it's just that your question isn't too clear.
I would write a custom class that extended ArrayObject and threw an exception if you tried to assign a variable that wasn't the correct type, there's really no better way to do it that I can think of.
PHP as a lanugage is very flexible in terms of type handling and type conversion. You will probably have to put a manual check in if you want any kind of strong type checking, a simple if statement will do.
The array object is designed to be especially flexible (lazy key assignment, automatic increment, string or integer keys, etc.) so you should probably use a custom object of your own.
You could use type hinting:
<?php
interface Shape
{
function draw();
}
class MyArray
{
private $array = array();
function addValue(Shape $shape) //The hinting happens here
{
$array[] = $shape;
}
}
?>
This example is not perfect, but you'll get the idea.
Basically, you are going to want to do a function that checks if the variable you are inserting into the array is an object.
function add($var)
{
if(is_object($var))
{
$this->array[] = $var;
}
}
If you want to make sure it has a specific class name, you would do something like this (for PHP5):
function add(className $var)
{
$this->array[] = $var;
}
or this for previous PHP versions:
function add($var)
{
if($var instanceOf className)
{
$this->array[] = $var
}
}
You might want to look into array_filter() to do this without building an object.
Looking at that page, I've found that you can use array_filter with common functions like is_object. So doing something like this:
$this->array = array_filter($this->array ,'is_object');
Would filter the array to contain only objects.

Categories