CakePHP use Hash to prepare Model array for saving - php

I'm wondering how one might use CakePHP Hash functions to achieve the following:
This is the array before (Plugin stored in Session):
$Data = array(
'add' => array(
'Certificate' => array(
'name' => '',
'entity_id' => '1',
'state_id' => '18',
'domicile' => '',
'formation_date' => array(
'month' => '',
'day' => '',
'year' => ''
)
)
),
'add2' => array(
'Certificate' => array(
'filing_fees' => '82'
)
)
)
This is the array after. I am reformatting it to call Certificate->save(). I removed the top level and merged the Certificate model.
$Data = array(
'Certificate' => array(
'name' => '',
'entity_id' => '1',
'state_id' => '18',
'domicile' => '',
'formation_date' => array(
'month' => '',
'day' => '',
'year' => ''
),
'filing_fees' => '82'
)
)
This is my current code:
$processed = array();
foreach ($Data as $k => $array1) {
foreach ($array1 as $array1k => $array2) {
if (!isset($processed[$array1k])) {
$processed[$array1k] = array();
}
foreach ($array2 as $a2k => $a2v) {
$processed[$array1k][$a2k] = $a2v;
}
}
}
What I have works, but it's not very "Cake-ish" and will certainly cause problems when I need to prepare data for saving more complex model relationships (e.g. HABTM saveall).
I tried Hash::combine, Hash::merge, array_merge_recursive(), and combinations of these before posting. I understand the PHP logic, but I am lost to find the CakePHP functions with similar logic.
The first step is to merge the Model, then the second step is to remove the key ('add, 'add2'). The closest I got was Hash::combine, but there was no way to reference a $keyPath {s} of the Model, skipping over the first level ('add', 'add2') of the array.
If you could point me in the direction of which Hash or other CakePHP functions are recommended, I'd be happy to take the next step.

Related

Sorting very long json object with php

I am working with an API and i am trying to sort the json object it returns to me. Here is a small cut out of the json object
Now i want to sort this because i only want to save part of the data. Say i wanted to save the "_ID" here. THe data i need is really way further down but i think if i can figure out how to get this, i can figure out the rest. Since as you can see from the picture, it contains many objects inside objects and arrays within arrays its very confusing for me to target the specific values i want
I have tried something like this:
$body = $response->getBody();
$data = json_decode($body, true);
$sortedData = $data."hits".hits[0]."_id";
return $sortedData
Also tried without the quotation marks, but i cant really get it to work. Im very new to PHP.
You decoded these objects into associative arrays, so $data['hits']['hits'][0]['_id'] should be the correct way to access that element.
https://www.php.net/manual/en/language.types.array.php explains the basics of how to work with arrays and access elements within them.
Since php 5.5, you can use array_column to get specific column from the array :
$body = $response->getBody();
$data = json_decode($body, true);
$sortedData = array_column($data, '_id');
return $sortedData;
Edit
From what I see on your array sample, you want to do a recursive multidimensional arrays search (not just 2-dimensional).
Assuming you have array like this :
$arr = array(
array(
'x' => '10',
'name' => 'blah',
'other' => array(
'_id' => '26',
'color' => '10x',
)
),
array(
'x' => '7',
'name' => 'blahblah',
'other' => array(
'_id' => '29',
'color' => '7x',
)
),
array(
'x' => '15',
'name' => 'blahblahblah',
'other' => array(
'_id' => '27',
'color' => '15x',
)
),
array(
'x' => '1',
'name' => 'sdf',
'other' => array(
'_id' => '41',
'color' => '1x',
)
),
array(
'x' => '4',
'name' => '3dgdg',
'other' => array(
'_id' => '31',
'color' => '4x',
)
),
array(
'x' => '5',
'name' => 'nmnmnm',
'other' => array(
'_id' => '36',
'color' => '5x',
)
),
array(
'x' => '21',
'name' => 'dhshshhh',
'other' => array(
'_id' => '34',
'color' => '21x',
)
)
);
And you want to get the _id key. In that case you could try this function :
function array_column_recursive(array $haystack, $needle) {
$found = [];
array_walk_recursive($haystack, function($value, $key) use (&$found, $needle) {
if ($key == $needle)
$found[] = $value;
});
return $found;
}
Usage :
$ids = array_column_recursive($arr,'_id');
sort($ids);
print_r($ids);
Reference :
array_column
array_column_recursive

Sum of Dynamic Multi-Dimension array in PHP

I searched for few in-built methods and tried few logics from here and there but none can make me satisfied. I have created my own logic but is limited to a certain dimension of the array. I have managed to solve my problem for the project but as I said I am not satisfied.
Consider the array below:
$data = array
(
'0' => array
(
'0' => array
(
'make_ready' => '',
'ready_time' => '0.55',
'rate' => '46',
'no_of_run' => '',
'fixed_cost' => '',
'variable_cost' => '25.3',
'0' => array(
'kg' => 2.66,
'rate' => 11.4,
'fixed_cost' => '',
'variable_cost' => 30.32,
'0' => array(
'kg' => 2.66,
'rate' => 11.4,
'fixed_cost' => '',
'variable_cost' => 30.32,
),
),
),
),
'1' => array
(
'0' => array
(
'make_ready' => '1',
'ready_time' => '1.16',
'rate' => '36.47',
'no_of_run' => '',
'fixed_cost' => '36.47',
'variable_cost' => '42.31',
),
),
'2' => array
(
'make_ready' => '2',
'ready_time' => '0.29',
'rate' => '360',
'no_of_run' => '',
'fixed_cost' => '720',
'variable_cost' => '104.4',
),
'size' => '1000 X 1200 X 1190',
'up' => '3 X 4 / 17',
'unit' => '4',
'rate' => 16.32,
'fixed_cost' => '',
'variable_cost' => 65.28,
);
Problem:
I want to sum up all the values of array element where key is 'variable_cost', no matter how deep (in terms of dimension) is the array. Basically like a loop that can scan all the elements and do 'sum' if key matches.
I would like someone to help/suggest any logic where the calculations can be done till nth dimension.
For example like the movie Inception, in which they can go
dream->with in a dream->to nth number of dream.
and come out with the sum of 'variable_cost'. Hope you guys can understand the question here.
Thank you.
You will need to use a recursive function to sum all the variable_cost values:
function sum_variable_cost( $data, $total=0) {
foreach ($data as $key => $item) {
if (is_array($item)) {
$total = sum_variable_cost($item, $total);
} else if ($key=='variable_cost') {
//echo $key . " " . $item . "\n";
$total += $item;
}
}
return $total;
}
echo sum_variable_cost( $data );
Basically it loops through the array and sees if there are other arrays and only adds values that contain the key variable_cost.
If you uncomment the echo line it will show this output:
variable_cost 25.3
variable_cost 30.32
variable_cost 30.32
variable_cost 42.31
variable_cost 104.4
variable_cost 65.28
297.93

Optimizing algorithm to avoid exaggerated script execution time

Yesterday I ask here Append array values to another array by keys comparison and I have tried a few things without success. I have two arrays $result and $result1. count($result) is 204640 and count($result1) is 129849 so they are huge. The arrays is the result of a PDO statement execution as shown in code below. This is an example for $result array:
'00180000015oGSWAA2' =>
array (
'accountId' => '00180000015oGSWAA2',
'npi' => '1053576223',
'firstname' => 'Jack',
'lastname' => 'Cheng',
'title' => '',
'accountLastModifiedDate' => '2014-09-09 17:37:15',
'suffix' => '',
'fax' => '',
'address1' => '853 N CHURCH ST',
'city' => 'SPARTANBURG',
'stateLicensedId' => '31191',
'state' => 'SC',
'phone' => '',
'zip' => '29303',
'address2' => '',
'addressLastModifiedDate' => '2014-09-04 08:44:17',
),
'00180000015oGeXAAU' =>
array (
'accountId' => '00180000015oGeXAAU',
'npi' => '1629067301',
'firstname' => 'Fred',
'lastname' => 'Thaler',
'title' => '',
'accountLastModifiedDate' => '2014-09-09 17:36:41',
'suffix' => '',
'fax' => '',
'address1' => '1 PEARL ST',
'city' => 'BROCKTON',
'stateLicensedId' => '58249',
'state' => 'MA',
'phone' => '',
'zip' => '2301',
'address2' => '',
'addressLastModifiedDate' => '2014-09-04 04:25:44',
)
And this is an example for $result1 array:
'001S000000nBvryIAC' =>
array (
'tid' => '04T800000008zySEAQ',
'acsLastModifiedDate' => '2015-01-06 17:19:48',
),
'00180000015oGeXAAU' =>
array (
'tid' => '04T800000008zzgEAA',
'acsLastModifiedDate' => '2015-01-07 04:06:40',
),
'001S000000nYWcYIAW' =>
array (
'tid' => '04T800000008zySEAQ',
'acsLastModifiedDate' => '2015-02-25 15:45:01',
),
As you can see $result[1] and $result1[1] shares the same keys, right? Ok, then what I need is to push the content of $result1[1] on the end of $result[1] and getting something like:
'00180000015oGeXAAU' =>
array (
'accountId' => '00180000015oGeXAAU',
'npi' => '1629067301',
'firstname' => 'Fred',
'lastname' => 'Thaler',
'title' => '',
'accountLastModifiedDate' => '2014-09-09 17:36:41',
'suffix' => '',
'fax' => '',
'address1' => '1 PEARL ST',
'city' => 'BROCKTON',
'stateLicensedId' => '58249',
'state' => 'MA',
'phone' => '',
'zip' => '2301',
'address2' => '',
'addressLastModifiedDate' => '2014-09-04 04:25:44',
'tid' => '04T800000008zzgEAA',
'acsLastModifiedDate' => '2015-01-07 04:06:40',
)
Meaning when keys are equal in both arrays then merge or append values from the second one into the first one. Right now my best approach is the following:
// PDO statement
$result = $stmt->fetchAll();
// PDO statement
$result1 = $stmt->fetchAll();
foreach ($result as $key => $row) {
foreach ($result1 as $key1 => $row1) {
if ($key === $key1) {
array_push($row, array_shift($row1));
}
}
}
var_dump($row);
But it takes an eternity due to arrays length, so any advice in how to speedup this?
UPDATE: almost a solution
Based on #decese solution I have rewrite this a bit so my apologies in first and take a look to this. Now I called arrays as $oneArr and $twoArr and also I write a small output examples (don't kill me just yet):
// var_export($oneArr)
'00180000015oGSWAA2' =>
array (
'target_id' => '00180000015oGSWAA2',
'firstname' => 'Jack',
),
'00180000015oGeXAAU' =>
array (
'target_id' => '00180000015oGeXAAU',
'firstname' => 'Fred',
)
// var_export($twoArr)
'001S000000nBvryIAC' =>
array (
'tid' => '04T800000008zySEAQ',
'acsLastModifiedDate' => '2015-01-06 17:19:48',
),
'00180000015oGeXAAU' =>
array (
'tid' => '04T800000008zzgEAA',
'acsLastModifiedDate' => '2015-01-07 04:06:40',
)
This is the ouput I want to achieve, meaning when keys are equal in both arrays then merge or append values from the second one into the first one:
'00180000015oGeXAAU' =>
array (
'target_id' => '00180000015oGeXAAU',
'firstname' => 'Fred',
'tid' => '04T800000008zzgEAA',
'acsLastModifiedDate' => '2015-01-07 04:06:40',
)
I have this done, again based on first answer which I thanks a lot for clear a bit things to me, with the following code:
// Fetch results from first SQL query
$result = $stmt->fetchAll();
// Fetch only two keys from the entire and put them on $oneArr
foreach ($result as $row) {
$oneArr[$row['target_id']] = [
'target_id' => $row['target_id'],
'firstname' => $row['firstname']
];
}
// Fetch results from second SQL query
// yes, var names are the same not matter, I will only use one time
$result = $stmt->fetchAll();
// Fetch only two keys from the entire and put them on $twoArr
foreach ($result as $row) {
$twoArr[$row['target_id']] = [
'tid' => $row['tid'],
'acslmd' => $row['acslmd']
];
}
$i = 0;
foreach ($oneArr as $keyOneArr => $valueOneArr) {
if (array_key_exists($keyOneArr, $twoArr)) {
array_push($oneArr[$keyOneArr], $twoArr[$keyOneArr]);
$i++;
}
}
var_export($oneArr);
But result is not the same as I want since I got this:
'00180000015oGeXAAU' =>
array (
'target_id' => '00180000015oGeXAAU',
'firstname' => 'Fred',
0 =>
array (
'tid' => '04T800000008zzgEAA',
'acslmd' => '2015-01-07 04:06:40',
),
),
How I can avoid the extra array on the result array?
PS: Times looks good now: Call time was 00:01:34
Looks like your arrays are actually indexed by the ids, so do this:
foreach ($result1 as $key => $value) {
if (isset($result[$key])) {
$result[$key] += $value;
}
}
Of course, doing all this work in the database using a JOIN would make the most sense to begin with, if possible.
You could use array_merge_recursive
See my working example: http://3v4l.org/hQERW
Note: in the provided data, only 00180000015oGeXAAU is common to both arrays, so it only merges the values for that key
Basically, just call
$result = array_merge_recursive($result, $result1);
PHP.net says:
array_merge_recursive() merges the elements of one or more arrays together so that the values of one are appended to the end of the previous one. It returns the resulting array.
If the input arrays have the same string keys, then the values for these keys are merged together into an array, and this is done recursively, so that if one of the values is an array itself, the function will merge it with a corresponding entry in another array too. If, however, the arrays have the same numeric key, the later value will not overwrite the original value, but will be appended.

cakephp combining associated array fields

I've an associated array with 20 elements whose child array looks like
(int) 2 => array(
'Comment' => array(
'id' => '5',
'user_id' => '13',
'time' => '2012-05-18 14:47:36'
),
'User' => array(
'name' => 'User name'
)
)
Now I want to extract the field name from its child array User with cakephp's set utility and append it to the child array Comment. Is there a one way step to do this other than using a for or foreach loop?
(int) 2 => array(
'Comment' => array(
'id' => '5',
'user_id' => '13',
'time' => '2012-05-18 14:47:36',
'name =>'User name'
)
)
It doesn't answer your question, but doing this with a foreach is a one way step too:
foreach ($arrays as $array)
$array['Comment']['name'] = $array['User']['name'];
I believe there's no need to use some utility, just for the sake of using an utility.
Especially that it'll do a foreach itself.

Ubercart uc_cart_get_contents get data from standard class

I'm writing a custom module for one of my projects and I'm having a bit of an issue. What I'm trying to do is get a piece of data from uc_cart_get_contents() into a variable so that I can use it in a calculation:
Here's my var_export:
array ( )array ( 0 => stdClass::__set_state(array( 'cart_item_id' => '5', 'cart_id' => '1', 'nid' => '9', 'qty' => '10', 'changed' => '1287074120', 'data' => array ( 'attributes' => array ( 3 => '4', ), 'shippable' => '1', 'restrict_qty' => '0', 'module' => 'uc_product', ), 'title' => 'Chicago Canyon', 'vid' => '9', 'cost' => 1.16, 'price' => 11.16, 'weight' => 0, 'module' => 'uc_product', 'model' => 'chicago-canyon-p-card-p-env', )), )
But what if I want to put the model of each item in the cart into a variable, and based upon that variable adjust the item's price.
If it was an array I would do this:
$items= uc_cart_get_contents();
$model = $items[model];
but that doesn't work, it's a std class. I'm so so lost. Please help!
If your asking how to access object propertiers you do so like this:
$model = $items->model;
for starters, uc_cart_get_contents() returns an array of objects. so, if you did:
$items=uc_cart_get_contents();
you would have to iterate over $items, and then get the specific data elements you want from each item.
for example:
$items = uc_cart_get_contents();
foreach ($items as $item)
{
$model = $item->model;
// whatever ...
}
hope that helps

Categories