Adding iteration to an objects properties in PHP - php

This is likely to be very inelegant however this is my problem.
I have a returned array of objects like this..
Array (
[count_assessor0] => stdClass Object ( [assessor0] => 91 )
[count_assessor1] => stdClass Object ( [assessor1] => 3 )
[count_assessor2] => stdClass Object ( [assessor2] => 5 )
[count_assessor3] => stdClass Object ( [assessor3] => 24 )
[count_verifier0] => stdClass Object ( [verifier0] => 91 )
[count_verifier1] => stdClass Object ( [verifier1] => 3 )
[count_verifier2] => stdClass Object ( [verifier2] => 5 )
[count_verifier3] => stdClass Object ( [verifier3] => 24 )
)
Ok, so as you can see each array and property have a numerical suffix. What I want to do is use these suffixes in a foreach loop below however when it comes to adding $n to the objects property I get an error as it doesn't 'add' the suffix on to $role.
$options = array('Yes - Qualified', 'Yes - Not Qualified', 'No - Working Towards', 'No - Not Working Towards');
$roles = array('assessor' => $options, 'verifier' => $options, 'teaching_status' => $options, 'coaching_status' => $options);
$i = 0 ;
foreach($roles as $role => $options){
echo ucwords($role);
$n = 0 ;
foreach($options as $option) {
echo $option ;
echo $count["count_$role$i"]->$role$n;
$n++ ;
$i++ ;
endforeach ;
unset($n) ;
endforeach ;
If I have explained this well enough can anyone help?
Thanks!

I think You should make use of dynamic variable name creation, it is well described here:
Dynamic variable names in PHP
So in You code there should be something like that:
$property = ${$role.$n};
echo $count["count_$role$i"]->$property;

Related

Access Multi dimensional array through a dynamic variable

I am trying to pass a dynamic variable into a multidimensional array.
This is the actual code:
for($i = 0; $i < count($social ["#object"] -> field_sector ["und"]); $i++){
echo $social ["#object"] -> field_sector ["und"] [$i] ["taxonomy_term"] -> name;
}
Since I want to re-use this code for multiple types, I created a function
function render_multi_array ($parent, $field_name) {
for($i = 0; $i < count($parent ["#object"] -> $field_name ["und"]); $i++){
echo $parent ["#object"] -> $field_name ["und"] [$i] ["taxonomy_term"] -> name;
}
}
The issue is happening with $field_name as I am unable to provide this dynamically. Any idea how I can make this function work?
Sample array is follows:
Array
(
[#title] => Sector
[#field_name] => field_sector
[#object] => stdClass Object
(
[vid] => 1079
[uid] => 30
[vuuid] => 83ab0817-0175-4541-b20e-93611c20c026
[nid] => 1077
[type] => random_study
[field_random_id] => Array
(
[und] => Array
(
[0] => Array
(
[value] => CS_525
[format] =>
[safe_value] => CS_525
)
)
)
[field_sector] => Array
(
[und] => Array
(
[0] => Array
(
[tid] => 411
[taxonomy_term] => stdClass Object
(
[tid] => 411
[vid] => 10
[name] => Sample title goes here.
)
)
[1] => Array
(
[tid] => 248
[taxonomy_term] => stdClass Object
(
[tid] => 248
[vid] => 10
[name] => Energy
)
)
)
)
In PHP 7 the code should work as written. PHP 7.0 changed evaluation order to strictly left to right.
In PHP 5, you'll get an illegal string offset warning because PHP is trying to first evaluate $field_name["und"] (e.g. "field_sector"["und"]) and use the result of that as the property name in #object rather than evaluating $parent["#object"]->$field_name to get the array and then accessing that with ["und"].
You can prevent that by bracketing the variable like this:
function render_multi_array ($parent, $field_name) {
for ($i = 0; $i < count($parent["#object"]->{$field_name}["und"]); $i++){
echo $parent ["#object"]->{$field_name}["und"][$i]["taxonomy_term"]->name;
}
}
Adding those brackets won't cause any problems if you upgrade to PHP 7 later.
By the way, it looks like this code would be simpler with a foreach loop instead.
function render_multi_array ($parent, $field_name) {
foreach ($parent['#object']->{$field_name}['und'] as $item) {
echo $item['taxonomy_term']->name;
}
}

Cycling an array and delete item

I need help :)
I've to code a script that, cycling through an array inside an array , delete an element if in XXX field there isn't value (is NULL ).
My array is:
Array (
[idCampaign] => 3
[idIT] => 322
[recipients] =>Array (
[0] => stdClass Object ( [name] => minnie [email] => blabla#gmail.com [XXX] => )
[1] => stdClass Object ( [name] => [email] => fddd#gmail.it [XXX] => 0.88451100 )
) ) [date] => MongoDate Object ( [sec] => 1468503103 [usec] => 0 ) )
In this example the item [0] has no value in XXX value so my output array will be:
Array (
[idCampaign] => 3
[idIT] => 322
[recipients] =>Array (
[1] => stdClass Object ( [name] => [email] => fddd#gmail.it [XXX] => 0.88451100 )
) ) [date] => MongoDate Object ( [sec] => 1468503103 [usec] => 0 ) )
i hope that you can help me :)
You could use a nested foreach() Loop to cycle through the Data and then perform some tests, which on failing, guarantees that it is safe to unset the pertinent variable. Here's how:
<?php
// WE SIMULATE SOME DATA TO POPULATE THE ARRAY, ONLY FOR TESTING PURPOSES
$objDate = new stdClass();
$objRez1 = new stdClass();
$objRez2 = new stdClass();
$objRez1->name = "minnie";
$objRez1->email = "blabla#gmail.com";
$objRez1->XXX = null;
$objRez2->name = null;
$objRez2->email = "fddd#gmail.it";
$objRez2->XXX = 0.88451100;
$objDate->sec = 1468503103;
$objDate->usec = 0;
// IN THE END WE NOW HAVE A SAMPLE ARRAY (SIMULATED) TO WORK WITH.
$arrData = array(
'idCampaign' => 3,
'idIT' => 322,
'recipients' => array(
$objRez1,
$objRez2
),
'date' =>$objDate,
);
// LOOP THROUGH THE ARRAY OF DATA THAT YOU HAVE
// NOTICE THE &$data IN THE LOOP CONSTRUCT...
// THIS IS NECESSARY FOR REFERENCING WHEN WE UNSET VARIABLES WITHIN THE LOOP
foreach($arrData as $key=>&$data){
// SINCE THE XXX KEY IS STORED IN THE 'recipients' ARRAY,
// WE CHECK IF THE CURRENT KEY IS 'recipients' & THAT $data IS AN ARRAY
if($key == "recipients" && is_array($data)){
// NOW WE LOOP THROUGH THE DATA WHEREIN THE 'XXX' KEY LIVES
foreach($data as $obj){
// IF THE VALUE OF THE XXX KEY IS NULL OR NOT SET,
// WE SIMPLY UNSET IT...
if(!$obj->XXX){
unset($obj->XXX);
}
}
}
}
var_dump($arrData);
You can verify the Results HERE.
Hope this could offer you a little tip on how to implement it rightly on your own...
This should do the job
foreach($arrayOfObjects as $index => $object){
if(!isset($object->xxx) || empty($object->xxx)){
unset($arrayOfObjects[$index]);
}
}

Codeception check several elements with same locator

I have several elements on my page with same locator.
Example:
<div.test-info><a>Test1</a></div>
<div.test-info><a>Test2</a></div>
<div.test-info><a>Test3</a></div>
<div.test-info><a>Test4</a></div>
There maybe 20 or more elements on the page.
In python, I tested this with FOR loop, which run through array of elements, grabbed by 'findElemenets' method.
My problem is that i don't know how to do this with Codeception.
I found method '_findElements' but it returns Facebook\WebDriver\Remote\RemoteWebElement instances.
Like :
Array
(
[0] => Facebook\WebDriver\Remote\RemoteWebElement Object
(
[executor:protected] => Facebook\WebDriver\Remote\RemoteExecuteMethod Object
(
[driver:Facebook\WebDriver\Remote\RemoteExecuteMethod:private] => Facebook\WebDriver\Remote\RemoteWebDriver Object
(
[executor:protected] => Facebook\WebDriver\Remote\HttpCommandExecutor Object
(
[url:protected] => http://127.0.0.1:4444/wd/hub
[curl:protected] => Resource id #326
)
[sessionID:protected] => 109595b5-f094-4824-ac10-fc7d6353b799
[mouse:protected] =>
[keyboard:protected] =>
[touch:protected] =>
[executeMethod:protected] => Facebook\WebDriver\Remote\RemoteExecuteMethod Object
*RECURSION*
)
)
[id:protected] => 0
[fileDetector:protected] => Facebook\WebDriver\Remote\UselessFileDetector Object
(
)
)
[1] => Facebook\WebDriver\Remote\RemoteWebElement Object
(
[executor:protected] => Facebook\WebDriver\Remote\RemoteExecuteMethod Object
(
[driver:Facebook\WebDriver\Remote\RemoteExecuteMethod:private] => Facebook\WebDriver\Remote\RemoteWebDriver Object
(
[executor:protected] => Facebook\WebDriver\Remote\HttpCommandExecutor Object
(
[url:protected] => http://127.0.0.1:4444/wd/hub
[curl:protected] => Resource id #326
)
[sessionID:protected] => 109595b5-f094-4824-ac10-fc7d6353b799
[mouse:protected] =>
[keyboard:protected] =>
[touch:protected] =>
[executeMethod:protected] => Facebook\WebDriver\Remote\RemoteExecuteMethod Object
*RECURSION*
)
)
[id:protected] => 1
[fileDetector:protected] => Facebook\WebDriver\Remote\UselessFileDetector Object
(
)
)
)
How can I operate with this data, or is there another good way to resolve my problem ?
If you want to get content of divs, use grabMultiple method, it returns array of strings.
$I->grabMultiple('div.test-info a')
$elements = $I->_findElements('div.test-info a');
foreach($elements as $element)
{
*do some testing* for example $element->click();
}
the methods you can use for the RemoteWebElement, see http://facebook.github.io/php-webdriver/classes/RemoteWebElement.html
Here is working solution:
$allLinks = $I->grabMultiple('.readmore'); //grab all clickable links
for( $i = 0; $i<sizeof($allLinks); $i++ ) { //iterate through a loop
$I->click($allLinks[$i]); //click each link
}

Retrieving correct record from multidimentional array

I'm having a mental freeze moment. If I have an array in the following format:
$myData = Array
(
[0] => stdClass Object
(
[id] => 1
[busID] => 5
[type] => SMS
[number] => 5128888888
)
[1] => stdClass Object
(
[id] => 2
[busID] => 5
[type] => APP
[number] => 5125555555
)
[2] => stdClass Object
(
[id] => 4
[busID] => 5
[type] => APP
[number] => 5129999988
[verified] => 1
[default] => 0
)
)
And I only have an var for ID of the record, how do I retrieve the rest of the detail for that set.
$myID = 2;
// get number 5125555555 and it's type
echo $myData[][$myID]['number']; // ???
The way you have your data arranged your going to have to loop through your array to identify the object corresponding to $myID.
foreach($myData as $object) if($object->id == $myID) echo $object->number;
The alternative is to arrange your $myData as an associative array with the id field as the key. Then you could access it simply with $myData[$myID]->number.
Actually it's an array that contains StdClass objects , try looping over $myData and access each attribute :
foreach ( $myData as $data )
{
print_r($data->id);
// ...
}
You can avoid loop by using following logic:
<?php
$myID = 2;
$myData = json_decode(json_encode($myData),1); // Convert Object to Array
$id_arr = array_column($myData, 'id'); // Create an array with All Ids
$idx = array_search($myID, $id_arr);
if($idx !== false)
{
echo $myData[$idx]['type'] . ' -- ' . $myData[$idx]['number'];
}
?>
Working Demo
Note: array_column is supported from PHP 5.5.
For lower versions you can use this beautiful library https://github.com/ramsey/array_column/blob/master/src/array_column.php
You can create a custom function to achieve this, you need to pass the array and id whose details you want and the function will return the array with matching id, like below
function detailsById($myData,$id){
foreach($myData as $data){
if($data->id == $id){
return $data;
}
}
}
Just call this function with your array and id..
$data=detailsById($myData,2);
echo "<pre>";print_r($data);
This will give you :
stdClass Object
(
[id] => 2
[busID] => 5
[type] => APP
[number] => 5125555555
)
And further to print 'number' and 'type' use $data array
$data['type'];
$data['number'];

php stdClass check for property exist

I have read some similar issues here but unfortunately find the solution for my case.
Some part of the output for an API connection is as;
stdClass Object (
[page] => 0
[items] => 5
[total] => 5
[saleItems] => stdClass Object (
[saleItem] => Array (
[0] => stdClass Object (
[reviewState] => approved
[trackingDate] => 2013-11-04T09:51:13.420+01:00
[modifiedDate] => 2013-12-03T15:06:39.240+01:00
[clickDate] => 2013-11-04T09:06:19.403+01:00
[adspace] => stdClass Object (
[_] => xxxxx
[id] => 1849681
)
[admedium] => stdClass Object (
[_] => Version 3
[id] => 721152
)
[program] => stdClass Object (
[_] => yyyy
[id] => 10853
)
[clickId] => 1832355435760747520
[clickInId] => 0
[amount] => 48.31
[commission] => 7.25
[currency] => USD
[gpps] => stdClass Object (
[gpp] => Array (
[0] => stdClass Object (
[_] => 7-75
[id] => z0
)
)
)
[trackingCategory] => stdClass Object (
[_] => rers
[id] => 68722
)
[id] => 86erereress-a9e4-4226-8417-a46b4c9fd5df
)
)
)
)
Some strings do not include gpps property.
What I have done is as follows
foreach($sales->saleItems->saleItem as $sale)
{
$status = $sale->reviewState;
if(property_exists($sale, gpps))
{
$subId = $sale->gpps->gpp[0]->_;
}else{
$subId = "0-0";
}
}
What I want is I the gpps property is not included in that string $subId stored as 0-0 in db, otherwise get the data from the string. But it doesn't get the strings without gpps.
Where is my mistake?
Change
if(property_exists($sale, gpps))
with
if(property_exists($sale, "gpps"))
notice how now gpps is passed as string, as per the signature of the property_exists function:
bool property_exists ( mixed $class , string $property )
This function checks if the given property exists in the specified class.
Note:
As opposed with isset(), property_exists() returns TRUE even if the property has the value NULL.
property_exists is the method designed for this purpose.
bool property_exists ( mixed $class , string $property )
This function checks if the given property exists in the specified class.
Note:
As opposed with isset(), property_exists() returns TRUE even if the property has the value NULL.
Try a simple hack and use count, since the property contains an array, and I guess, that count(array) == 0 is the same case as when the property is not set.
foreach($sales->saleItems->saleItem as $sale)
{
$status = $sale->reviewState;
if(#count($sale->gpps->gpp) && count($sale->gpps->gpp) > 0)
{
$subId = $sale->gpps->gpp[0]->_;
}else{
$subId = "0-0";
}
}
Sure, this is not the most beautiful solution, but since the php-function do not work as expected, I thought a bit more pragmatic.
Another way , get_object_vars
$obj = new stdClass();
$obj->name = "Nick";
$obj->surname = "Doe";
$obj->age = 20;
$obj->adresse = null;
$ar_properties[]=get_object_vars($obj);
foreach($ar_properties as $ar){
foreach ($ar as $k=>$v){
if($k =="surname"){
echo "Found";
}
}
}

Categories