Laravel eloquent change attribute by field name - php

My model structure after model -> find($id);
protected 'attributes' =>
array (size=35)
'id' => string '1234134' (length=6)
'case' => string '123123' (length=7)
I want to update this model like this
foreach($input as $key => $value){
var_dump($key);
$case->($key)= $value;
}
$case -> save();
I tried like this but doesn't work
$reflection = new \ReflectionClass($case);
foreach($input as $key => $value){
var_dump($key);
$reflection->"$ke"y;
}

The following code should work.
$reflection = new \ReflectionClass($case);
foreach($input as $key => $value){
var_dump($key);
$reflection->{$key} = $value;
}
$case->save();

if this is a laravel eloquent model, you could utilize the use of the fill method.
$case->fill($input);
$case->save();

It seems like your syntax is a bit off, try this:
foreach($input as $key => $value){
$case->{$key} = $value;
}
$case->save();

Your problem is that you are trying to access a property of the object in a way that PHP is not supporting.
To access a property of the object by using a variable containing it's name you need to use string interpolation. Wikipedia - String Interpolation
you can achieve this by using curly brackets {} instead of round brackets ()
You can fix your example like this:
foreach($input as $key => $value){
$case->{$key}= $value;
}
$case->save();
By the way in PHP this can be achieved almost like in your second example but without the double quotes
foreach($input as $key => $value){
$case->$key= $value;
}
$case->save();
I personally prefer using curly brackets as it's showing more clearly that I'm using the string value of the variable.

Related

Modifying object in array is changing the session value

I have following piece of code in PHP Laravel that has array of objects. Each object has 2 attributes. Id and name. This whole object is being saved in session. Then after saving, I am removing the id from each object in the array. This is also modifying the session.
Am I doing something wrong?
$array = [];
$obj = new \stdClass();
$obj->id = "1";
$obj->name = "Test";
array_push($array, $obj);
$request->session()->put('val', $array);
foreach($array as $key => $val) {
unset($array[$key]->id);
}
echo "<pre>";
print_r($request->session()->get('val'));
echo "</pre>";
here, I noticed that id attribute is gone from session.
Issue arises because the same copy of the object is being manipulated. To solve this, you will need to clone the object and then unset and send in response keeping data in session intact.
$cloned_data = [];
foreach($array as $key => $val) {
$new_obj = clone $val;
unset($new_obj->id);
$cloned_data[] = $new_obj;
}
print_r($cloned_data);
For sending only the names to the frontend you can use collection pluck to get a new array of just names
$dataForFrontend = collect($array)->pluck('name')->all();
This is changing the view of data to be send to front end. [0] => 'Test'
If you need to key it by name - something like [0]['name'] => 'Test'
$dataForFrontend = collect($data)->map(
fn($item) => ['name' => $item->name]
)->all();
If there's need to retain the array elements as objects of original type, essentially same as #nice_dev's solution
$dataForFrontend = collect($array)->map(function($item) {
$clone = clone $item;
unset($clone->id);
return $clone;
})->all();
To retain the array elements as objects - not of original type but as objects of std class
$dataForFrontend = collect($data)->map(
fn($item) => (object)['name' => $item->name]
)->all();

Laravel iterate array and write to Model with Relations

I think about dynamic model creation or updating an model.
Let's assume i have an array like this:
$data = array(
'first_name' => 'Max',
'last_name' => 'Power',
'invoiceAddress.city' => 'Berlin',
'invoiceAddress.country_code' => 'DE',
'user.status_code' => 'invited'
);
Now i would like to iterate that array, and write the data to an model, where the dot notation tells me that i must write to an relation.
Normal code:
$model->first_name = $data['first_name'];
$model->last_name = $data['last_name'];
$model->invoiceAddress->city = $data['invoiceAddress.city'];
and so on.
I would prefer a more dynamic way:
foreach($data as $key => $value){
$properties = explode('.',$key);
//Now the difficult part
$model[$properties[0]][$properties[1]] = $value;
//Would work for invoiceAddress.city,
//but not for first_name
}
Here is the problem, that i don't know how many properties the explode will create.
Is there a way to solve such problem in a dynamic way?
You could use the Illuminate\Support\Arr helper from Laravel like this:
foreach($data as $key => $value) {
Arr::set($model, $key, $value);
}
It works because the Arr class uses dot notation to access the properties like:
Arr::get($model, 'invoiceAddress.country_code');
Is equivalent to:
$model['invoiceAddress']['country_code'];
If you prefer to use cleaner helper:
foreach($data as $key => $value) {
array_set($model, $key, $value);
}
You could also use these Laravel helpers data_fill() or data_set().
Other doted notation functions are listed here.

Get Key from php Array

I am using simplepie to get some feeds, I have set the key in the array which I am having trouble accessing. Here's my code:
$feed->set_feed_url(array(
'Title One'=>'http://example.com/rss/index.xml',
'Title Two'=>'http://feeds.example.com/rss/example',
'Title Three'=>'http://feeds.example.com/ex/blog'
));
When I loop over and try to access it I'm getting errors, here's how I am trying to access it.
foreach ($feed->get_items() as $item):
echo $item[0];
Fatal error: Cannot use object of type SimplePie_Item as array
How can I access those I tried also:
echo $item->[0];
without luck.
When you loop over an array (often used with associative arrays) using foreach, there is an additional construct to be able to get the key. It looks like this:
foreach ($feed->get_items() as $key => $item) {
echo($key);
}
So an array with a structure like:
$myArray = [
'a' => 1,
'b' => 2,
];
When iterated with foreach in that syntax, will put "a" or "b" in the $key variable depending on which iteration it is, and $item will contain either "1" or "2".
In your case, $item is the object instance and then you are trying to access it like it is an array. If you need to know the key, use that other foreach syntax.
To get the title of the SimplePie_Item object, you can call get_title():
foreach ($feed->get_items() as $index => $item) {
echo($item->get_title());
}

$this->$array[$key] returning nothing when there is a value in place

I'm attempting to dynamically use a value in an array within an object.
In my particular case I have an array like this.
$this->customer = array(
[dealerId] => 4
[billFirstName] => Joe
[billLastName] => Blo
[billAddress1] => 1010s
[billAddress2] => 1020s
[billCity] => Anytown
[billState] => ST
[billCountry] => USA
[billPostalCode] => 11111
[dEmail] => emailaddress
[billPhone] => 8008008888
[password] => password
[distPrice] => 5
[distCost] => 20);
$result = $this->keyCheck('dealerId', 'customer');
The method I'm using:
protected function keyCheck($key, $array, $type = false)
{
if(array_key_exists($key, $this->$array) && $this->$array[$key]):
return $this->$array[$key];
else:
return $type;
endif;
}
The first check works (array_key_exists($key, $this->$array)). But the second check fails ($this->$array[$key]) even though there is a value held in that index of the array. I've proven that the array exists inside the keyCheck() method by using, print_r($this->$array); inside the method. And I know the value I'm looking for is available inside the method by using, print $this->$array['dealerId'];
Don't get hung up on the names, or the methodology I'm using, what I'm really interested in is finding out how to address a value held in an array that is dynamically addressed in this way.
It's probably so easy that I'll be slapping my head once it's revealed...
You are running into the dreaded treat string as an array trap, i.e.:
$str = 'customer'; echo $str[0]; // prints c
The $array[$key] portion of $this->$array[$key] is being interpreted as show me the nth index of string $array (if you pass customer it will try to access $this->c, which doesn't exist). Assign the array to a variable first. Here is an example:
class A
{
public $customer = array('dealerId'=>4, 'billFirstName'=>'Joe');
public function keyCheck($key, $arrayName, $type = false)
{
$array = $this->$arrayName;
if(array_key_exists($key, $array) && $array[$key]) {
return $array[$key];
} else {
return $type;
}
}
}
$a = new A();
echo $a->keyCheck('billFirstName', 'customer'); // Joe
Alternatively, you could use the complex syntax: $this->{$arrayName}[$key] as suggested in Artjom's answer.
PHP 5.4 addresses this gotcha:
[In PHP 5.4] Non-numeric string offsets - e.g. $a['foo'] where $a is a
string - now return false on isset() and true on empty(), and produce
a E_WARNING if you try to use them.
This E_WARNING should help developers track down the cause much more quickly.
Well u have to use
$this->{$array}[$key];

How do I perform an effective array search in PHP when I'm looking for more than one key in the array?

Taking a dictionary as an example, let's say I've got the following array to catalog the pronunciations of a given word:
$pronunciation["text"] = array("alpha", "beta", "gamma", "delta", "epsilon");
$pronunciation["definition"] = array(1, 2, NULL, NULL, 1);
text contains the pronunciation that will be displayed to the user, while definition contains the ID for the definition in the list where that pronunciation applies. If definition is NULL, it's not associated with any particular definition, and should be displayed elsewhere in the entry.
Now, if I try to do something like the following:
$key = array_search(1, $pronunciation["definition"]);
All I'll get is 0, since that's the first key in definition that contains the value. Likewise, substituting NULL returns 3, however both of these actually have another related key that I'm trying to fetch.
Is there a way to get it to return all related keys without having to resort to brute force methods such as a for loop?
Try this one:
array_keys($pronunciation["definition"],1)
I'm afraid there is not a function that do that as you want. Edit: Nope, there is! See Jauzsika answer.You have to use a foreach or a for loop.
function array_search_all($needle, $haystack) {
$keys = array();
foreach ($haystack as $k => $v) if ($v === $needle) $keys[] = $k;
return $keys;
}
Call:
$keys = array_search_all(1, $pronunciation["definition"]);
I don't know wheter it's faster or not, but I think if there're a set of data which you have to search in, it's better to set up an array, where the data is the key.
$data["alpha"] = 1
$data["beta"] = 1
//...
All your foreach should be modified from
foreach ($data as $item) {
to
foreach ($data as $item => $value) {
Restructure your arrays into a single array keyed on the text and using the definition as the value:
$pronunciation = array("alpha" => 1,
"beta" => 2,
"gamma" => NULL,
"delta" => NULL,
"epsilon" => 1);
Then use array_filter() to build a subset of the values you need
$searchVal = 1;
$subset = array_filter($pronunciation,
create_function('$value', 'return $value == '.$searchVal.';')
);
var_dump($subset);

Categories