Amend PHP Object properties on the fly [duplicate] - php

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
In PHP how can I access a “:private” array in an object?
I am not sure if there is a right way to do this or if this is completely unacceptable technique.
I am using PHP and I am in a situation where a script is given an object, it does not have access to the objects Class and many of the properties are protected (see below).
Is it possible to "hack" (bad choice of words) the object manually to amend property values on the fly?
Not sure of a way to do this or if there is a way by converting one way and then back again.
object(__PHP_Incomplete_Class)#3 (16) {
["__PHP_Incomplete_Class_Name"]=>
string(28) "Zend_Controller_Request_Http"
["_paramSources":protected]=>
array(2) {
[0]=>
string(4) "_GET"
[1]=>
string(5) "_POST"
}
["_requestUri":protected]=>
string(13) "/?mod=mainnav"
["_baseUrl":protected]=>
NULL
["_basePath":protected]=>
NULL
["_pathInfo":protected]=>
string(0) ""
["_params":protected]=>
array(0) {
}
["_rawBody":protected]=>
NULL
["_aliases":protected]=>
array(0) {
}
["_dispatched":protected]=>
bool(false)
["_module":protected]=>
NULL
["_moduleKey":protected]=>
string(6) "module"
["_controller":protected]=>
NULL
["_controllerKey":protected]=>
string(10) "controller"
["_action":protected]=>
NULL
["_actionKey":protected]=>
string(6) "action"
}

If properties are protected you can create a class that extends from this one and modify any properties. If they are private look at Reflection:
$reflecRequest = new ReflectionObject($request);
$reflecRequestProp = $reflecRequest->getProperty('_requestUri');
$reflecRequestProp->setAccessible(true);
$reflecRequestProp->setValue($request, 'newUri');

Ended up using a more simple technique to do this.
I have the Object serialized into a string. So I simply replaced the current value (which I always have) with the new value using preg_replace.
There is some regex which will find the variable name and then I could change its value (so doesn't require knowing the value) but I hadn't been able to complete that yet (and I do have the current value).
$objectA = serialize($request);
$current_url = '\?mod=mainnav';
$new_url = 'newpage';
$objectB = preg_replace('/'.$current_url.'/', $new_url, $objectA);
//check the new object
var_dump('<pre>');
var_dump(unserialize($objectB));
var_dump('</pre>');
Using Reflections is probably the better technique most of the time, but for what I needed here I felt this was an simple and fast way to do it plus keeps all other object properties.

Related

Accessing an array that is part of an object seems to fail

I have the following code snippet that doesn't do what I expect:
var_dump($pronunciationResults);
$alignEntries = $pronunciationResults->alignEntry;
var_dump($alignEntries);
Which produces for the first var_dump (I have elided out the end of the structure):
object(SimpleXMLElement)#1371 (1) {
["alignEntry"]=>
array(123) {
[0]=>
object(SimpleXMLElement)#1375 (3) {
["#attributes"]=>
array(1) {
["alignType"]=>
string(2) "OK"
}
["target"]=>
string(3) "The"
Followed by the output of the second var_dump
object(SimpleXMLElement)#1373 (3) {
["#attributes"]=>
array(1) {
["alignType"]=>
string(2) "OK"
}
["target"]=>
string(3) "The"
I have a really simple php program that works exactly as expected, and have no idea why in this case I get the first element of the array, rather than the array itself.
So the comment below by #trincot was interesting. However:
var_dump($pronunciationResults->children());
var_dump($pronunciationResults->children()->alignEntry);
var_dump($pronunciationResults->alignEntry->children());
Gives the exact same structure as I got above for each of the var_dump.
It turns out the foreach does walk the original alignEntries array, even though var_dump doesn't show it as an array.
I have no idea what is going on with var_dump
Your objects are not standard objects. You should use them using the appropriate API. In case of an instance of SimpleXMLElement, you can get the children array via the method children():
foreach ($pronunciationResults->children() as $child) {
var_dump($child);
}
Of course, since also those child elements are of the SimpleXMLElement class, you should also treat those via the proper methods. So if you would want to iterate over their attributes, then call the attributes() method on them, ...etc.
Do not focus on what you see in var_dump, except for the class. You'll see undocumented properties which are not supposed to be used directly. Stick to the documented interface for those objects.

How to convert the string representation of array to normal array

I have string representation of an array in a file. I need to convert it to array . How to achieve this.
For example
$arr = 'array(1,2,3,4,5,6)';
echo getType($arr); // string
//convert $arr to type array
echo getType($arr); // array
It depends on if the file is made up entirely of valid PHP. If it is you could just include the file. Otherwise, given that this string is valid PHP you could eval the string, though typically this is viewed as bad solution to almost any problem.
If the entire file is valid PHP and you just want the array in another script use include.
somefile.php
return array(1,2,3,4,5,6);
someotherfile.php
$arr = include 'somefile.php';
var_dump($arr);
This gives you...
array(6) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
[5]=>
int(6)
}
I don't know if the string format is fixed or not.
If not you could look at serialize() and unserialize().
The other approach, assuming the format is as written, would be to execute the file, through require or include, rather than read it as a string. That would create the variable in your context. There are a few little issues with this approach, such as enclosing tags, but perhaps that is resolvable in your situation.
Lastly I found this approach as well: Execute PHP code in a string. This is an improved variant of my second approach.
Use php-array-parser.
But it's not working well with different types of tokens in the same time, e.g. "array()" and "[]".

Error "Cannot use object of type stdClass as array" when accessing a clearly existing, integer type data from Laravel Database query result

I got my data from Laravel database query command:
$group = DB::table('groups')->where("id", $group_id)->first();
When I var dump my data, I get:
object(stdClass)#200 (7) {
["id"]=>
int(1)
["levels_id"]=>
int(1)
["title"]=>
string(8) "Novice 1"
["description"]=>
string(11) "Lorem Ipsum"
["max_question_display"]=>
int(5)
["created_at"]=>
NULL
["updated_at"]=>
NULL
}
I want to access the max_question_display. But when I do:
var_dump($group["max_question_display"]);
PHP returns error Cannot use object of type stdClass as array.
When I do:
var_dump($group->max_question_display);
I get:
int(5)
But I don't want the int. I only want the 5. In integer form.
If I foreach loop the $group:
foreach ($group as $t) {
echo "<pre>";
var_dump($t);
echo "</pre>";
}
I get each of the data as a single data each loop.
int(1)
int(1)
string(8) "Novice 1"
string(11) "Lorem Ipsum"
int(5)
NULL
NULL
This is obviously also not the way the result accessed that I'm looking for.
I also tried to get the first element of array, thinking that this might be an array with 1 element, but that also raise the same error.
I get it that the general answer in this site about this error is that "stdClass is not array". I have browsed several question with similar title like mine, but nothing address object that came from Laravel DB. When I read the manual on Laravel DB, I was assured that I can access the data returned like a simple dictionary / hashmap.
EDIT: Sorry, I understand my very, very newbie mistakes. No need to answer this. Thanks.
Notice the first line of your first var_dump:
object(stdClass)#200
Because you're dealing with an object, you access its properties with ->. When you do:
var_dump($group->max_question_display);
The reason you see (int) in the output is that the var_dump function shows the value type, next to the value. To access the value, do
$group->max_question_display;
If you want to see it on screen without the type, use echo
echo $group->max_question_display; // 5
stdClass is an object. You cannot use an object with array syntax to access its properties, if the class does not implement ArrayAccess interface.
As pointed out by #IbrahimLawal , var_dump outputs both the type and value. Just echoing $group->max_question_display will provide just the value
echo $group->max_question_display; // 5
In Summary: You must use arrow syntax when interacting with stdClass.

Retrieve value from an object

I have an object and like to retrieve the value of one or more elements from the object. Hire is one of the objects if put in a var_dump().
object(SimpleXMLElement)#13 (2) {
["#attributes"]=>
array(1) {
["name"]=>
string(5) "chain"
}
["value"]=>
string(11) "Abba Hotels"
}
I get the value but i can not get to the name.
To get the value i use for example:
echo $row->property->value
My first thought was to use:
echo $row->property->#attributes->name
, but it return as a ERROR. I try to use #attributes in a variable but that gives a NULL.
At second thought i tried to use get_object_vars() and in_array() but no luck again.
Do you guys have a idea about how i can get to the value of the "name" object?
See the docs for SimpleXMLElement:
$object->attributes()
Will give you what you need. I.e.
echo $object->attributes()->name;
It looks like you are using a property value from somewhere. If $row is the object, then you could use this I think.
$row->#attritubes['name']
Im not fully sure but thought id give it a go helping anyawy. Let me know if it works.

Facebook Stream.Get -- How to access data in array?

On stream.get, I try to
echo $feeds["posts"][$i]["attachment"]["href"];
It return the URL, but, in the same array scope where "type" is located (which returns string: video, etc), trying $feeds["posts"][$i]["attachment"]["type"] returns nothing at all!
Here's an array through PHP's var_dump: http://pastie.org/930475
So, from testing I suppose this is protected by Facebook? Does that makes sense at all?
Here it's full: http://pastie.org/930490, but not all attachment/media/types has values.
It's also strange, because I can't access through [attachment][media][href] or [attachment][media][type], and if I try [attachment][media][0][type] or href, it gives me a string offset error.
["attachment"]=> array(8) {
["media"]=> array(1) {
[0]=> array(5) {
["href"]=> string(55) "http://www.facebook.com/video/video.php?v=1392999461587"
["alt"]=> string(13) "IN THE STUDIO"
["type"]=> string(5) "video"
My question is, is this protected by Facebook? Or we can actually access this array position?
Well, once the data is returned to you, it can no longer be protected by Facebook. You have full access to everything in that result as a regular data structure.
From the looks of it, there are multiple href properties throughout, so you'll want to be careful which one you're going for. $feeds["posts"][$i]["attachment"]["href"] is a valid element for some items, but $feeds["posts"][$i]["attachment"]["media"][0]["href"] is also a valid element.
There doesn't appear to be a $feeds["posts"][$i]["attachment"]["type"] element though, so that's why you're getting nothing for that particular item. There is a type inside ["attachment"]["media"][0] however, which is probably what you want.
If you are getting a string offset error when using array syntax, you've probably mixed up an element somewhere. Strings can be accessed via array syntax. For example:
$str = "string";
echo $str[1]; //echos 't'
You would get an offset warning if you tried to access an index that was larger than the string. In any case, from the looks of that output, $feeds["posts"][$i]["attachment"]["media"][0]["type"] should work.

Categories