Is this php syntax valid? $class->{'something'}() - php

I was reading a code example of something, and noticed a syntax that isn't familiar to me.
$response = $controller->{'home'}();
Is that a valid php syntax?

Yes.
$controller->{'home'}
// same as
$controller->home
// used to access a property
And
$controller->{'home'}()
// same as
$controller->home()
// used to call a method
The main benefit is that, by calling ->{stuff}, you can access properties with different (or strange) names.
Example:
$a = new stdClass();
$a->{'#4'} = 4;
print_r($a);
// stdClass Object
// (
// [#4] => 4
// )
You can't do $a->#4, but can do $a->{'#4'}
See this, for instance: https://3v4l.org/PaOF1

Yes it is. The cool thing about it is that you can call object's methods based on values stored in variables:
$whatToExecute = 'home';
$response = $controller->{$whatToExecute}();
Good luck!!

Related

how can i set value to an array like chaning methods?

i wanna set value with key to an arrau like chaning
I just want to know how Laravel did it
this is laravel code of eloquent update query
$variable=Model::find(3);
$variable->columnname="name";
$variable->save();
this is my code
$variable=["name"=>"Eric","email"=>"example#gmail.com"];
$variable->name="jack";
$variable->email="testest#gmail.com";
print_r($variable); or $query="update tblname ..."
It doesn't work and it give me error
how this system work
You are mixing some things up here I guess.
// Array syntax
$array = [];
$array['key'] = 'value'; // adding "value" to the array with the key "key"
$array['key'] = 'newValue'; // Values can be changed like this.
// Object syntax
$obj = new stdClass;
$obj->key = 'value'; // adding "value to the object with as the attribute "key"
BUT this would just be for a standard Class. When you are using an already existing class (in your example "Model") you can not always access or change the attributes. That's why you can often see methods like
$obj->getName(); //to get the value of "name" of the class
$obj->setName(); // to set...
Getter and Setter? I did a quick search. I think the link should clear up a couple of things. And for your code:
// option 1, create a class with getter and setter, see link
// option 2
$variable = new stdClass;
$variable->name = "Jack";
...

change $_POST to seperate function parameters in PHP

The problem is easy to explain. What I want to do is to create an object, parameters and function calls based on $_POST variables.
$obj = new $_POST['object']['name']($_POST['object']['params']);
return json_encode(
$obj->$_POST['function']['name']($_POST['function']['params'])
);
The only problem here is that it gives the parameters as an array. And I want it to seperate the variables with a comma, like: $obj->function($var1 , $var2, $var3);. How can I achieve this?
This can be done, but you should only do it using a white list of possible objects to create. Otherwise it is kind of dangerous. A system this open may not be a good idea. If you can rethink the problem it may help to approach it a different way.
To solve your problem though, you can use a construct like this:
// Possible values:
$acceptable_classes = array('myClass1', 'myClass2', 'myClass3');
// If it is an allowed class,
if (in_array($_POST['object']['name'], $acceptable_classes) {
// Store it in a variable.
$class = $_POST['object']['name'];
$obj = new $class;
}
You need to keep a similar whitelist for the function. You might use a multidimensional array for that. You may extend this to hold acceptable parameters for the possible functions. It can blow out of proportion pretty quickly, but will help maintain security.
$acceptable_classes = array(
'myClass1' => array(
'func1', 'func2'
),
'myClass2' => array(
'func3', 'func4'
)
);
if ($acceptable_classes, array_key_exists($_POST['object']['name']) {
if (in_array($_POST['function']['name'], $acceptable_classes($_POST['object']['name'])) {
// Store it in a variable.
$class = $_POST['object']['name'];
$obj = new $class;
$func = $_POST['function']['name'];
return json_encode($obj->$func($_POST['function']['params']));
}
}
Do something like this:
call_user_func_array( array($obj, $_POST['function']['name']), $_POST['function']['params'])
Documentation of the call_user_func_array function
call_user_func_array() is what you're looking for. On a side note, running $_POST values is a security risk, I hope you sanitize them properly.
The best way is to create object without arguments passed to constructor and initiate it using some other method. For example:
$obj = new $_POST['object']['name']();
$result = call_user_func_array(array($obj,'init'),$_POST['object']['params']);
Also, in PHP 5.4+ you can use this "hack":
$reflection = new ReflectionClass($_POST['object']['name']);
$obj = $reflection->newInstanceWithoutConstructor();
call_user_func_array(array($obj,'__constructor'),$_POST['object']['params']);
But I advise you to change your architecture so you would be able to pass array to constructor "as is".
have the function take an array
$name = $_POST['object']['name'];
$obj = new $name;
$array = explode(',', $_POST['object']['params'];
$obj->function($array);

Creating default object from empty value in PHP?

I see this error only after upgrading my PHP environment to PHP 5.4 and beyond. The error points to this line of code:
Error:
Creating default object from empty value
Code:
$res->success = false;
Do I first need to declare my $res object?
Your new environment may have E_STRICT warnings enabled in error_reporting for PHP versions <= 5.3.x, or simply have error_reporting set to at least E_WARNING with PHP versions >= 5.4. That error is triggered when $res is NULL or not yet initialized:
$res = NULL;
$res->success = false; // Warning: Creating default object from empty value
PHP will report a different error message if $res is already initialized to some value but is not an object:
$res = 33;
$res->success = false; // Warning: Attempt to assign property of non-object
In order to comply with E_STRICT standards prior to PHP 5.4, or the normal E_WARNING error level in PHP >= 5.4, assuming you are trying to create a generic object and assign the property success, you need to declare $res as an object of stdClass in the global namespace:
$res = new \stdClass();
$res->success = false;
This message has been E_STRICT for PHP <= 5.3. Since PHP 5.4, it was unluckilly changed to E_WARNING. Since E_WARNING messages are useful, you don't want to disable them completely.
To get rid of this warning, you must use this code:
if (!isset($res))
$res = new stdClass();
$res->success = false;
This is fully equivalent replacement. It assures exactly the same thing which PHP is silently doing - unfortunatelly with warning now - implicit object creation. You should always check if the object already exists, unless you are absolutely sure that it doesn't. The code provided by Michael is no good in general, because in some contexts the object might sometimes be already defined at the same place in code, depending on circumstances.
Simply,
$res = (object)array("success"=>false); // $res->success = bool(false);
Or you could instantiate classes with:
$res = (object)array(); // object(stdClass) -> recommended
$res = (object)[]; // object(stdClass) -> works too
$res = new \stdClass(); // object(stdClass) -> old method
and fill values with:
$res->success = !!0; // bool(false)
$res->success = false; // bool(false)
$res->success = (bool)0; // bool(false)
More infos:
https://www.php.net/manual/en/language.types.object.php#language.types.object.casting
If you put "#" character begin of the line then PHP doesn't show any warning/notice for this line. For example:
$unknownVar[$someStringVariable]->totalcall = 10; // shows a warning message that contains: Creating default object from empty value
For preventing this warning for this line you must put "#" character begin of the line like this:
#$unknownVar[$someStringVariable]->totalcall += 10; // no problem. created a stdClass object that name is $unknownVar[$someStringVariable] and created a properti that name is totalcall, and it's default value is 0.
$unknownVar[$someStringVariable]->totalcall += 10; // you don't need to # character anymore.
echo $unknownVar[$someStringVariable]->totalcall; // 20
I'm using this trick when developing. I don't like disable all warning messages becouse if you don't handle warnings correctly then they will become a big error in future.
Try this if you have array and add objects to it.
$product_details = array();
foreach ($products_in_store as $key => $objects) {
$product_details[$key] = new stdClass(); //the magic
$product_details[$key]->product_id = $objects->id;
//see new object member created on the fly without warning.
}
This sends ARRAY of Objects for later use~!
In PHP 7 anonymous objects can be created this way:
$res = new class {
public $success = false;
};
https://www.php.net/manual/en/language.oop5.anonymous.php
http://sandbox.onlinephpfunctions.com/code/ab774707a8219c0f35bdba49cc84228b580b52ee
First think you should create object
$res = new \stdClass();
then assign object with key and value thay
$res->success = false;
Try this:
ini_set('error_reporting', E_STRICT);
I had similar problem and this seem to solve the problem. You just need to initialize the $res object to a class . Suppose here the class name is test.
class test
{
//You can keep the class empty or declare your success variable here
}
$res = new test();
$res->success = false;
Starting from PHP 7 you can use a null coalescing operator to create a object when the variable is null.
$res = $res ?? new \stdClass();
$res->success = false;
A simple way to get this error is to type (a) below, meaning to type (b)
(a) $this->my->variable
(b) $this->my_variable
Trivial, but very easily overlooked and hard to spot if you are not looking for it.
You may need to check if variable declared and has correct type.
if (!isset($res) || !is_object($res)) {
$res = new \stdClass();
// With php7 you also can create an object in several ways.
// Object that implements some interface.
$res = new class implements MyInterface {};
// Object that extends some object.
$res = new class extends MyClass {};
}
$res->success = true;
See PHP anonymous classes.
Try using:
$user = (object) null;
I had a similar problem while trying to add a variable to an object returned from an API. I was iterating through the data with a foreach loop.
foreach ( $results as $data ) {
$data->direction = 0;
}
This threw the "Creating default object from empty value" Exception in Laravel.
I fixed it with a very small change.
foreach ( $results as &$data ) {
$data->direction = 0;
}
By simply making $data a reference.
I hope that helps somebody a it was annoying the hell out of me!
no you do not .. it will create it when you add the success value to the object.the default class is inherited if you do not specify one.
This problem is caused because your are assigning to an instance of object which is not initiated. For eg:
Your case:
$user->email = 'exy#gmail.com';
Solution:
$user = new User;
$user->email = 'exy#gmail.com';
This is a warning which I faced in PHP 7, the easy fix to this is by initializing the variable before using it
$myObj=new \stdClass();
Once you have intialized it then you can use it for objects
$myObj->mesg ="Welcome back - ".$c_user;
I put the following at the top of the faulting PHP file and the error was no longer display:
error_reporting(E_ERROR | E_PARSE);

Php Syntax Unexpected Sytax Error

I want to write like this in php. How can i express samely into php?
$test = '{"longUrl": "http://www.yahoo.com"}';
Thanks.
If you want to write actual PHP code to make a new object (assuming your example is JSON), there's no literal/shortcut syntax in PHP for that; you have to make a new stdClass object and set its variables manually:
$test = new stdClass;
$test->longUrl = "http://www.yahoo.com";
If you are comfortable writing JSON inside a string, as you are doing in your example, simply feed that into json_decode() and you have yourself a stdClass object:
$test = json_decode('{"longUrl": "http://www.yahoo.com"}');
$test = array("longUrl" => "http://www.yahoo.com");
>echo $test['longUrl']
http://www.yahoo.com

Assigning PHP class fields to array values when passing both into a function doesn't set the fields, why?

As the description states, I have a function that takes in an array and an object as arguments and assigns all of the objects fields to their respective values in the array depending on the type of the object. The objects all have different fields, but they all have a type attribute which the function uses to determine which fields to assign.
It works something like this:
function unload($arr,&$obj){ <-- //&$obj not $obj
if($obj->type == 'A'){
echo 'Setting field for A';
$obj->a = $arr['a_value'];
//some more assignments..
}
elseif($obj->type == 'B'){
$obj->b = $arr['b_value'];
echo 'Setting field for B';
//some more assignments...
}
//some more elseifs
//return an error if
//object's type doesn't
//match
else{
echo 'Error: Object type '.$obj->type.' not recognized.';
}
}
$arr['a_value'] = 'SomeValue';
$arr['b_value'] = 'SomeOtherValue';
$obj = new A(); //A's type set to 'A' upon initialization
unload($arr,$obj);
echo 'A->a set to: '.$obj->a;
Output:
A->a set to:
The code enters the correct branch for the object that is passed in but none of the object's fields get assigned. What am I doing wrong?
The server is running PHP 4.4.7, I still have no idea what's causing this.
Edit: I FINALLY figured it out, it was a combination of 2 things:
I didn't realize the $this keyword was required when referencing class field names from within the class. I assumed the variables had global scope so $this was optional like it is in Java. This is why just changing the function declaration didn't fix the problem. Now everything works fine!
Which PHP version are you on?
Because in PHP4 you need to explicitly pass the object by reference:
function unload($arr,&$obj){
If otherwise you are on PHP5, double check your $arr contents. And do some print_r inside and outside the function ...
If you want to get the class name i'd suggest you to use get_class() which will return the class name.
Anyway why are you using A->a instead of $obj->a? It seems to be wrong.
And notice that switch could best suits your needs in this case.
EDIT Finally got it: you have to replace
$arr['a'] = 'SomeValue';
$arr['b'] = 'SomeOtherValue';
with
$arr['a_value'] = 'SomeValue';
$arr['b_value'] = 'SomeOtherValue';
or otherwise set $obj->b = $arr['a_value']; to $obj->b = $arr['a']; and do the same with the b value.
The meaning of this is that the array keys have to be the same.

Categories