How to make this multidimensional array into three specified parts? - php

I have this array
$data = [
0 => [
'id' => '114',
'organization_name' => 'ABC Ltd',
'organization_telephone' => '01234 112233',
'organization_email' => 'admin#example.com',
'organization_url' => 'http://www.example.com',
'order_id' => '119',
'order_delivery_address_1' => '55',
'order_delivery_address_2' => 'High Street',
'order_delivery_address_3' => '',
'order_delivery_postcode' => 'LL27 0YX',
'product_colour_name' => 'Red',
'product_size_name' => '8/9',
'product_price' => '7.5',
'product_quantity' => '10',
'product_line_price' => '75',
],
];
And I want to divide it into 3 arrays as below:
$orgnization_details = [
'id' => '114',
'organization_name' => 'ABC Ltd',
'organization_telephone' => '01234 112233',
'organization_email' => 'admin#example.com',
'organization_url' => 'http://www.example.com',
]
$order_details = [
'order_id' => '119',
'order_delivery_address_1' => '55',
'order_delivery_address_2' => 'High Street',
'order_delivery_address_3' => '',
'order_delivery_postcode' => 'LL27 0YX',
]
$product_details = [
'product_colour_name' => 'Red',
'product_size_name' => '8/9',
'product_price' => '7.5',
'product_quantity' => '10',
'product_line_price' => '75',
]
I tried using array_filter for orgnization_details as below
foreach ($data as $details)
{
$orgnization_details = array_filter($details, function($key) { return $key <= 'organization_url'; }, ARRAY_FILTER_USE_KEY);
}
But it didn't work as expected.
Please help me with this.

You are very close.
The array_filter() needs to be modified to check if the beginning of the key is a specific string:
$orgnization_details = array_filter($details, function($key){
// do the first 13 chars equal "organization_" or is the key "id"?
return substr( $key, 0, 13 ) === 'organization_' || $key === 'id';
}, ARRAY_FILTER_USE_KEY);
// Do similar logic for setting $order_details
// Do similar logic for setting $product_details

You could define the keys and check for an intersection of the keys in the main array:
$orginazation_keys = array_flip(['id',
'organization_name',
'organization_telephone',
'organization_email',
'organization_url' ]);
$orgnization_details = array_intersect_key($data[0], $orginazation_keys);
Or you can grep for them since they follow a pattern:
$orgnization_details = array_intersect_key($data[0],
array_flip(preg_grep('/^(organization|id)/', array_keys($data[0]))));

<?php
$data = [
0 => [
'id' => '114',
'organization_name' => 'ABC Ltd',
'organization_telephone' => '01234 112233',
'organization_email' => 'admin#example.com',
'organization_url' => 'http://www.example.com',
'order_id' => '119',
'order_delivery_address_1' => '55',
'order_delivery_address_2' => 'High Street',
'order_delivery_address_3' => '',
'order_delivery_postcode' => 'LL27 0YX',
'product_colour_name' => 'Red',
'product_size_name' => '8/9',
'product_price' => '7.5',
'product_quantity' => '10',
'product_line_price' => '75',
],
];
$prefix_map = [
'id' => 'organization_details',
'organization' => 'organization_details',
'order' => 'order_details',
'product' => 'product_details'
];
foreach($data[0] as $k => $v) {
$key_prefix = explode('_', $k)[0];
$new_key = $prefix_map[$key_prefix];
$out[$new_key][$k] = $v;
}
extract($out);
var_export($organization_details);
Output:
array (
'id' => '114',
'organization_name' => 'ABC Ltd',
'organization_telephone' => '01234 112233',
'organization_email' => 'admin#example.com',
'organization_url' => 'http://www.example.com',
)
This creates a new multi-dimensional array with the corresponding associated keys by mapping the existing key prefixes (part before the underscore). Then it's just a case of using extract on that array to create the named variables.
This results in the three variables: $organization_details, $order_details and $product_details that you desire.

If your sub-arrays are consistently in the same order you can simply slice:
<?php
$data = [
0 => [
'id' => '114',
'organization_name' => 'ABC Ltd',
'organization_telephone' => '01234 112233',
'organization_email' => 'admin#example.com',
'organization_url' => 'http://www.example.com',
'order_id' => '119',
'order_delivery_address_1' => '55',
'order_delivery_address_2' => 'High Street',
'order_delivery_address_3' => '',
'order_delivery_postcode' => 'LL27 0YX',
'product_colour_name' => 'Red',
'product_size_name' => '8/9',
'product_price' => '7.5',
'product_quantity' => '10',
'product_line_price' => '75',
]
];
$first = $data[0];
$organisation_details = array_slice($first, 0, 5);
$order_details = array_slice($first, 5, 5);
$product_details = array_slice($first, -5);
var_export($organisation_details);
var_export($order_details);
var_export($product_details);
Output:
array (
'id' => '114',
'organization_name' => 'ABC Ltd',
'organization_telephone' => '01234 112233',
'organization_email' => 'admin#example.com',
'organization_url' => 'http://www.example.com',
)array (
'order_id' => '119',
'order_delivery_address_1' => '55',
'order_delivery_address_2' => 'High Street',
'order_delivery_address_3' => '',
'order_delivery_postcode' => 'LL27 0YX',
)array (
'product_colour_name' => 'Red',
'product_size_name' => '8/9',
'product_price' => '7.5',
'product_quantity' => '10',
'product_line_price' => '75',
)

Related

Filter and re-format a given multi-dimensional array (php)

I have been given a dataset by my tutor and asked to carry out the following:
// make a function
// get skus of which the figure of the average monthly sales unit is equal or greater than 350
// array in the following format:
[
'id' => 11102,
'sku' => 'TEST_3',
'alternates' => [
'asin' => [
'code' => '50',
'value' => 'JL1235',
],
'barcode' => [
'code' => '10',
'value' => 'JS160694',
],
],
'commodityCode' => '9989898889',
'price' => [
'value' => 145.99,
],
'instructions' => [
'picking' => [
'code' => 'PICK',
'value' => 'I\'VE JUST HAD AN UNHAPPY LOVE AFFAIR, SO I DON\'T SEE WHY ANYBODY ELSE SHOULD HAVE A GOOD TIME.',
],
],
'quantity' => [
'inner' => 100,
'masterCarton' => 200,
'pallet' => 300,
],
'averageMonthlyUnitSales' => 100,
'created_at' => '2022-03-13 04:14:12'
],
Example dataset is here:
$data = [
[
'id' => '9947',
'sku' => 'test_1',
'asin_code' => '50',
'asin_value' => '',
'barcode' => '10',
'barcode_value' => 'js160694',
'commodityCode' => '9989898889',
'price' => '120.50',
'picking_instruction_code' => 'PICK',
'picking_instruction_value' => '',
'qty_inner' => '120',
'qty_masterCarton' => '200',
'qty_pallet' => '1200',
'averageMonthlyUnitSales' => '750',
'created_at' => '2019-02-23T01:54:14.957299+00:00'
],
[
'id' => '10921',
'sku' => 'test_2',
'asin_code' => '50',
'asin_value' => 'bx12345',
'barcode' => '10',
'barcode_value' => 'jb170931',
'commodityCode' => '9989898889',
'price' => '20.59',
'picking_instruction_code' => 'PICK',
'picking_instruction_value' => 'It\'s only half completed, I\'m afraid',
'qty_inner' => '70',
'qty_masterCarton' => '250',
'qty_pallet' => '270',
'averageMonthlyUnitSales' => '120',
'created_at' => '2021-12-23T11:41:31.193982+00:00'
],
[
'id' => '11102',
'sku' => 'test_3',
'asin_code' => '50',
'asin_value' => 'jl1235',
'barcode' => '10',
'barcode_value' => 'js160694',
'commodityCode' => '9989898889',
'price' => '145.99',
'picking_instruction_code' => 'PICK',
'picking_instruction_value' => 'I\'ve just had an unhappy love affair, so I don\'t see why anybody else should have a good time.',
'qty_inner' => '100',
'qty_masterCarton' => '200',
'qty_pallet' => '300',
'averageMonthlyUnitSales' => '100',
'created_at' => '2022-03-13T04:14:12.11.093745 +00:00'
],
];
I can perform the first part of the assignment (filter for averageMonthlyUnitSales>350) by carrying out something like:
$filtered_array= array_filter($data, function($item){
return ($item['averageMonthlyUnitSales']>350);
});
But I am not too sure how I can go about getting a new array in the required format?
The only way I can see to simply do both is as follows.
$data = [
[
'id' => '9947',
'sku' => 'test_1',
'asin_code' => '50',
'asin_value' => '',
'barcode' => '10',
'barcode_value' => 'js160694',
'commodityCode' => '9989898889',
'price' => '120.50',
'picking_instruction_code' => 'PICK',
'picking_instruction_value' => '',
'qty_inner' => '120',
'qty_masterCarton' => '200',
'qty_pallet' => '1200',
'averageMonthlyUnitSales' => '750',
'created_at' => '2019-02-23T01:54:14.957299+00:00'
],
[
'id' => '10921',
'sku' => 'test_2',
'asin_code' => '50',
'asin_value' => 'bx12345',
'barcode' => '10',
'barcode_value' => 'jb170931',
'commodityCode' => '9989898889',
'price' => '20.59',
'picking_instruction_code' => 'PICK',
'picking_instruction_value' => 'It\'s only half completed, I\'m afraid',
'qty_inner' => '70',
'qty_masterCarton' => '250',
'qty_pallet' => '270',
'averageMonthlyUnitSales' => '120',
'created_at' => '2021-12-23T11:41:31.193982+00:00'
],
[
'id' => '11102',
'sku' => 'test_3',
'asin_code' => '50',
'asin_value' => 'jl1235',
'barcode' => '10',
'barcode_value' => 'js160694',
'commodityCode' => '9989898889',
'price' => '145.99',
'picking_instruction_code' => 'PICK',
'picking_instruction_value' => 'I\'ve just had an unhappy love affair, so I don\'t see why anybody else should have a good time.',
'qty_inner' => '100',
'qty_masterCarton' => '200',
'qty_pallet' => '300',
'averageMonthlyUnitSales' => '100',
'created_at' => '2022-03-13T04:14:12.11.093745 +00:00'
],
];
$new = [];
foreach ($data as $line){
if ( $line['averageMonthlyUnitSales'] > 350 ){
// reformat the array
$new = [
'id' => $line['id'],
'sku' => $line['sku'],
'alternates' => ['asin' => ['code'=>$line['asin_code'], 'value'=>$line['asin_value'] ],
'barcode' => ['code'=> $line['barcode'], 'value' => $line['barcode_value']]
],
'commodityCode' => $line['commodityCode'],
'price' => [ 'value' => $line['price'] ],
'instructions' => ['picking' => ['code' => $line['picking_instruction_code'], 'value'=> $line['picking_instruction_value']]
],
'quantity' =>['inner' =>$line['qty_inner'], 'masterCarton' =>$line['qty_masterCarton'], 'pallet'=>$line['qty_pallet']],
'averageMonthlyUnitSales'=>$line['averageMonthlyUnitSales'],
'created_at'=>$line['averageMonthlyUnitSales']
];
}
}
print_r($new);
RESULT
PHP 8.1.3
Array
(
[id] => 9947
[sku] => test_1
[alternates] => Array
(
[asin] => Array
(
[code] => 50
[value] =>
)
[barcode] => Array
(
[code] => 10
[value] => js160694
)
)
[commodityCode] => 9989898889
[price] => Array
(
[value] => 120.50
)
[instructions] => Array
(
[picking] => Array
(
[code] => PICK
[value] =>
)
)
[quantity] => Array
(
[inner] => 120
[masterCarton] => 200
[pallet] => 1200
)
[averageMonthlyUnitSales] => 750
[created_at] => 750
)

Create Array From Key

Thank you in advance. Is there any way to create a multidimensional array from key names.
$array = array(
'brand/name' => 'BRAND_NAME',
'brand/model' => 'MODEL_NO',
'brand/inv/qty' => '20',
'brand/inv/cost' => '30',
'wh' => 'NY',
'brand/inv/sales' => '40'
);
Transform to this array.
$array = array(
'brand' => array(
'name' => 'BRAND_NAME',
'model' => 'MODEL_NO',
'inv' => array(
'qty' => 20,
'cost' => 30,
'sales' => 40,
)
),
'wh' => 'NY'
);
Thank you !
Try my code (I used the reference operator "&" to get the successive inner arrays):
Input array:
$array = array(
'brand/name' => 'BRAND_NAME',
'brand/model' => 'MODEL_NO',
'brand/inv/qty' => '20',
'brand/inv/cost' => '30',
'wh' => 'NY',
'brand/inv/sales' => '40'
);
php code:
<?php
$resultArray = array();
foreach($array as $path => $element) {
$pathArray = explode("/", $path);
$auxRef = &$resultArray;
foreach($pathArray as $pathPart) {
if(! array_key_exists($pathPart, $auxRef)) {
$auxRef[$pathPart] = array();
}
$auxRef = &$auxRef[$pathPart];
}
$auxRef = $element;
unset($auxRef);
}
?>
Result array:
array ( 'brand' => array ( 'name' => 'BRAND_NAME', 'model' => 'MODEL_NO', 'inv' => array ( 'qty' => '20', 'cost' => '30', 'sales' => '40', ), ), 'wh' => 'NY', )

PHP: Compare key value of objects

I have two arrays each one contain a set of objects
$input = [
(object)[
'id' => 2,
'number' => 54523,
'date' => '2019-12-17',
'book_for' => 'tttt',
'subject' => 'tttt',
'content' => 'ttt',
'language' => 'Arabic',
'cpfor' => 'tt',
'book_key' => '2WHae',
'note' => 'ttt',
'type' => 'Internal',
'pid' => 2,
'bookid' => 2,
'process' => 'STA',
],
];
and the second array is
$answers = [
(object)[
'aid' => 1,
'a_number' => 0,
'answer_of' => 1,
'answer_date' => '2019-12-17 00:00:00',
'answer_for' => 'xcc',
'answer_subject' => 'DSF',
'answer_content' => 'FSD',
'language' => '',
'cpfor' => 'WE',
'note' => 'EWWE',
],
(object)[
'aid' => 2,
'a_number' => 0,
'answer_of' => 2,
'answer_date' => '2019-12-19 00:00:00',
'answer_for' => 'answer for tt',
'answer_subject' => 'answer for tt',
'answer_content' => 'answer for tt',
'language' => 'Arabic',
'cpfor' => 'answer for ttvv',
'note' => 'answer for tt',
],
];
I want looping through and compare the value of id key in first array with value of answer_of key in second array if the id is not the same answer_of then return this object else ignore in other mean if id is not exist in second array(answer_of) return the object with all key and values else ignore
i tried the below function but even get those are exist in second array
function unanswered2($array1, $array2)
{
if (!(empty($array2))) {
$unanswered_arrays = [];
foreach ($array1 as $b) {
foreach ($array2 as $a) {
if ($b->bookid != $a->answer_of) {
array_push($unanswered_arrays, (object)$b);
}
}
}
return $unanswered_arrays;
}
return $array1;
}
anyone can tell where i have an error or any suggestion
the result is
$result=unanswered2($input,$answers);
$result= [
(object)[
'id' => 2,
'number' => 54523,
'date' => '2019-12-17',
'book_for' => 'tttt',
'subject' => 'tttt',
'content' => 'ttt',
'language' => 'Arabic',
'cpfor' => 'tt',
'book_key' => '2WHae',
'note' => 'ttt',
'type' => 'Internal',
'pid' => 2,
'bookid' => 2,
'process' => 'STA',
],
];
it should ignore it not return
I think the simplest solution is to use array_filter and a prepared list of answer_of values (for which you can use array_column).
Here's an example:
function findUnanswered(array $questions, array $answers): array
{
// use array_column to prepare a list of `answer_of` values
// *array_flip* them, so we can later use isset for better performance
$availableAnswers = array_flip(array_column($answers, 'answer_of'));
// filter all questions
return array_filter(
$questions,
// by a callback function, that
static function (object $question) use($availableAnswers): bool {
// ^ which we *use* from the outer scope
// |
// checks if the question id is [not set]* in +
// (* meaning no answer exists)
return !isset($availableAnswers[$question->id]);
}
);
}
Demo: https://3v4l.org/ZKlNn
I've read your comment to the prev my answer...
function getDiff($ar1, $ar2){
return array_filter($ar2, function($obj) use ($ar1) {
foreach($ar1 as $obj1){
return $obj1->bookid !== $obj->answer_of;
}
}, ARRAY_FILTER_USE_BOTH);
}
print_r(getDiff($input,$answers));
Output:
Array
(
[0] => stdClass Object
(
[aid] => 1
[a_number] => 0
[answer_of] => 1
[answer_date] => 2019-12-17 00:00:00
[answer_for] => xcc
[answer_subject] => DSF
[answer_content] => FSD
[language] =>
[cpfor] => WE
[note] => EWWE
)
)
https://3v4l.org/oGQWS
Provided you don't care about the original keys in the answers array.
Input:
<?php
$input = [
(object)[
'id' => 2,
'number' => 54523,
'date' => '2019-12-17',
'book_for' => 'tttt',
'subject' => 'tttt',
'content' => 'ttt',
'language' => 'Arabic',
'cpfor' => 'tt',
'book_key' => '2WHae',
'note' => 'ttt',
'type' => 'Internal',
'pid' => 2,
'bookid' => 2,
'process' => 'STA',
],
];
$answers = [
(object)[
'aid' => 1,
'a_number' => 0,
'answer_of' => 1,
'answer_date' => '2019-12-17 00:00:00',
'answer_for' => 'xcc',
'answer_subject' => 'DSF',
'answer_content' => 'FSD',
'language' => '',
'cpfor' => 'WE',
'note' => 'EWWE',
],
(object)[
'aid' => 2,
'a_number' => 0,
'answer_of' => 2,
'answer_date' => '2019-12-19 00:00:00',
'answer_for' => 'answer for tt',
'answer_subject' => 'answer for tt',
'answer_content' => 'answer for tt',
'language' => 'Arabic',
'cpfor' => 'answer for ttvv',
'note' => 'answer for tt',
],
];
Method:
$unanswered = array_diff_key(
array_column($answers, null, 'answer_of'),
array_column($input, null, 'id')
);
var_export($unanswered);
Output:
array (
1 =>
stdClass::__set_state(array(
'aid' => 1,
'a_number' => 0,
'answer_of' => 1,
'answer_date' => '2019-12-17 00:00:00',
'answer_for' => 'xcc',
'answer_subject' => 'DSF',
'answer_content' => 'FSD',
'language' => '',
'cpfor' => 'WE',
'note' => 'EWWE',
)),
)

How to get unique values from an array?

I have address array. I want to get unique address records from below array. I have used lots of logic but all fails to extract unique address. If we get any differences between keys like address_one, address_two etc. with another one, then I will consider as unique, but here some array values same with others.
Array
(
0 => Array
(
'address_one' => 'qqqqqqqqqq',
'address_two' => 'wwwwww',
'zipcode' => '212121',
'country_id' => '1',
'country_name' => 'United States',
'state_id' => '5',
'state_name' => 'AP',
'city_id' => '3',
'city_name' => 'Bhopal'
),
1 => Array
(
'address_one' => 'lkl',
'address_two' => 'ik2',
'zipcode' => '564564',
'country_id' => '1',
'country_name' => 'United States',
'state_id' => '1',
'state_name' => 'Madhya Pradesh',
'city_id' => '1',
'city_name' => 'Indore'
),
2 => Array
(
'address_one' => 'ace1',
'address_two' => 'caldrys1',
'zipcode' => '564561',
'country_id' => '91',
'country_name' => 'Guinea',
'state_id' => '3',
'state_name' => 'AL',
'city_id' => '3',
'city_name' => 'Bhopal'
),
3 => Array
(
'address_one' => '',
'address_two' => '',
'zipcode' => '',
'country_id' => '',
'country_name' => '',
'state_id' => '',
'state_name' => '',
'city_id' => '',
'city_name' => ''
),
4 => Array
(
'address_one' => '',
'address_two' => '',
'zipcode' => '',
'country_id' => '',
'country_name' => '',
'state_id' => '',
'state_name' => '',
'city_id' => '',
'city_name' => ''
),
5 => Array
(
'address_one' => 'lkl',
'address_two' => 'ik2',
'zipcode' => '564564',
'country_id' => '1',
'country_name' => 'United States',
'state_id' => '1',
'state_name' => 'Madhya Pradesh',
'city_id' => '1',
'city_name' => 'Indore'
),
6 => Array
(
'address_one' => 'Ace',
'address_two' => 'Matru Line',
'zipcode' => '483504',
'country_id' => '100',
'country_name' => 'India',
'state_id' => '1',
'state_name' => 'Madhya Pradesh',
'city_id' => '2',
'city_name' => 'Katni'
),
7 => Array
(
'address_one' => 'lkl',
'address_two' => 'ik2',
'zipcode' => '564564',
'country_id' => '1',
'country_name' => 'United States',
'state_id' => '1',
'state_name' => 'Madhya Pradesh',
'city_id' => '1',
'city_name' => 'Indore'
),
8 => Array
(
'address_one' => 'ace1',
'address_two' => 'caldrys1',
'zipcode' => '564561',
'country_id' => '91',
'country_name' => 'Guinea',
'state_id' => '3',
'state_name' => 'AL',
'city_id' => '3',
'city_name' => 'Bhopal'
)
);
To get unique multidimensional array you can use this :
$output_array = array_map(
"unserialize",
array_unique(array_map("serialize", $input_array))
);
Please use this to get unique array.
$output_array = array_unique($input_array, SORT_REGULAR);

PHP and PayPal IPN array

I am getting PayPal's IPN in array form like this:
$ipn = array(
'mc_gross' => '15.50',
'protection_eligibility' => 'Eligible',
'address_status' => 'confirmed',
'item_number1' => '1',
'tax' => '0.00',
'item_number2' => '2',
'payer_id' => 'XXXXXXXXXXXXX',
'address_street' => '1 Main St',
'payment_date' => '02:41:18 Nov 23, 2011 PST',
'payment_status' => 'Completed',
'charset' => 'windows-1252',
'address_zip' => '95131',
'mc_shipping' => '0.00',
'mc_handling' => '0.00',
'first_name' => 'Test',
'mc_fee' => '0.75',
'address_country_code' => 'US',
'address_name' => 'Test User',
'custom' => '',
'payer_status' => 'verified',
'business' => 'receiver#example.com',
'address_country' => 'United States',
'num_cart_items' => '2',
'mc_handling1' => '0.00',
'mc_handling2' => '0.00',
'address_city' => 'San Jose',
'payer_email' => 'payer#example.com',
'mc_shipping1' => '0.00',
'mc_shipping2' => '0.00',
'txn_id' => '8RE82733S8684874F',
'payment_type' => 'instant',
'last_name' => 'User',
'address_state' => 'CA',
'item_name1' => 'trilogy2',
'receiver_email' => 'receiver#example.com',
'item_name2' => 'trilogy1',
'payment_fee' => '0.75',
'quantity1' => '1',
'quantity2' => '1',
'receiver_id' => 'XXXXXXXXXXXXX',
'txn_type' => 'cart',
'mc_gross_1' => '5.55',
'mc_currency' => 'USD',
'mc_gross_2' => '9.95',
'residence_country' => 'US',
'transaction_subject' => 'Shopping Carttrilogy2trilogy1',
'payment_gross' => '15.50',
'' => ''
);
In this case customer has ordered only 2 items: 'item_name1' and 'item_name2'
Obviously, a customer can order X number of products and PayPal will include an 'item_nameX' in the notification data. Is there a way to go through the array and extract all names and assign them to variables so I will have something like:
$ordered_item1 = $ipn['item_name1'];
$ordered_item2 = $ipn['item_name2'];
...
$ordered_itemXYZ = $ipn['item_nameXYZ'];
Thanks for any help.
If you have data named with a prefix followed by a count, you should be using an array, not separate variables. To fill an array with the item information:
foreach ($ipn as $key => $value) {
if (preg_match('/(?P<field>[a-z]+)_?(?P<i>\d+)/', $key, $parts)) {
$ordered_items[(int) $parts['i']][$parts['field']] = $value;
}
}

Categories