Searching an array and getting results - php

Okay, So I am wanting to find information in an array and get a block returned based on the credentials passed. The way I am doing it right now is not working, I'm looking for a shorter process and a more fool proof process.
Right now I have this:
public function get_product($product_id, $color, $size)
{
$results = $this->pf->get('products/'.$product_id);
$vars = $results['variants'];
$details = array();
foreach($vars as $var)
{
if(!in_array($product_id, $details))
{
if($var['product_id'] == $product_id)
{
if($var['size'] == $size)
{
if($var['color'] == $color)
{
$details[$var['id']] = array(
'id' => $var['id'],
'name' => $var['name'],
'image' => $var['image'],
'price' => $var['price'],
);
}
}
}
}
}
return $details;
}
This receives a product_id, a color, and a size. Sometimes $color is null, Sometimes $size is null, and sometimes both $color and $size are null and we just need to find the one array that matches the $product_id.
What I am wanting returned is this:
$details[$var['id']] = array(
'id' => $var['id'],
'name' => $var['name'],
'image' => $var['image'],
'price' => $var['price'],
);
Right now nothing gets returned. $results returns this for an example: (This is what I need to search.)
{
"code": 200,
"result": {
"product": {
"id": 1,
"type": "POSTER",
"brand": null,
"model": "Poster",
"image": "https://d1yg28hrivmbqm.cloudfront.net/products/poster_18x24.jpg",
"variant_count": 9,
"files": [
{
"id": "default",
"title": "Print file",
"additional_price": null
},
{
"id": "preview",
"title": "Mockup",
"additional_price": null
}
],
"options": []
},
"variants": [
{
"id": 4464,
"product_id": 1,
"name": "Poster 12×12",
"size": "12×12",
"color": null,
"color_code": null,
"image": "https://d1yg28hrivmbqm.cloudfront.net/products/1/4464.jpg",
"price": "9.00"
},
Notice how color is returned as null. size can be that way to. So basically I am wanting a quicker and better way to search the returned array for the specified product_id, size, and color. So I need returned and matching the corresponding variants block that matches the variables submitted.
I hope I've made sense of what I'm trying to accomplish.
UPDATE
This is what I am needing.
So on my site the customers chooses a product, in this case a poster. Before adding it to the cart they are prompted to select a size. Let's say a 12x12. The way the API works is that it has a "top" item and then has smaller items "variants" that include the size and color. Each variant is a poster with a different size. The only way to obtain the poster product, is by receiving every variant for the poster. But each "variant" has a different "id" to send to the api to order the correct product.
So, I receive the product and it's variants in bulk or every color and size as it's own variant.
"variants": [
{
"id": 4464,
"product_id": 1,
"name": "Poster 12×12",
"size": "12×12",
"color": null,
"color_code": null,
"image": "https://d1yg28hrivmbqm.cloudfront.net/products/1/4464.jpg",
"price": "9.00"
},
{
"id": 1349,
"product_id": 1,
"name": "Poster 12×16",
"size": "12×16",
"color": null,
"color_code": null,
"image": "https://d1yg28hrivmbqm.cloudfront.net/products/1/1349.jpg",
"price": "11.00"
},
But remember the customer wanted a poster that was 12x12? We only need to send the demand to print a 12x12 poster. So we need to send to the api the ID for the variant that matches the 12x12 size.
I need a way to search through each variant for a product and find the correct variant that matches the product_id of the poster, and the size requirements of 12x12.
{
"id": 4464,
"product_id": 1,
"name": "Poster 12×12",
"size": "12×12",
"color": null,
"color_code": null,
"image": "https://d1yg28hrivmbqm.cloudfront.net/products/1/4464.jpg",
"price": "9.00"
},
Once I find that correct variant, I need to collect all that information into a new array and return it.
//Get the product based on the supplied product_id. ($results)
//Break that array down into just the variants. ($vars)
//Search the $vars array for a block that matches the product_id.
//Search those $vars blocks for a single one that matches the size.
//If color is supplied, search those $vars blocks for a single one that matches the color.
//If size and color are supplied, a single block should be returned that matches all three variables (product_id, size, and color). Sometimes size and/or color is `null`. But a product_id is always supplied.
I hope the clears up what I am needing a little better.

Try this. Am also ssuming you are using php. If you have a question, asking me directly. I think I can help you but I don't know exactly what you want.
<?php
function get_product($object){
$result = json_decode($object);
$product_id = $result->result->product->id;
$variants = $result->result->variants;
$details = array();
foreach($variants as $variant):
$details[] = $variant;
endforeach;// foreach
return $details;
}
$json_obj = '{
"code": 200,
"result": {
"product": {
"id": 1,
"type": "POSTER",
"brand": null,
"model": "Poster",
"image": "https://d1yg28hrivmbqm.cloudfront.net/products/poster_18x24.jpg",
"variant_count": 9,
"files": [
{
"id": "default",
"title": "Print file",
"additional_price": null
},
{
"id": "preview",
"title": "Mockup",
"additional_price": null
}
],
"options": []
},
"variants": [
{
"id": 4464,
"product_id": 1,
"name": "Poster 12×12",
"size": "12×12",
"color": null,
"color_code": null,
"image": "https://d1yg28hrivmbqm.cloudfront.net/products/1/4464.jpg",
"price": "9.00"
}
]
}
}';
$array = json_decode($json_obj);
echo '<pre>';
print_r(get_product($json_obj));
echo '</pre>';

Related

Merge duplicates in a grouped Laravel Collection and return a sum of a specific field

Im making an app for a customer where the user can type in specifications of sold christmas trees, stored in a JSON format in the database as "line_items". It needs to be outputtet in a table on the delivery note for the customer to see. The user have cases where multiple pallets are loaded on to a truck with the same species of trees that share the same size. In that case I want to merge the duplicates and sum the amount.
I've come up with this:
$data = collect($deliveryNote->line_items)
->groupBy(['type', 'size']);
that gives me the output below.
{
"NGR": {
"125-150": [
{
"slot": 2,
"pallet": "cghjh",
"type": "NGR",
"label": "purple",
"size": "125-150",
"amount": "30"
},
{
"slot": 3,
"pallet": "cghjh",
"type": "NGR",
"label": "purple",
"size": "125-150",
"amount": "30"
}
],
"150-175": [
{
"slot": 2,
"pallet": "yghiuj",
"type": "NGR",
"label": "orange",
"size": "150-175",
"amount": "30"
}
]
},
"NOB": {
"125-150": [
{
"slot": 3,
"pallet": "cghjh",
"type": "NOB",
"label": "purple",
"size": "125-150",
"amount": "30"
}
]
}
}
This is grouped almost how i want.
Now i want to merge the duplicates, filter out the "slot", "pallet", "label" and update the amount for the collection to display like this:
{
"NGR": {
"125-150": [
{
"type": "NGR",
"size": "125-150",
"amount": "60"
},
],
"150-175": [
{
"type": "NGR",
"size": "150-175",
"amount": "30"
}
]
},
"NOB": {
"125-150": [
{
"type": "NOB",
"size": "125-150",
"amount": "30"
}
]
}
}
I've tried this:
$data = collect($deliveryNote->line_items)
->groupBy(['type', 'size']);
->map(function ($item) {
return $item->sum('amount');
});
And it's not giving me the correct output.
I hope anybody has the the time to help me out.
Thanks you in advance.
In your last example, you are only iterating the "NGR", "NOB" keys and therefor values, to get to the trees you want to sum, you have to go one level deeper in your iteration.
Having a hard time figuring out if line_items is a relationship or custom data set, assumptions written in comments.
$data = collect($deliveryNote->line_items)
->groupBy(['type', 'size']);
->map(function ($tree) {
// i assume $trees is an array else don't wrap
return collect($trees)->map(function ($shipments) {
return [
'amount' => $shipments->sum('amount'),
// assuming object, if array access it like so
'size' => $shipments->first()->size,
'amount' => $shipments->first()->amount,
];
});
});

Merge 2 arrays based on a common element

So I have a Laravel controller that is pulling in 2 arrays.
Array 1:
[
{
"id":1,
"created_at":null,
"updated_at":null,
"name":"The Darkroom",
"description":"This is the room your parents warned you about",
"image":"https:\/\/images.unsplash.com\/photo-1579662908513-50e1433a258a?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1234&q=80",
"is_private":"0"
},{
"id":2,
"created_at":null,
"updated_at":null,
"name":"Smoking & Cigars",
"description":"Time to light up and enjoy a cigar!",
"image":"https:\/\/images.unsplash.com\/photo-1617850136763-06bc0a9a089c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2000&q=80",
"is_private":"0"
},{
"id":3,
"created_at":null,
"updated_at":null,
"name":"Humiliation",
"description":"today is the day you are going to be exposed",
"image":"https:\/\/images.unsplash.com\/photo-1571570261702-3d23956fa32e?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2600&q=80",
"is_private":"1"
},{
"id":4,
"created_at":null,
"updated_at":null,
"name":"Financial Domination",
"description":"hand over your cash and say thank you Sir!",
"image":"https:\/\/images.unsplash.com\/photo-1526304640581-d334cdbbf45e?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2200&q=80",
"is_private":"0"
},{"id":5,"created_at":null,"updated_at":null,"name":"Pups & Handlers","description":"Woof, woof, bark, sit","image":"https:\/\/images.unsplash.com\/photo-1506939754500-f27bc71fccd4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2200&q=80","is_private":"1"}]
Array 2:
{"channels":{"presence-chat.1":{"user_count":1},"presence-chat.4":{"user_count":1}}}
Final Array should look like this:
[
{
"id":1
"other data in the first array"
"user_count": 1
}
]
What I NEED to do inside my controller is merge the data together into a single array. So ideally, take the second array, match up the chat.ID with the ID of the first array and add in user_count to it... well you get what I mean.
I Have NEVER done this before so I have NO IDEA how best to go about this. Any help would be forever appreciated!
Here you go, this assumes that presence-chat.4 means channel with the id of 4:
<?php
$json1 = '[{"id":1,"created_at":null,"updated_at":null,"name":"The Darkroom","description":"This is the room your parents warned you about","image":"https:\/\/images.unsplash.com\/photo-1579662908513-50e1433a258a?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1234&q=80","is_private":"0"},{"id":2,"created_at":null,"updated_at":null,"name":"Smoking & Cigars","description":"Time to light up and enjoy a cigar!","image":"https:\/\/images.unsplash.com\/photo-1617850136763-06bc0a9a089c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2000&q=80","is_private":"0"},{"id":3,"created_at":null,"updated_at":null,"name":"Humiliation","description":"today is the day you are going to be exposed","image":"https:\/\/images.unsplash.com\/photo-1571570261702-3d23956fa32e?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2600&q=80","is_private":"1"},{"id":4,"created_at":null,"updated_at":null,"name":"Financial Domination","description":"hand over your cash and say thank you Sir!","image":"https:\/\/images.unsplash.com\/photo-1526304640581-d334cdbbf45e?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2200&q=80","is_private":"0"},{"id":5,"created_at":null,"updated_at":null,"name":"Pups & Handlers","description":"Woof, woof, bark, sit","image":"https:\/\/images.unsplash.com\/photo-1506939754500-f27bc71fccd4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2200&q=80","is_private":"1"}]';
$json2 = '{"channels":{"presence-chat.1":{"user_count":1},"presence-chat.4":{"user_count":1}}}';
// convert the json into php arrays
$array1 = json_decode($json1, true);
$array2 = json_decode($json2, true);
// we extract the user_counts from the second array
// and make the index of a new array the channel id with value user_count
$channel_counts = [];
foreach ($array2['channels'] as $chan_name => $count) {
$channel_id = explode('.', $chan_name)[1];
$user_count = $count['user_count'];
$channel_counts[$channel_id] = $user_count;
}
// we pass this array by reference as we are modifying it
foreach ($array1 as &$channel) {
$id = $channel['id'];
if (isset($channel_counts[$id]))
$channel['user_count'] = $channel_counts[$id];
else
$channel['user_count'] = 0;
}
unset($channel);
$final_json = json_encode($array1, JSON_PRETTY_PRINT);
echo $final_json;
Which results in:
[
{
"id": 1,
"created_at": null,
"updated_at": null,
"name": "The Darkroom",
"description": "This is the room your parents warned you about",
"image": "https:\/\/images.unsplash.com\/photo-1579662908513-50e1433a258a?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1234&q=80",
"is_private": "0",
"user_count": 1
},
{
"id": 2,
"created_at": null,
"updated_at": null,
"name": "Smoking & Cigars",
"description": "Time to light up and enjoy a cigar!",
"image": "https:\/\/images.unsplash.com\/photo-1617850136763-06bc0a9a089c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2000&q=80",
"is_private": "0",
"user_count": 0
},
{
"id": 3,
"created_at": null,
"updated_at": null,
"name": "Humiliation",
"description": "today is the day you are going to be exposed",
"image": "https:\/\/images.unsplash.com\/photo-1571570261702-3d23956fa32e?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2600&q=80",
"is_private": "1",
"user_count": 0
},
{
"id": 4,
"created_at": null,
"updated_at": null,
"name": "Financial Domination",
"description": "hand over your cash and say thank you Sir!",
"image": "https:\/\/images.unsplash.com\/photo-1526304640581-d334cdbbf45e?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2200&q=80",
"is_private": "0",
"user_count": 1
}, ...snip
]

Generate Nested Tree Structure or Hierarchy based on parent child relationship using recursion - PHP

I've been stuck in this since yesterday any help will be much appreciated. The situation is this: I have a table for navigation links with the following structure,
id | parent_id | text
In my scenario the parent_id may be null(no sub-menu) or any id pointing back to the table which will make the record a sub-menu of the parent. I've tried many different ways to execute this but with no luck, the closest scenario I came up with is the following,
// All navigation link results are stored in $data
public static function transform(array &$data) {
$result = [];
$search = function(&$array = [], $parent = null) use (&$search, &$result){
foreach($array as $key => $value) {
/** If the element has an ancestor */
if($parent && $parent->id == $value->parent_id) {
$next = $parent->children[] = $value;
$search($array, $next);
unset($array[$key]);
}
}
return $parent;
};
foreach($data as $val) {
$result[] = $search($data, $val);
}
return $result;
}
The function works fine and tracks all the ancestors of a certain link but in the next iteration is tracking all the ancestors of the next element(even if it was a child of the previous one) so it comes back with a lot of duplicated data. I came up with the solution to unset the iterated element from the array but for some reason, the element is still being used in the next iteration.
Here is my current data
Here is my current result
A simple concept for faster search and to process one item only once.
Create a temp array with key as id and values as array of child ids. Will use this array to process next direct childs. It would be a depth first traversal.
Also set id as key in input array, so we can directly access whole node when required.
function generateTree($data){
$arrChild = []; // Store parent as key and its childs as array to quickly find out.
foreach($data as $obj){
$arrChild[$obj->parent_id][] = $obj->id;
$data[$obj->id] = $obj;
}
$final = [];
$setChild = function(&$array, $parents) use (&$setChild, $data, $arrChild){
foreach($parents as $parent){
$temp = $data[$parent];
// If key is set, that means given node has direct childs, so process them too.
if(isset($arrChild[$parent])){
$temp->children = [];
$setChild($temp->children, $arrChild[$parent]);
}
$array[] = $temp;
}
};
// Empty key would represent nodes with parent as `null`
$setChild($final, $arrChild['']);
return $final;
}
$final = generateTree($arr);
echo json_encode($final, JSON_PRETTY_PRINT);
Output:
[
{
"id": 1,
"navigation_id": 4,
"parent_id": null,
"text": "link 1",
"icon": "",
"url": null,
"page_id": 4,
"children": [
{
"id": 2,
"navigation_id": 4,
"parent_id": 1,
"text": "link 2",
"icon": "",
"url": null,
"page_id": 4,
"children": [
{
"id": 3,
"navigation_id": 4,
"parent_id": 2,
"text": "link 3",
"icon": "fas fa-ad",
"url": "https:\/\/google.com",
"page_id": null
},
{
"id": 4,
"navigation_id": 4,
"parent_id": 2,
"text": "link 4",
"icon": "fab fa-google",
"url": "https:\/\/google.com",
"page_id": null
}
]
}
]
},
{
"id": 5,
"navigation_id": 4,
"parent_id": null,
"text": "link 5",
"icon": "",
"url": null,
"page_id": 5,
"children": [
{
"id": 6,
"navigation_id": 4,
"parent_id": 5,
"text": "link 6",
"icon": "",
"url": null,
"page_id": 4
},
{
"id": 7,
"navigation_id": 4,
"parent_id": 5,
"text": "link 7",
"icon": "",
"url": null,
"page_id": 4
}
]
}
]

How to insert nested array of a multidimensional array into mysql

I have a multidimensional aray that i want to insert into mysql database. Everything works fine but iwant a better solution as the rows repeat itself following the nested array
here is my json
{
"results": [
{
"id": 48728,
"name": "MOVIES AT THE PARK # GIBA GORGE",
"url": "Some URL",
"imageUrl": "Some Path",
"dateCreated": "2018-06-08T09:18:59.717",
"lastModified": "2018-06-26T14:20:45.0214921",
"startDate": "2018-07-28T17:00:00",
"endDate": "2018-07-28T22:00:00",
"venue": {
"id": 0,
"name": "Giba Gorge Mountain Bike Park",
"addressLine1": "110 Stockville Road",
"addressLine2": "",
"latitude": -29.8276051,
"longitude": 30.781735700000013
},
"locality": {
"levelOne": "South Africa",
"levelTwo": "KwaZulu-Natal",
"levelThree": "Clifton Canyon"
},
"organiser": {
"id": 0,
"name": "Ultra Glow SA ",
"phone": "0822603351",
"mobile": "0828927837",
"facebookUrl": "",
"twitterHandle": "",
"hashTag": "UGMOVIES",
"organiserPageUrl": "some url"
},
"categories": [
{
"id": 3,
"name": "Film & Media"
},
{
"id": 12,
"name": "Food & Drink"
}
],
"tickets": [
{
"id": 98655,
"name": "ADULT TICKET",
"soldOut": false,
"provisionallySoldOut": false,
"price": 100,
"salesStart": "2018-06-26T11:52:00",
"salesEnd": "2018-07-28T17:00:00",
"description": "",
"donation": false,
"vendorTicket": false
},
{
"id": 98656,
"name": "UNDER 12",
"soldOut": false,
"provisionallySoldOut": false,
"price": 80,
"salesStart": "2018-06-26T11:53:00",
"salesEnd": "2018-07-28T17:00:00",
"description": "",
"donation": false,
"vendorTicket": false
}
],
"schedules": [
],
"refundFeePayableBy": 0
},
{
"id": 51681,
"name": "ULTRA GLOW COLOUR CRUZ # RIETVLEI ZOO FARM",
"url": "some url",
"imageUrl": "some path",
"dateCreated": "2018-06-26T12:12:07.3",
"lastModified": "2018-06-28T15:22:24.1579751",
"startDate": "2018-08-12T10:00:00",
"endDate": "2018-08-12T14:00:00",
"venue": {
"id": 0,
"name": "Rietvlei Zoo Farm",
"addressLine1": "101 Swartkoppies Road",
"addressLine2": "",
"latitude": -26.3117147,
"longitude": 28.07989120000002
},
"locality": {
"levelOne": "South Africa",
"levelTwo": "Gauteng",
"levelThree": "Johannesburg South"
},
"organiser": {
"id": 0,
"name": " Ultra Glow South Africa",
"phone": "0822603351",
"mobile": "0828927837",
"facebookUrl": "",
"twitterHandle": "",
"hashTag": "",
"organiserPageUrl": "some url"
},
"categories": [
{
"id": 60,
"name": "Trail Running"
},
{
"id": 5,
"name": "Sports & Fitness"
}
],
"tickets": [
{
"id": 98735,
"name": "ADULT EARLY BIRD",
"soldOut": false,
"provisionallySoldOut": false,
"price": 150,
"salesStart": "2018-06-26T12:47:00",
"salesEnd": "2018-08-12T10:00:00",
"description": "",
"donation": false,
"vendorTicket": false
},
{
"id": 98736,
"name": "UNDER 12 - EARLY BIRD",
"soldOut": false,
"provisionallySoldOut": false,
"price": 120,
"salesStart": "2018-06-26T12:47:00",
"salesEnd": "2018-08-12T10:00:00",
"description": "",
"donation": false,
"vendorTicket": false
}
],
"schedules": [
],
"refundFeePayableBy": 0
}
],
"pageSize": 10,
"pages": 1,
"records": 2,
"extras": null,
"message": null,
"statusCode": 0
}
i have tried the following code to insert the relevant datas into database
<?php
$connect= mysqli_connect("localhost","root","","result");
$jsondata=file_get_contents("result.json");
$json= json_decode($jsondata,true);
$results=$json['results'];
$n= sizeof($results);
for($i=0;$i<$n;$i++){
$row=$results[$i];
foreach($row['tickets'] as $key => $value){
$sql="INSERT into
event(name,url,imageUrl,dateCreated,eventName,addressLine1,addressLine2,ticketNa me,price)
VALUES('".$row["name"]."','".$row["url"]."','".$row["imageUrl"]."','".$row["dateCreated"]."','".$row["venue"]["name"]."','".$row["venue"]["addressLine1"]."','".$row["venue"]["addressLine2"]."','".$value["name"]."','".$value["price"]."')";
mysqli_query($connect,$sql);
}
}
echo "events data inserted";
?>
This enters the respective datas into my database but because of the nested array tickets with respective keys name and price the same events are being posted twice into my database like MOVIES AT THE PARK # GIBA GORGE for price 100 is one one row and MOVIES AT THE PARK # GIBA GORGE for price 80 on another row ... I have to display these datas in future as part of one event name with their the ticket type and price as a table... do you have any idea on any other way i can make it better, instead of having two rows for same events?
Thanks in advance
for those who have been suggesting me not to use for and foreach loop this is my update code after removing for loop and a single foreach loop and it gives me an error of undefined index of name and price under tickets
<?php
$connect= mysqli_connect("localhost","root","","result");
$jsondata=file_get_contents("result.json");
$json= json_decode($jsondata,true);
$results=$json['results'];
foreach($results as $key => $result){
$sql="INSERT into `event(name,url,imageUrl,dateCreated,eventName,addressLine1,addressLine2,ticketName,price) VALUES('".$result["name"]."','".$result["url"]."','".$result["imageUrl"]."','".$result["dateCreated"]."','".$result["venue"]["name"]."','".$result["venue"]["addressLine1"]."','".$result["venue"]["addressLine2"]."','".$result["tickets"]["name"]."','".$result["tickets"]["price"]."')";`
mysqli_query($connect,$sql);
}
echo "events data inserted";
?>
hence i have further updated my code by using two foreach loops, one to ietrate through the top level array "results" and the other to iterate through the nested array "tickets"
<?php
$connect= mysqli_connect("localhost","root","","result");
$jsondata=file_get_contents("result.json");
$json= json_decode($jsondata,true);
$results=$json['results'];
foreach($results as $key => $result){
foreach($result["tickets"] as $k => $v){
$sql="INSERT into event(name,url,imageUrl,dateCreated,eventName,addressLine1,addressLine2,ticketName,price) VALUES('".$result["name"]."','".$result["url"]."','".$result["imageUrl"]."','".$result["dateCreated"]."','".$result["venue"]["name"]."','".$result["venue"]["addressLine1"]."','".$result["venue"]["addressLine2"]."','".$v["name"]."','".$v["price"]."')";`
mysqli_query($connect,$sql);
}
}
echo "events data inserted";
?>
that iterates through the nested array so there is nothing wrong in my code now the only problem is i am getting 2 events on my table because of two ticket types adult and children in "tickets" array
so as per many suggestions here i need to create two separate tables for events and tickets i would appreciate if anyone can tell me that how do iconnect these two tables to be able to show the information of my events in html with ticket type and price shown in html table tag thanks in advance
The main reason that is happening is look at the below code :
$row=$results[$i];
foreach($row['tickets'] as $key => $value){
$sql="INSERT into event(name,url,imageUrl,dateCreated,eventName,addressLine1,addressLine2,ticketNa me,price) VALUES('".$row["name"]."','".$row["url"]."','".$row["imageUrl"]."','".$row["dateCreated]."','".$row["venue"]["name"]."','".$row["venue"]["addressLine1"]."','".$row["venue"]["addressLine2"]."','".$value["name"]."','".$value["price"]."')";
mysqli_query($connect,$sql);
}
The $row contains your one main entry and $row['tickets'] contains 2 entries and you are using the $row main contents inside the loop for tickets. That is the reason you are getting 2 entries. The best way to cope this is to use a single foreach loop instead of using a for and a foreach.
EDIT:
Actually I would like to suggest to normalize your table by breaking this into 2 tables, one for storing event information and the other for using the ticket information. See the structure below:
event(id,name,url,imageUrl,addressLine1,addressLine2,dateCreated);
event_tickets(id,event_id,ticketName,price,dateCreated);
This will help you maintain the information easily. Also you can modify the code to something like this :
$sql="INSERT into event(name,url,imageUrl,addressLine1,addressLine,2dateCreated) VALUES ('".$row['name']."','".$row['url']."','".$row['imageUrl']."','".$row['venue']['addressLine1']."','".$row['venue']['addressLine2']."','".date('Y-m-d h:i:s')."');"
mysqli_query($connect, $sql);
$event_id = mysqli_insert_id($connect);
And then you can use a foreach to insert the ticket information in the event_tickets table.
Hope this helps
it's because you're using a foreach within a for. You just want a foreach:
foreach ($multiArray as $key => $singleArray) {
//rest of code, replacing $row with $singleArray['key']. E.g. $singleArray['id']
}
update after seeing OP update:
so you would do:
foreach ($results as $row) {
foreach ($row['tickets'] as $ticket) {
//sql
}
}
this should allow you to use $ticket['key'] in your SQL - though I do suggest switch to PDO prepared statements to protect yourself from SQL injection.
Also as other suggested, separating tickets into its own table would be highly advantageous to you.

PHP - Most efficient way to filter two arrays

I have a question on what is the most performant way to filter two arrays of objects. I have two arrays of products from different systems and i want to work out which products have been removed from one array and then return the products that have been removed.
See the current function i have below which i know is super slow.
public function checkRemove($externalProducts, $localProducts){
//Push all the SKU codes from feed to an array();
$arr = [];
foreach ($externalProducts->products as $product) {
if($product->StockNumber != null){
array_push($arr, $product->StockNumber);
}
}
//Loop through the local products
$productsRemove = [];
foreach ($localProducts->products as $key => $localProduct) {
if(in_array($localProduct->sku, $arr)){
}else{
array_push($productsRemove, $localProduct);
}
}
return $productsRemove;
}
$externalProducts = {
"Filter": {
"Title": "All Products"
},
"Products": [{
"Type": "Jacket",
"Price": 75,
"ExpiryDate": "2018-06-30",
"StockNumber": "180220/003",
"Created": "2018-02-20 12:24:06",
"Modified": "2018-05-30 02:00:23"
},
{
"Type": "Jeans",
"Price": 150,
"ExpiryDate": "2018-06-30",
"StockNumber": "180221/004",
"Created": "2017-08-10 15:11:44",
"Modified": "2018-05-30 02:00:22"
},
{
"Type": "Jacket",
"Price": 240,
"ExpiryDate": "2018-06-30",
"StockNumber": "150804/012",
"Created": "2015-08-04 17:03:42",
"Modified": "2018-05-30 02:00:22"
}
]
}
$internalProducts = "localProducts": [{
"title": "Fur Coat",
"id": 16526,
"created_at": "2018-05-17T10:15:45Z",
"updated_at": "2018-05-17T10:15:45Z",
"sku": "180514/001",
"price": "75.00",
"regular_price": "75.00",
"categories": [
"Jackets",
],
},
{
"title": "Ripped Jeans",
"id": 16527,
"created_at": "2018-05-17T10:15:45Z",
"updated_at": "2018-05-17T10:15:45Z",
"sku": "180221/004",
"price": "150.00",
"regular_price": "150.00",
"categories": [
"Jeans",
],
},
{
"title": "Leather Jacket",
"id": 16528,
"created_at": "2018-05-17T10:15:45Z",
"updated_at": "2018-05-17T10:15:45Z",
"sku": "150804/012",
"price": "240.00",
"regular_price": "240.00",
"categories": [
"Jackets",
],
}
]
Take a look at array_filter
You can provide a callback function which will be run for each element in the array. If the callback function returns true, the current value from the array is returned in the result array.
You still have to iterate over one array at least. It is $localProducts. So, for $localProducts there're no improvements. But you can improve $externalProducts - add a special method (if you can) that will return StockNumbers only. More effective will be if StockNumbers will be of structure as:
[
'stocknumber1' => true,
'stocknumber2' => true,
'stocknumber3' => true,
'stocknumber4' => true,
'stocknumber5' => true,
]
This will improve your search, as checking isset($StockNumbers['stocknumber4']) is faster than in_array or array_search.
If you can't change structure of $externalProducts->products, than build array of stock numbers in a loop:
public function checkRemove($externalProducts, $localProducts){
//Push all the SKU codes from feed to an array();
$arr = [];
foreach ($externalProducts->products as $product) {
if ($product->StockNumber != null){
// Again I add sku as key, not as value
$arr[$product->StockNumber] = true;
}
}
//Loop through the local products
$productsRemove = [];
foreach ($localProducts->products as $localProduct) {
// check with `isset` is faster
if (isset($arr[$localProduct->sku])) {
array_push($productsRemove, $localProduct);
}
}
return $productsRemove;
}

Categories