I know that some array functions, such as array_rand, work for objects as long as you put (array) in front of the object. In this case I am trying to get the ID of the
$this->id = end($this->log->r);
this returns all of the elements in the last element. I just want to know what the key of that element is. This is a JSON_decoded object.
end() sets the pointer to the last property defined in the object and returns its value.
When the pointer is moved, you can call the key() function to get the property name
<?php
$object = new stdClass();
$object->first_property = 'first value';
$object->second_property = 'second value';
$object->third_property = 'third value';
$object->last_property = 'last value';
// move pointer to end
end($object);
// get the key
$key = key($object);
var_dump($key);
?>
Outputs
string 'last_property' (length=13)
This functionality is identical for arrays How to get last key in an array
You can cast array before apllying end() method on an object :
# $menu_items is an object returned by wp_get_nav_menu_items() wordpress method
$menu_items = wp_get_nav_menu_items('nav_menu');
$last_item = (array) end($menu_items);
print_r($last_item['title']);
Related
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();
Iam working on a laravel project which stores values to a DB entry in loop on meeting certain conditions.
This first creates an array if the entry is for the first time and adds a value to it. Henceforth, it recalls the array and keeps adding values to it.
if(is_null($lead->shown_to)) {
$a = array();
array_push($a, "lead 1");
$lead->shown_to = serialize($cart);
$lead->save();
} else {
$a=unserialize($lead->shown_to);
array_push($a, "lead 2");
$lead->shown_to = serialize($a);
$lead->save();
}
To be able to create an array and add distinct elements to it repeatedly.
Is there a way to first check if the element exists in it or not. If it does, just move ahead, else add it?
Thanks in advance.
There're a couple of methods you can use.
You can first look for the value on the DB if exists using a column from the database like:
$result = Model::where( 'column', 'value' );
if ( $result ) {
// update already exists
} else {
// create one
}
// Retrieve flight by name, or create it if it doesn't exist...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);
// Retrieve by name, or instantiate...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);
Also it depends what you are looking for as firstOrCreate persists the value into the DB where firstOrNew just creates a new instance where you need to call save()
to check a value exists in an array you can use array_search(). this will return the value if exists. if not it returns false.
if(!array_search('lead 2', $a)) {
// array does't has 'lead 2' so,
array_push('lead 2', $a);
}
In Laravel I would take advantage of the Collections because they have a lot of helpful methods to work with.
I would do something like this:
OPTION 1
//Depending on the value of $lead->show, initialize the cart variable with the serialization of the attribute or and empty array and transform it to a collection.
$cart = collect($lead->shown_to ? unserialize($lead->shown_to) : []);
//Ask if the collection doesn't have the given value. If so, added it.
if (!$cart->contains($your_value)) {
$cart->push($your_value);
}
//Convert to array, serialize and store
$lead->shown_to = serialize($cart->toArray());
$lead->save();
OPTION 2
//Depending on the value of $lead->show, initialize the cart variable with the serialization of the attribute or and empty array and transform it to a collection.
$cart = collect($lead->shown_to ? unserialize($lead->shown_to) : []);
//Always push the value
$cart->push($your_value);
//Get the unique values, convert to an array, serialize and store
$lead->shown_to = serialize($cart->unique()->toArray());
$lead->save();
You can get more creative using the collections and they read better on Laravel
I think you can use updateOrCreate, if not exists it will create now, if exists, it will update it, so you can keep assigning value to shown_to property
$lead= App\Lead::updateOrCreate(
['name' => 'Lead 1'],
['shown_to' => serialize($a)]
);
if you wan to keep the existing shown_to better to use json data, so that you can do like
$lead= App\Lead::updateOrCreate(
['name' => 'Lead 1'],
['shown_to' => json_encode(array_push(json_decode($a), $newData))]
);
I have some JSON, if I var_dump the output looks like:
var_dump( $oJSON->{$oQ->sQuestionName} );
object(stdClass)[14]
public 'Lease' => boolean true
I would like to retrieve 'Lease' as a string.
I've tried casting it:
(string)$oJSON->{$oQ->sQuestionName}
but it returns an E_RECOVERABLE:
E_RECOVERABLE_ERROR Error: Object of class stdClass could not be converted to string
The following works, however I feel there must be a better way?
array_shift(array_values(array_keys(get_object_vars($oJSON->{$oQ->sQuestionName}))));
N.B. I can't use to use the following due to compatability issues
array_keys(get_object_vars($oJSON->{$oQ->sQuestionName}))[0]
Use ReflectionClass::getProperties() to get a list of the object's properties.
$reflect = new ReflectionClass($foo);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);
You can convert your desired object to an array first
$array = (array) $oJSON->{$oQ->sQuestionName};
Then you can take its first element's key
echo key($array); // Should say Lease
Fiddle
You can use json_decode with second parameter true
For example:
$str = '{"0":{"id":"123","name":"Title"}}';
var_dump(json_decode($str,true));
So, you will have an array with string objects.
I have a little situation, I am using the SplObjectStorage object and at some point I need to attach an item but also push it to the top of the list so when I iterate through the items I will get it as first object.
i.e.
$splObj->attach($something)
$splOBj->attach($something2)
$splObj->attach($this_must_be_first);
// When I iterate
foreach($splOBj as $obj) {
// I need the FIRST item to be the $this_must_be_first
}
Am not sure if this exist for iterators but this is a simple work around with iterator_to_array and array_reverse
$splObj = new SplObjectStorage();
$last = new stdClass();
$last->element = "Last Element";
$splObj->attach(new stdClass());
$splObj->attach(new stdClass());
$splObj->attach($last);
$splArray = iterator_to_array($splObj);
$splArray = array_reverse($splArray);
foreach ($splArray as $obj)
{
var_dump($obj);
}
Output
object(stdClass)[2]
public 'element' => string 'Last Element' (length=12)
object(stdClass)[4]
object(stdClass)[3]
This is... I don't even know what this is happening.
// var_dump of items before
object(stdClass)[84]
public '75' => object(stdClass)[87]
$items = (array) $items; // Casting unserialized stdClass to array
var_dump($items);
//Result of var dump:
array
'75' =>
object(stdClass)[87]
//Now lets get this item:
var_dump($items[75]); // Error
var_dump($items['75']); // Error
What the?
Thanks.
I think, you are using a debug extension, so the var_dump() output is different then standart library, properties can not be numeric but $obj->{'75'} is okay.
If can you reach to the sub object by $items->{'75'} yes you have a numeric property.
otherwise you can try print_r($items); and see the original output, or check the array after get_object_vars()
<?php
$items = new stdClass();
$items->{'75'} = new stdClass();
$items->{'75'}->{'85'} = new stdClass();
$items = (array) $items; // Casting unserialized stdClass to array
$items_array = get_object_vars($items); // getting object vars as an array.
var_dump($items["75"]); // Error
var_dump($items['75']); // Error
var_dump($items_array['75']); // Works
PHP issue : #45959
Read the casting blockquote: http://www.php.net/manual/en/language.types.array.php#language.types.array.casting
Casting to an array doesn't work like that.
See here: get_object_vars() vs. cast to array
and here: http://www.php.net/manual/en/language.types.array.php#language.types.array.casting
Blockquote
"If an object is converted to an array, the result is an array whose elements are the object's properties. The keys are the member variable names, with a few notable exceptions: integer properties are unaccessible; private variables have the class name prepended to the variable name; protected variables have a '*' prepended to the variable name. These prepended values have null bytes on either side.