Yii2 array of objects, find the one - php

I have an array in yii2, and ocassionally it's only 1 single object that is not empty (all other element of array is empty) and I don't know which one is it. How can I either find the one that is not empty, or (my idea what I was trying), to create a new array, with array_filter (but I'm not sure if it works also with array of objects), to have only the one object in it.
if (count($ttepk) == 1) {
$ttep_filtered[] = array_filter($ttepk);
$id = $ttep_filtered[0]->id;
}
But it was also not working. I get the error message: PHP Notice – yii\base\ErrorException Trying to get property of non-object.
Before array_filter it looks like this:
Array
(
[3] => app\models\Model Object
(
after array_filter:
Array
(
[0] => Array
(
[3] => app\models\Model Object
(
So it seems, array_filter is not the one I need, or I use it the wrong way.
Can you please help me? Thank you!

You can try something like this
$filtered = array_filter($ttepk, function($item) {
return $item instanceof app\models\Model;
});
if (count($filtered) == 1) {
$id = reset($filtered)->id;
}

Related

array_walk not changing value

function values($id,$col)
{
$vals = [1=>['name'=>'Lifting Heavy Boxes']];
return $vals[$id][$col];
}
$complete = [1=>["id"=>"2","sid"=>"35","material_completed"=>"1","date"=>"2017-12-18"]];
$form = 'my_form';
array_walk($complete, function(&$d,$k) use($form) {
$k = values($k, 'name').' ['.date('m/d/y',strtotime($d['date'])).'] ('.$form.')';
echo 'in walk '.$k."\n";
});
print_r($complete);
the echo outputs:
in walk Lifting Heavy Boxes [12/18/17] (my_form)
the print_r outputs:
Array
(
[1] => Array
(
[id] => 2
[sid] => 35
[material_completed] => 1
[date] => 2017-12-18
)
)
I have another array walk that is very similar that is doing just fine. The only difference I can perceive between them is in the one that's working, the value $d is already a string before it goes through the walk, whereas in the one that's not working, $d is an array that is converted to a string inside the walk (successfully, but ultimately unsuccessfully).
Something I'm missing?
And here's the fixed version:
array_walk($complete, function(&$d,$k) use($form) {
$d = values($k, 'name').' ['.date('m/d/y',strtotime($d['date'])).'] ('.$form.')';
});
That's what I was trying to do anyway. I wasn't trying to change the key. I was under the mistaken impression that to change the value you had to set the key to the new value.
You cannot change the key of the array inside the callback of array_walk():
Only the values of the array may potentially be changed; its structure cannot be altered, i.e., the programmer cannot add, unset or reorder elements. If the callback does not respect this requirement, the behavior of this function is undefined, and unpredictable.
This is also mentioned in the first comment:
It's worth nothing that array_walk can not be used to change keys in the array.
The function may be defined as (&$value, $key) but not (&$value, &$key).
Even though PHP does not complain/warn, it does not modify the key.

Get the single element from the array

I got the following array (the array is retrieved through a db query). Now, my question is, how do I get a single element like e_domains from the array mentioned below:
stdClass Object
(
[id] => 1
[uni_origin] => Aachen
[e_domains] => rwth-aachen.de
)
I got the output shown above by running the following line of codes:
if ($results ) {
foreach ( $results as $result ){
echo'<pre>'; print_r($result) ;
}
}
First off, that's not an array, that's an object. Like it says: "stdClass Object".
Access object properties like this:
$object->property_name
In your case, it would be:
$result->e_domains
There are much more to learn on the subject, like static properties, visibility etc. In your case, the above example will work.
Read more about classes and objects in the manual: http://php.net/manual/en/language.oop5.basic.php
Try this:
$e_domains = mysql_result(mysql_query("SELECT id FROM games LIMIT 1"),0);
Hope it helpt.

PHP - adding an object with its properties to array

I have a problem with modifying an array.
foreach ($page->getResults() as $lineItem) {
print_r($lineItem->getTargeting()->getGeoTargeting()->getExcludedLocations());
}
This code gives a result:
Array
(
[0] => Google\AdsApi\Dfp\v201611\Location Object
(
[id:protected] => 2250
[type:protected] => COUNTRY
[canonicalParentId:protected] =>
[displayName:protected] => France
)
)
I'm trying to add another, [1] , same type of object to this array.
I made a class to create and add an object:
class Location{
public function createProperty($propertyName, $propertyValue){
$this->{$propertyName} = $propertyValue;
}
}
$location = new Location();
$location->createProperty('id', '2792');
$location->createProperty('type', 'COUNTRY');
$location->createProperty('canonicalParentId', '');
$location->createProperty('displayName', 'Turkey');
array_push($lineItem->getTargeting()->getGeoTargeting()->getExcludedLocations(), $location);
Then, if I pass this into print_r() function
print_r($lineItem->getTargeting()->getGeoTargeting()->getExcludedLocations());
It shows the same result.
In the end, I need to send this updated whole $lineItem to this function
$lineItems = $lineItemService->updateLineItems(array($lineItem));
But seems like before sending I can't properly add an object to the array.
Thanks in advance.
PHP returns arrays as a value instead of as a reference. This means you must set the modified value back somehow.
Looking at the library apparently in question, there seems to be setExcludedLocations method for that purpose.
So your code should be something like:
$geo_targeting = $lineItem->getTargeting()->getGeoTargeting();
$excluded_locations = $geo_targeting->getExcludedLocations();
array_push($excluded_locations, $location);
$geo_targeting->setExcludedLocations($excluded_locations);

In PHP, how can I access a child object when I don't know it's name?

Using json_decode, I've ended up with an object that looks like this:
$data->foo->bar->1234567->id
I want to access id. There are two problems, both with the number 1234567:
It's an illegal property name.
The number will differ each time, and I can't predict what the number will be. I need a way of accessing id, even when I don't know the number.
I know I can overcome problem (1) with curly braces, but I don't know how to overcome (2). I don't want to use get_object_vars, because the object is likely to be very large, and that function is very slow.
My current solution is simply
foreach ($data->foo->bar as $id); but that feels rather hacky. Is there a better way?
From my comment above, using json_decode(,true) and then resetting.
The example json array looks like:
Array (
[foo] => Array (
[bar] => Array (
[1234567] => Array (
[id] => 1234
)
)
)
)
The code:
<?php
$data = json_decode('{"foo":{"bar":{"1234567":{"id":1234}}}}', true);
reset($data['foo']['bar']);
$number = key($data['foo']['bar']);
echo $data['foo']['bar'][$number]['id'];
Output: 1234
In case you don't need the whole array anymore and only want to get the id you can get it like this:
<?php
$data = json_decode('{"foo":{"bar":{"1234567":{"id":1234}}}}', true);
echo array_shift($data['foo']['bar'])['id'];
Only works if the unknown key is the first element of bar. array_shift removes the element from $data.

Apply function to every array key

I am using Cassandra and I have saved some byte representations as ID. Everything is working fine, however that data (id) is no good for output.
$users = $db->get('1');
echo '<pre>';
print_r($users);
die();
Outputs
Array
(
[��� X��W��c_ ] => Array
(
[id] => ��� X��W��c_
[name] => steve
[surname] => moss
)
[�*B�X��y�~p��~] => Array
(
[id] => �*B�X��y�~p��~
[name] => john
[surname] => doe
)
)
As you can see ID's are some wierd characters, it's because they are byte representations in database. They actually look like \xf5*B\xa0X\x00\x11\xe1\x99y\xbf~p\xbc\xd1~.
In PHPCASSA there is function CassandraUtil::import(); to which I can pass these bytes and it will return guid. It works fine, but I want my array to automatically converted from bytes to guids.
Only option I find is looping through every item in array and assigning new value to it. Somehow I think that it is not the best approach. Is there any other ways to do this?
TL;DR
Have array with bytes like above, need to use CassandraUtil::import(); on array keys and id's to get readable id's. What is the most effective way of doing so.
UPDATE
Sorry, only saw the top level array key, I think you would have to run the function below as well as another one after:
function cassImportWalkRecur(&$item, $key)
{
if ($key == 'id')
$item = CassandraUtil::import();
}
$array = array_walk_recursive($array, 'cassImportWalkRecur');
That should apply it to the ID fields. If you need to check the data first, there maybe a way to detect the encoding, but I am not sure how to do that.
You should be able to create a function and use array_walk to traverse the array and update the keys. Something like:
function cassImportWalk($item, &$key)
{
$key = CassandraUtil::import();
}
$array = array_walk($array, 'cassImportWalk');
Untested (also you may have to change the CassandraUtil usage), but should work.
Unless I am misunderstanding the question this can be done simply and cleanly like so:
$users = $db->get('1');
$keys = array_keys($users);
$readableKeys = array_map("CassandraUtil::import",$keys);
foreach($users as $currentKey => $subArray) {
$readableKey = array_shift($readableKeys);
$subArray['id'] = $readableKey;
$users[$readableKey] = $subArray;
unset($users[$currentKey]);
}
Would array_flip() all keys and values, then array_walk() and apply my function, before doing a final array_flip().

Categories