I know there is alot of information available in regards to PHP - var_dump my question is if I need to pick the particular information from the dump I am receiving from the API which is returning different array object....for example the below dump I need the information of realm under characterData Array how can I pick the that information and stored in String variable. Brief example of php code to explain my question will be highly appreciated...
object(Character)[3]
private 'name' => string 'XXXX' (length=6)
private 'region' => string 'eu' (length=2)
private 'realm' => string 'Defias Brotherhood' (length=18)
private 'characterData' =>
array (size=24)
'lastModified' => float 1363345999000
'name' => string 'Growar' (length=6)
'realm' => string 'Defias Brotherhood' (length=18)
'battlegroup' => string 'Rampage / Saccage' (length=17)
basically this information is coming from battlegroup api
$armory = new BattlenetArmory('EU','Defias Brotherhood');
$armory->setLocale('ru_RU');
// To reset back to default server locale
$armory->setLocale(FALSE);
//initialize the character to get the character object
$character = $armory->getCharacter('XXXX');
If you don't have a getter for the field characterData, you won't have access to it because it is a private property, unless you use Reflection:
$ref = new ReflectionClass( 'Character');
$prop = $ref->getProperty( 'characterData');
$prop->setAccessible( true);
$array = $prop->getValue( $yourCharacterObject);
echo $array['realm'];
This can be tested with a simple class that mimics the OPs:
class Character {
private $characterData;
public function __construct() {
$this->characterData['realm'] = 'Defias Brotherhood';
}
}
Currently, others have the proposed this solution:
$yourCharacterObject = new Character();
// echo $yourCharacterObject->characterData['realm'];
Which results in:
Fatal error: Cannot access private property Character::$characterData in X on line 11
However, Reflection will be able to grab the private value and display it without error, as shown in this demo, which uses the above class and code to print the desired property value.
Character is a class that you create instance from - for example:
$c = new Character();
since characterData is private you can't access it via $c->characterData
You need to use some public access function (like getCharacterData) or if you have access inside the object just changed it according to your needs
Related
I have a class within which I want to
Set an array
Loop through the array
Invoke anonymous functions set in #1 as I loop through the array in #2
EDIT: The code below is working when tested out of my application, but in my CodeIgniter 3 Controller, I keep getting an error: Method name must be a string
My simplified code for the purposes of example (CodeIgniter 3):
<?php
class MyClass {
// Setting my array
public function my_arr ($options = array())
{
$arr = array(
'1' => array(
'a' => 'z',
'b' => function($i) {
return 'c' . $i;
},
),
'2' => array(
'a' => 'y',
'b' => function($i) {
return 'd' . $i;
},
),
);
return $arr;
/**
*
* EDIT: Later in my code I found that there was some kind
* of serialization/encoding attempt like:
* json_decode(json_encode($arr));
*/
}
// Doing My Loop
public function do_loop()
{
$my_arr = $this->my_arr();
$i = 0;
foreach($my_arr as $key => $value){
$anonymous_function = $value['b'];
echo $anonymous_function($i) . '<br>'; // Keep getting `Method name must be a string`
$i++;
}
}
}
(new MyClass())->do_loop();
Posting back here in hopes that it helps.
My issue:
Later on in my codebase, I was trying to encode/serialize my method's
output.
After a bit of reading, I found out that json_encode() &
serialize() don't support serialization of closures / anonymous functions.
So, the Method name must be a string error happend because my attempts to encode/serialize - effectively - stripped the anonymous functions out & thus referenced a null function.
How I resolved the issue:
First I started with Opis Closure library to seralize the closure (I didn't end up going with this, but including it because I think it's a pretty cool library)
After the above, I just realized that I should refactor so that I wasn't trying serialize closures at all.
In PHP, I'm requesting data from my QuickBooks Online account using their Query functions.
I'm iterating through each customer object that is returned in a standard foreach($customer as $x) code block.
Using var_dump, I can tell each object has the following format:
object(QuickBooksOnline\API\Data\IPPCustomer) [34]
public 'Taxable' => string 'true' (length=4)
public 'BillAddr' =>
object(QuickBooksOnline\API\Data\IPPCustomer) [78]
public 'Id' => string '7509' (length=4)
public 'Line1' => '1234 Irrelevant Dr.' (length=19)
In PHP, if I simply try to access $x->Taxable, it works no problem, but any sub-object I try to access returns an error: "trying to get property of non-object on line X"
So:
echo $x->Taxable;
gives me the taxable status, but
echo $x->BillAddr->Line1;
gives me an error.
These are public classes, so shouldn't I be able to call them like this?
Found the problem and I have no idea why this is required, but here's how I got it to work, adding curly braces:
echo "{$x->BillAddr->Line1}"; instead of just echo "$x->BillAddr->Line1";
Same rule applies to assignment as well, apparently:
$line1 = "{$x->BillAddr->Line1}";
Thanks for your help, guys!
It is common in php to store config data in arrays, and that is read only. Has someone made utility to make possible to save changes to array direct in source? I don't mean serializing array to some file but update value in source where it was read.
This is how I manipulate and save the state of config arrays.
Here I create a config array (but let's assume you already have one in the same format), I write it. Then next I read it in, make an edit and save back to the file.
Adjust to your liking.
<?php
function write_config($config, $path) {
file_put_contents($path, '<?php return ' . var_export($config, true). ';');
}
function read_config($path)
{
return include $path;
}
$config_path = '/tmp/config.php';
$config = array(
'foo' => 'bar'
);
write_config($config, $config_path);
$config = read_config($config_path);
var_dump($config);
$config['foo'] = 'baz';
write_config($config, $config_path);
$config = read_config($config_path);
var_dump($config);
Output:
array (size=1)
'foo' => string 'bar' (length=3)
array (size=1)
'foo' => string 'baz' (length=3)
I usually have a base array set with defaults, and have another array for adjustments that I use to override the first. I use array_merge_recursive to apply the latter over the first.
Hi all i have a function in a class which will print all the variable pass for this function
Class Code :
<?php
class MyPrintClass {
public function printVaraible() {
var_dump(func_get_args())
}
}
$printVar = new MyPrintClass;
?>
if i use like below its correctly working and printing all the values pass.
$print->printVaraible('value1','Value2',20);
The output i got for above cmd
array (size=1)
0 => string 'value1' (length=6)
1 => string 'value2' (length=6)
2 => string 'value3' (length=6)
if i use like blow its showing as a single array.. i want the value seperated.. how its possible ?
function getVal(){
global $printVar;
$print->printVaraible(func_get_args());
}
I need to pass the value like below
getVal('value1','Value2',20);
and i need the output as
array (size=1)
0 => string 'value1' (length=6)
1 => string 'value2' (length=6)
2 => string 'value3' (length=6)
Currently i get NULL as the output
Updated Question Based On the Answer Given By deceze
** I Also had a small change in my code**
Class Code :
<?php
class MyPrintClass {
public function printVaraible($tag,$value) {
echo $tag.' == '.$value;
var_dump(func_get_args());
}
}
$printVar = new MyPrintClass;
?>
Converted Class To Function By
<?php
function getVal($tag,$value) {
global $printVar;
call_user_func_array([$printVar, 'printVariable'], $tag,$value,func_get_args());
}
?>
If i try to use it as below i get error
<?php getVal('first','second','third,'fourth'); ?>
Warning: call_user_func_array() expects exactly 2 parameters, 4 given
call_user_func_array([$print, 'printVariable'], func_get_args());
This calls the function with separate parameters from an array. I'd question the usefulness of this though, since you'll just end up with an array from func_get_args anyway. Why not pass arrays around in the first place?
Your getting null in the return because you never return anything, from the functions above.
if you want to call a class method I suggest you look into Refection or you can also do
$a = 'printVaraible';
$class->$a(1,3); //
besides using call_user_func_array, I would also suggest looking into closures (php > 5.3 ), which will let you write them this way.
$a = function foo(){ echo 'foo'};
$a();
Last thing I would generally avoid using global, as it obscures in your code where the values come from. It is always better to inject values into the function scope and not mix that with the global, imaging hunting that global down in a large project, I just avoid them at all cost and forget they exist.
I want to create a function which receives a single argument that holds the path to a PHP file and then parses the given file and returns something like this:
class NameOfTheClass
function Method1($arg1, $arg2, $arg2)
private function Method2($arg1, $arg2, $arg2)
public function Method2($arg1, $arg2, $arg2)
abstract class AnotherClass
function Method1($arg1, $arg2, $arg2)
private function Method2($arg1, $arg2, $arg2)
public function Method2($arg1, $arg2, $arg2)
function SomeFunction($arg1, $arg2, $arg3)
This function should return all the classes, methods and function that exist in the given file with all the defined identifiers (abstract, public, private, protected, static, extends, interfaces, ...).
My first tought was to use regular expressions to do this, however these behave quite badly with comments, ie: /* this function returns(max(salary)) */ and become quite complex if I want to properly support scopes.
Another possible solution was to use the following built-in PHP functions:
get_declared_classes
get_declared_interfaces
get_defined_functions
get_class_methods
However these functions don't allow me to see the file where the classes / methods / functions are defined and thus it's not very useful.
I believe the Tokenizer extension is the solution for my problem, however I have never used this extension before.
If you are using PHP 5, the Reflection API is your tool.
Example:
$class = new ReflectionClass("NameOfTheClass");
$methods = $class->getMethods();
foreach($methods as $m) {
print $m->name;
$m->isPrivate() ? print "Private" : print "";
$m->isPublic() ? print "Public" : print "";
$params = $m->getParameters();
foreach($params as $p) {
print $p->getName();
}
}
I suggest the following procedure:
store the current output of get_declared_classes, get_declared_interfaces and get_defined_functions(if you really need to support them)
include the file
compare get_declared_classes, get_declared_interfaces and get_defined_functions with the ones you stored to see what's new
use reflection to analyze them
goto step 2 for the next file
Like you found out yourself, regex are quite not the right tool for the job, here ^^
And, like you said, the built-in functions you proposed are not that helpful either -- only thing that might be helpful is that they allow you to know which class exists... But they'll return builtin classes too :-(
Using the Tokenizer extension seems a bit overkill/hard to me ; I would probably not go that way, actually : too "low-level", I suppose.
Instead, I would take a look at PHP's Reflection API : it exists exactly to reverse-engineer classes, interfaces, functions, ...
So, I suppose it would be quite well-suited for what you are trying to do.
Edit : here is a quick example :
First, let's try to do reflection on a class :
include dirname(__FILE__) . '/temp-2.php';
$rC = new ReflectionClass('MyFirstClass');
You can now find out in which file it was declared, and which methods are in it :
var_dump($rC->getFileName());
var_dump($rC->getMethods());
Which will get you :
string '/home/squale/developpement/tests/temp/temp-2.php' (length=48)
array
0 => &
object(ReflectionMethod)[2]
public 'name' => string '__construct' (length=11)
public 'class' => string 'MyFirstClass' (length=12)
1 => &
object(ReflectionMethod)[3]
public 'name' => string 'glop' (length=4)
public 'class' => string 'MyFirstClass' (length=12)
And now, to get informations on each method :
foreach ($rC->getMethods() as $rM) {
var_dump($rM, $rM->getParameters());
echo '-----';
}
You'll get :
object(ReflectionMethod)[3]
public 'name' => string '__construct' (length=11)
public 'class' => string 'MyFirstClass' (length=12)
array
0 => &
object(ReflectionParameter)[4]
public 'name' => string 'arg1' (length=4)
1 => &
object(ReflectionParameter)[5]
public 'name' => string 'arg2' (length=4)
-----
object(ReflectionMethod)[2]
public 'name' => string 'glop' (length=4)
public 'class' => string 'MyFirstClass' (length=12)
array
0 => &
object(ReflectionParameter)[5]
public 'name' => string 'a' (length=1)
From there, you should be able to dig a bit more ; and arrive to what you first asked ;-)
As a sidenote : there is one thing I have no idea about is : "how to find which classes / methods are declared in a given file" :-(
If anyone has an idea, it'll be welcome !