In my application , I have few parameters (zone_id, startdate, enddate, brand, model) which I get from my UI form . Each of these parameters is an array containing 1 or more parameters .
My form parameters looks something like this :
Array
(
[sel_date_option] => today
[startdate] => 2011-09-19
[enddate] => 2011-09-19
[zone_id] => 1576,1562,1561
[model] => Array
(
[0] => A300
)
[brand] => Array
(
[0] => ACTS
)
)
Now , I want to generate keys which are combinations of these parameters . They would be something like :
[zone_id]_[model]_[brand]_[model]_[startdate]_[enddate]
This reflect all the possible arrangements of the above values .
For the above inputs, I should get the following keys :
1576_ACTS_A300_2011-09-19
1562_ACTS_A300_2011-09-19
1561_ACTS_A300_2011-09-19
Inside of giving the same startdate and enddate once can also enter a period like from 2011-09-19 to 2011-09-21.
What I am doing is I am using nested looping through all the parameter array and then creating a complex array of arrays something like the following :
Array
(
[0] => Array
(
[0] => 1576_DZ_A300
)
[1] => Array
(
[0] => 1576_DZ_A300
[1] => 1562_DZ_A300
)
[2] => Array
(
[0] => 1576_DZ_A300
[1] => 1562_DZ_A300
[2] => 1561_DZ_A300
)
[3] => Array
(
[0] => 1576_DZ_A300
[1] => 1562_DZ_A300
[2] => 1561_DZ_A300
[3] => 1563_DZ_A300
)
)
What I am doing is first I creating an array of all zones as :
Array
(
[0] => 1576
[1] => 1562
[2] => 1561
[3] => 1563
)
Then I am looping it using a nested loop for all the possible models and brands array like this :
function getInventoryData($criteria)
{
$index = "";
if($criteria['zone_id']!='')
{
$zone = explode(',', $criteria['zone_id']);
for($i=0;$i<count($zone);$i++)
{
$index[] .= $zone[$i];
}
echo '<pre>';print_r($index);exit;
}
if(!empty($criteria['model']))
{
foreach($index as $key=>$value)
{
foreach($criteria['model'] as $model)
{
$temparr[] = $index[$key].'_'.$model;
}
$index[$key] = $temparr;
}
}
Now , is there any other efficient method to achieve this ?
Moreover , there is another overhead associated with the above method :
While reading the generated keys , I have to loop through all the levels and in case of large sequence of data , the complexity can be really a matter of concern.
If I understand what you are trying to do correctly, this the most efficient method I can come up with for doing the above:
function getInventoryData ($arr) {
// Make sure all required keys are set
if (!isset($arr['zone_id'],$arr['model'],$arr['brand'],$arr['startdate'],$arr['enddate'])) return FALSE;
// Make a date string for the end of the keys
$dateStr = $arr['startdate'].(($arr['startdate'] == $arr['enddate']) ? '' : '_'.$arr['enddate']);
// Normalise the data
if (!count($arr['zone_id'] = array_unique(explode(',',$arr['zone_id']))) || !count($arr['brand'] = array_unique($arr['brand'])) || !count($arr['model'] = array_unique($arr['model']))) return FALSE;
// Get all possible permutations
$result = array();
foreach ($arr['zone_id'] as $zone) foreach ($arr['brand'] as $brand) foreach ($arr['model'] as $model) $result[] = "{$zone}_{$brand}_{$model}_{$dateStr}";
// Return the result
return $result;
}
Related
I am trying to use the Hubspot API (http://developers.hubspot.com/docs/overview) to loop through all deals and find only those which are current and then do something with those deals.
No matter what I try to do I cannot get my head around how I access the data I need - below is an example of the output.
In the API there are lots of items like dealstage below and the value field under these is what I need to access - for example in this case the deal is closedlost. Another example would be amount which would also have an entry in value so I can then see the deal value.
I want to loop through all deals and for each deal get the dealstage, amount, last update, owner and so on. Each of these are contained in an array of the same layout as [dealstage] below with a value
I have gotten to where I can print the dealstage value for each deal but it doesn't really help - is there a better way of doing this?
foreach ($list['deals'] as $line) {
foreach ($line['properties'] as $row => $value) {
if ($row=="dealstage") {
$stage=$value['value'];
print $stage."<br>";
}
}
}
Example array:
Array
(
[deals] => Array
(
[0] => Array
(
[portalId] => 12345
[dealId] => 67890
[isDeleted] =>
[associations] => Array
(
[associatedVids] => Array
(
[0] => 4051
)
[associatedCompanyIds] => Array
(
[0] => 23456
)
[associatedDealIds] => Array
(
)
)
[properties] => Array
(
[dealstage] => Array
(
[value] => closedlost
)
[createdate] => Array
(
[value] => 1471334633784
)
[amount] => Array
(
[value] => 1000
)
Would something like this be what you are looking for. Loop through the array picking out the items you are interested in and place them in a nice simple array for you to use later when building your email.
$for_email = array();
foreach ($list['deals'] as $line) {
$t = array();
if (isset($line['properties']['dealstage']['value'])) {
$t['dealstage'] = $line['properties']['dealstage']['value'];
}
if (isset($line['properties']['amount']['value'])) {
$t['amount'] = $line['properties']['amount']['value'];
}
if (isset($line['properties']['createdate']['value'])) {
$t['createdate'] = $line['properties']['createdate']['value'];
}
// any other data you want to capture
// put this data in the new array
$for_email[] = $t;
}
// check what the new array looks like
print_r($for_email);
I've got an array, called $data which needs to be updated with data from an ajax call.
There are two variables sent via an ajax call (with example inputs):
sectionDetails:
[111][0][2][0][service_providers][]
serviceProvider:
Google
The serviceProvider is the data, and the sectionDetails is the array in which the serviceProvider should be in, in the $data array.
What I need is the $data array to end up as:
$data = Array
(
[111] => Array
(
[0] => Array
(
[2] => Array
(
[0] => Array
(
[service_providers] => Array
(
[0] = Google
)
)
)
)
)
)
This way, I can dynamically input data into any cell and then later I can update specific arrays (e.g. $data[111][0][2][0][service_providers][0] = "Yahoo";
The $_POST['sectionDetails'] is however a string which is where the issue is.
Is there a way to change this string to an array that can then be appended to the main $data array (and in the case of an existing value in the same section, update the value)?
Hope that makes sense.
If you create a function like this:
function setToPath(&$data, $path, $value){
//$temp will take us deeper into the nested path
$temp = &$data;
//notice this preg_split logic is specific to your path syntax
$exploded = preg_split("/\]\[/", rtrim(ltrim($path,"["),"]"));
// Where $path = '[111][0][2][0][service_providers][]';
// $exploded =
// Array
// (
// [0] => 111
// [1] => 0
// [2] => 2
// [3] => 0
// [4] => service_providers
// [5] =>
// )
foreach($exploded as $key) {
if ($key != null) {
$temp = &$temp[$key];
} else if(!is_array($temp)) {
//if there's no key, i.e. '[]' create a new array
$temp = array();
}
}
//if the last index was '[]', this means push into the array
if($key == null) {
array_push($temp,$value);
} else {
$temp = $value;
}
unset($temp);
}
You can use it like this:
setToPath($data, $_POST['sectionDetails'], $_POST['serviceProvider']);
print_r($data) will return:
Array
(
[111] => Array
(
[0] => Array
(
[2] => Array
(
[0] => Array
(
[service_providers] => Array
(
[0] => Google
)
)
)
)
)
)
Being very careful and depending on the situation, you could use eval:
eval("\$data$sectionDetails = '$serviceProvider';");
print_r($data) will return:
Array
(
[111] => Array
(
[0] => Array
(
[2] => Array
(
[0] => Array
(
[service_providers] => Array
(
[0] => Google
)
)
)
)
)
)
Caution
The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.
I have a multidimensional array, and I am trying to sort it so that the array with the most entries comes first, etc... Then if two arrays have the same number of entries, they should be arranged alphabetically. Also, if the entries could be sorted by the key, 'name', I think that would be great. As you can see below, I am using ldap_sort to sort by 'name'. But I'm sure calling too many sort functions is bad practice.
if ($conn == True ) {
Try {
// Authenticate
$bind = ldap_bind($conn, $user, $pass);
// Search AD
$search = ldap_search($conn, $dn, $filter, $attr);
// Sort
ldap_sort($conn, $search, 'name');
// Retrieve Data
$records = ldap_get_entries($conn, $search);
Foreach ($records as $record) {
if(is_array($record) && array_key_exists('l', $record)) {
$locations[$record['l'][0]][] = $record;
}
continue;
}
} finally {
// Close Connection
ldap_close($conn);
}
} else {
trigger_error('Unable_To_Connect_To_Server');
}
// Sort Location By Number Of Entries
array_multisort(array_map('count', $locations), SORT_DESC, $locations);
I guess to put it layman's terms.. Sorting entries alphabetically by their 'name' value, should be inherent. Then the arrays should be sorted by the number of entries, and if any arrays have the same number of entries they should be sorted alphabetically.
P.S. - I'm asking for help because it's hard for me to understand multidimensional arrays (especially those returned by ldap_search) and sorting them is even more mind-boggling to me.
EDIT Like I said, arrays confuse me but hopefully the below accurately depicts my intentions:
Array (
[Location1] => Array (
[0] => Array (
[l] => Array (
[count] => 1
[0] => Location1
)
[0] => l
[telephonenumber] => Array (
[count] => 1
[0] => XXX.XXX.XXXX
)
[1] => telephonenumber
[department] => Array (
[count] => 1
[0] => Department1
)
[2] => department
[name] => Array (
[count] => 1 [0] => User1
)
[3] => name
[ipphone] => Array (
[count] => 1
[0] => IPPhone1
)
[4] => ipphone
[mail] => Array (
[count] => 1
[0] => user#domain.com
)
[5] => mail
[count] => 6
[dn] => DistinguishedName1
)
)
)
I cut the above short (there are hundreds of records returned) and I'm not sure I ended it correctly. But I am essentially parsing the information to output something like below.
c_Location1
a_user1
b_user1
c_user1
a_Location2
a_user2
b_user2
b_location3
a_user3
b_user3
Write a function that compares the lengths of the arrays. If they're the same, it compares the name entries. Use that as the callback function for usort.
usort($records, function($x, $y) {
if (count($x) == count($y)) {
$u1 = $x['name'][0];
$u2 = $y['name'][0];
return $u1 < $u2 ? -1 :
($u1 > $u2 ? 1 : 0);
} else {
return count($y) - count($x);
}
});
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'];
I'm looking for a way to make it so cake returns all database data in the same format/structure... Currently it returns two different types of format depending on the relationship.
If a model 'B' is associated with the current model 'A' being queried it will then place model associations for 'B' underneath it as you can see in [User] below. I want it so that all queries use that structure.
example:
$this->find('all', ....
returns:
Array
(
[0] => Array
(
[UserGroup] => Array
(
[id] => 53
[user_id] => 100003332014851
[media_id] =>
[name] => john
[description] => qwasdfad
)
[User] => Array
(
[id] => 100003332014851
[session_id] => ssm2qbrotmm13ho1ipm8ii2492
[username] =>
[password] => -1
[Planner] => Array
(
)
[Purchase] => Array
(
)
[Listing] => Array
(
)
)
)
I want this to look like:
Array
(
[0] => Array
(
[UserGroup] => Array
(
[id] => 53
[user_id] => 100003332014851
[media_id] =>
[name] => john
[description] => qwasdfad
[User] => Array
(
[id] => 100003332014851
[session_id] => ssm2qbrotmm13ho1ipm8ii2492
[username] =>
[password] => -1
[Planner] => Array
(
)
[Purchase] => Array
(
)
[Listing] => Array
(
)
)
)
)
)
In CakePHP, the find() method return data like your first format. But If you want to format like second one then you have to process it by hand (try to avoid this if possible)
$data = $this->find('all');
$assocs = Set::extract('/User', $data); // extracting all `User` array
foreach($assocs as $key => $assoc) {
unset($data[$key]['User']); // removing the associate `User` from `$data`
$data[$key]['UserGroup']['User'] = $assoc['User']; // adding associate under `UserGroup`
}
ended up doing this... it changes the output to what we need. The top level item does not have a header which is fine I just adjusted our scripts for that... maybe this will help somebody else if they need a custom idea
also no guarantee this covers all possible results but so far it works with all the queries we have.
class AppModel extends Model {
function afterFind($results, $primary) {
//if this is a primary, structure like a secondary so entire site is same format
if ($primary) {
$class = get_class($this);
//simple fix for primary
foreach ($results as $key => $result) {
$result = $this->formatData($result, $class);
$results[$key] = $result;
}
}
return $results;
}
function formatData($result, $class) {
$array = array();
if (isset($result[$class])) {
$array = $result[$class];
unset($result[$class]);
}
$array += $result;
return $array;
}
You can also use contain in this case along with find as UserGroup.User for your desired result