Create array with Set Extract in Cakephp with conditions - arrays

I have the following array:
Array
(
[0] => Array
(
[id] => 4
[rate] => 82.50
[pounds] => 2
[ounces] => 3
[mailtype] => Package
[country] => UNITED KINGDOM (GREAT BRITAIN)
[svccommitments] => 1 - 3 business days
[svcdescription] => Global Express Guaranteed (GXG)
[maxdimensions] => Max. length 46", width 35", height 46" and max. length plus girth combined 108"
[maxweight] =>30
)
[1] => Array
(
[id] => 6
[rate] => 82.50
[pounds] => 2
[ounces] => 3
[mailtype] => Package
[country] => UNITED KINGDOM (GREAT BRITAIN)
[svccommitments] => 1 - 3 business days
[svcdescription] => Global Express Guaranteed Non-Document Rectangular
[maxdimensions] => Max. length 46", width 35", height 46" and max. length plus girth combined 108"
[maxweight] => 70
)
And I want to use CakePHP's Set:extract tools to filter this array on the 'maxweight', so all elements that have a 'maxweight' more than X and get an array made up of the 'rate' and 'svcdescription' fields ie:
Array (
[82.50] => Global Express Guaranteed Non-Document Rectangular
...
etc
)
Is this at all possible?

In my opinion, to get the most value out of Set::extract, it would be better to start with an array with a structure more like the following (otherwise I believe you'd have to run Set::extract inside a loop):
$array = array(
'Shipping' => array(
array (
"id" => 4,
"rate" => 82.50,
"pounds" => 2,
"ounces" => 3,
"mailtype" => "Package",
"country" => "UNITED KINGDOM (GREAT BRITAIN)",
"svccommitments" => "1 - 3 business days",
"svcdescription" => "Global Express Guaranteed (GXG)",
"maxdimensions" => 'Max. length 46", width 35", height 46" and max. length plus girth combined 108"',
"maxweight" => 30
),
array (
"id" => 6,
"rate" => 82.50,
"pounds" => 2,
"ounces" => 3,
"mailtype" => "Package",
"country" => "UNITED KINGDOM (GREAT BRITAIN)",
"svccommitments" => "1 - 3 business days",
"svcdescription" => "Global Express Guaranteed Non-Document Rectangular",
"maxdimensions" => 'Max. length 46", width 35", height 46" and max. length plus girth combined 108"',
"maxweight" => 70
)
)
);
Now you can use the path syntax for Set::extract() to extract elements that have a maxweight greater than $x.
$extracted = Set::extract($array, '/Shipping[maxweight>'.$x.']');
With this data, you can build the array you're looking for using the rates as keys and svcdescription as values using Set::combine().
$combined = Set::combine($extracted, '{n}.Shipping.rate', '{n}.Shipping.svcdescription');

I've never used this before, but thanks for encouraging me to read up on it.
Have you tried using Set::combine() ?
http://book.cakephp.org/view/662/combine

Why can't you just use a foreach loop to process through the array.
$returnArray = array();
// Where $x is weight amount you're testing against
foreach ($yourData as $eachData) {
if ($eachData['maxweight'] > $x) {
$returnArray[$eachData['rate']] = $eachData['svcdescription'];
}
}

Related

Google Analytics return row names instead of numeric index

I'm using Google Analytics API to populate a dashboard. I'm curious if there is a setting I am unaware of that can return the rows as follows:
[0] => Array
(
[ga:pagePath] => /
[ga:pageViews] => 856
)
Instead of just 0, 1, .etc. numerical arrays:
[columnHeaders] => Array
(
[0] => Array
(
[name] => ga:pagePath
[columnType] => DIMENSION
[dataType] => STRING
)
[1] => Array
(
[name] => ga:pageViews
[columnType] => METRIC
[dataType] => INTEGER
)
)
[totalsForAllResults] => Array
(
[ga:pageViews] => 2099
)
[rows] => Array
(
[0] => Array
(
[0] => /
[1] => 856
)
[1] => Array
(
[0] => /portfolio
[1] => 268
)
I know how to do this with array logic but was just curious if there was a setting or something I could query GA with to get the first format. Couldn't find any info elsewhere.
No there isn't, neither in v3 nor in v4 (it would be terribly inefficient to repeat the dimension names for each row).
What you can do is define the index of dimensions & metrics so you can refer to values by name instead of index (below example in JavScript):
var ga = {
pagePath: 0,
pageView: 1
}
rows[1][ga.pagePath]; // /portfolio
rows[2][ga.pageViews]; // 268

Combine/merge results from two queries from different databases

I am trying to produce a web report using PHP that takes a query from a SQL Server database for the main query, and another query from a PostgreSQL database.
What is the best way to merge the results? Currently I am outputting the results as arrays.
The two arrays are made up like so:
Array1
(
[0] => Array
(
[site_name] => TESTSITE
[status] => 1
)
)
Array2
(
[0] => Array
(
[site_name] => TESTSITE
[booking_id] => 2156
[jobresults_key] => 1239
[result] => 4
)
)
The common items are [site_name] in both arrays, and I want to display the [status] from array1 if there is nothing for the matching [site_name] in array2, if there is a matching [site_name] in array2 then it should display [result].
As long as the arrays are short and array1 is always larger, this should work fine.
$array1 = array(
array(
'site_name' => 'TESTSITE',
'status' => 1
),
array(
'site_name' => 'TESTSITE-2',
'status' => 1
)
);
$array2 = array(
array(
'site_name' => 'TESTSITE',
'booking_id' => 2156,
'jobresults_key' => 1239,
'result' => 4
)
);
foreach($array1 as &$item1){
foreach($array2 as $item2){
if( $item1['site_name'] === $item2['site_name'] ){
$item1 = array_replace($item1, $item2);
}
}
}
print_r($array1);

A hash::combine array

I have this array from a sql query :
[0] => Array
(
[T1] => Array
(
[First] => A
[Second] => Apples
[LastChild] => F
)
[0] => Array
(
[LastChildNb] => 23
)
)
I would like to have this result :
[0] => Array
(
[0] => Array
(
[First] => A
[Second] => Apples
[LastChild] => F
[LastChildNb] => 23
)
)
How do I do this ? I think I should use "hash::combine", but what would the code be ?
You could do something like this, with $arr being your array above:
$arr = array_reduce($arr, function(&$arr, $v) {
return array_merge($arr, (array) $v);
}, array());
You can do
array_merge($arr[0]['T1'], $arr[0][0])
Where $arr is defined as follows:
$arr = [0 => Array
(
'T1' => Array
(
'First' => 'A',
'Second' => 'Apples',
'LastChild' => 'F'
),
0 => Array
(
'LastChildNb' => 23
)
)];
For multiple records in $arr, you can simply cycle over all records and do this merge manually.
However, assuming you're getting the array as a result of a find() method, I suggest you consider using T1__LastChildNb as an alias within the 'fields' of your condition. Simply said, if you have a find like following:
$this->T1->find('all', ['fields' => 'T1.*, (SOME SUBQUERY) AS LastChildNb']);
then modifying it to be
$this->T1->find('all', ['fields' => 'T1.*, (SOME SUBQUERY) AS T1__LastChildNb']);
might be what you're looking for since it will return desired array directly (tested on 2.6).
Let me know if you're interested in more information.

how to sort array date wise in cakephp

I have 2 table booking and message , now I want to show booking request and message in inbox at a time.
$this->paginate = array(
'conditions' => $conditions,'limit' =>10,
'order'=>array('Booking.created'=>'DESC'));
$bookings = $this->paginate('Booking');
$this->paginate = array(
'conditions' => $conditions,'limit' =>10,
'order'=>array('MessageDetail.created'=>'DESC'));
$messages = $this->paginate('MessageDetail');
i have merge both table data ( array_merge($bookings, $messages); )
now i want to it sort date wise (or any conditions)
Array
(
[0] => Array
(
[Booking] => Array
(
[id] => 4
[host_id] => 21
[place_id] => 10
[room_id] => 13
[user_id] => 12
[message_detail_id] => 16
[created] => 2013-04-23 14:44:03
[accept_date] =>
[cancel_date] =>
)
)
[1] => Array
(
[Booking] => Array
(
[id] => 3
[host_id] => 21
[place_id] => 10
[room_id] => 13
[user_id] => 12
[message_detail_id] => 13
[created] => 2013-04-15 14:10:59
[accept_date] => 2013-04-15 14:40:47
[cancel_date] =>
)
)
[2] => Array
(
[MessageDetail] => Array
(
[id] => 17
[message_id] => 2
[user_id] => 12
[sender_id] => 21
[unread] => 0
[created] => 2013-04-24 12:11:47
)
)
[3] => Array
(
[MessageDetail] => Array
(
[id] => 15
[message_id] => 2
[user_id] => 12
[sender_id] => 21
[booking_id] => 3
[unread] => 0
[created] => 2013-04-15 15:01:12
)
)
)
Thanks in advance.
Option #1:
Create a third Model named "BookingAndMessage". You could use the Model's afterSave method (on both Booking and Message) to create a duplicate record in your new model. You could then query the BookingAndMessage in the proper sort order.
Option #2: To solve the problem, as it stands, you will want to use PHP's usort function (also explained here PHP Sort a multidimensional array by element containing date).
<?php
$BookingsAndMessages = array_merge($bookings, $messages);
function date_compare($a, $b)
{
$modelKeyA = array_key_exists('Booking',$a) ? 'Booking' : 'MessageDetail';
$modelKeyB = array_key_exists('Booking',$b) ? 'Booking' : 'MessageDetail';
$t1 = strtotime($a[$modelKeyA]['created']);
$t2 = strtotime($b[$modelKeyB]['created']);
return $t1 - $t2;
}
usort($BookingsAndMessages, 'date_compare');
// Would sort the merged records by `created` date
?>
The downside to option 2 is, you are going to have to create rules for each field (and sort direction).
Perhaps you should Union your queries first, the Order.
$bookings = $this->Bookings->find('all', [
'conditions' => $conditions,'limit' =>10,
]);
$messages = $this->find('all', [
'conditions' => $conditions,'limit' =>10
]);
$data = $bookings->union($messages);
// This works if your first selected field is the one you want to sort.
$data->epilog('ORDER BY 1 ASC');
reference:
How do you modify a UNION query in CakePHP 3?

CakePHP saving model using Session

I am saving form data in a Session, and trying to save to a model called Property using the session array. Please see the array below. I think it has something to do with the Session array but I am not sure.
When I try to save like so, it does not save:
$this->Property->save($propertyData) where $propertyData is the property array.
sql_dump:
INSERT INTO `fra`.`properties` (`type`, `address`, `city`, `state`, `zip`, `price`, `bed_rooms`, `bath_rooms`, `lot_size_sq_ft`)
VALUES ('0', '2720 Acapulco way', 'modesto', 'ca', '95355', 310000, 4, 3, 6040)
The session array is:
Array
(
[house_details] => Array
(
[form] => Array
(
[section] => house_details
)
[Property] => Array
(
[type] => 0
[address] => 2720 Acapulco way
[city] => modesto
[state] => ca
[zip] => 95355
[price] => 310000
[prop_year_build] => 2007
[prop_year_remodel] =>
[bed_rooms] => 4
[bath_rooms] => 3
[garage_spaces] => 3
[lot_size_sq_ft] => 6040
[house_size_sq_ft] => 3720
[stories] => 2
[condition_rating] => 8
)
You should be able to do this quite simply. You probably have a problem with $propertyData being set as the wrong thing so it doesn't provide a valid value for the model save.
What do you get if you do debug($propertyData)?
Does this work?
$propertyData = $this->Session->read('house_details.Property');
$this->Property->save(propertyData);

Resources