Array search, add and delete - php

I have the following table:
CREATE TABLE sample (id INT AUTO_INCREMENT PRIMARY KEY, entry_id INT NOT NULL, last_change timestamp);
INSERT INTO sample (entry_id) VALUES (1), (2), (3), (4);
My code does the following:
Receives POST input and compares the values to the table above.
If the the POST data has a value that does not exist in the entry_id column, then it will perform an INSERT statement.
If the table has a value in the entry_id column that does not exist in the POST data, then it will perform a DELETE statement
PHP Code:
<?php
// $_POST data:
$submittedEntries = array(1, 3, 4, 5, 6);
// $dbORM->getEntries()
$currentEntries = array(
array("id" => 100, "entry_id" => 1, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 101, "entry_id" => 2, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 102, "entry_id" => 3, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 103, "entry_id" => 4, "timestamp" => "2014-07-24 2:14:00"),
)
$entriesToAdd = array();
$entriesToRemove = array();
// Find Entries to Add
// Loop through each entry submitted
foreach($submittedEntries as $entry_id) {
$exists = false;
// Loop through all Current Entries
foreach($currentEntries as $existingEntry) {
// Find matching IDs
if ($existingEntry["entry_id"] == $entry_id) {
$exists = true;
}
}
if ($exists == false) {
$entriesToAdd[] = $entry_id;
}
}
// Find Entries to Remove
// Loop through all Current Entries
foreach($currentEntries as $existingEntry) {
$remove = true;
// Loop through each entry submitted
foreach($submittedEntries as $entry_id) {
// Find matching IDs
if ($existingEntry["entry_id"] == $entry_id) {
$remove = false;
}
}
if ($remove == true) {
$entriesToRemove[] = $existingEntry["entry_id"];
}
}
// Add New Entries
foreach($entriesToAdd as $entry_id) {
$dbORM->addEntry($entry_id);
}
// Remove Entries
foreach($entriesToRemove as $entry_id) {
$dbORM->removeEntry($entry_id);
}
$entries = $dbORM->getEntries(); // SELECT * from sample;
print_r($entries);
/*
Expected Output:
array(
array("id" => 100, "entry_id" => 1, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 102, "entry_id" => 3, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 103, "entry_id" => 4, "timestamp" => "2014-07-24 2:14:00"),
array("id" => 104, "entry_id" => 5, "timestamp" => "2014-07-24 3:27:00"),
array("id" => 105, "entry_id" => 6, "timestamp" => "2014-07-24 3:27:00")
)
*/
Is there a better way to do this? I looked into all the php array functions and they do not seem to be able to deep search of multidimensional arrays.

If the table has to always be exactly like the POST, simplest way is to DELETE all rows and then INSERT all posts.
Another solution could be the use of unique key on entry_id...
This way you could really simply do 2 small queries:
$insert = "INSERT IGNORE INTO sample (entry_id)VALUES(".implode('),(',$submittedEntries).")";
$delete = "DELETE FROM sample WHERE entry_id NOT IN(".implode(',',$submittedEntries).")";

If you want to compair the two lists in PHP then you can use array_walk() to run through the db list and then use in_array() to see if it's in the submitted POST. You can then filter into two arrays.
<?php
$entriesToAdd = array();
$entriesToRemove = array();
$submittedEntries = array(1, 3, 4, 5, 6);
$currentEntries = array(
array("id" => 100, "entry_id" => 1),
array("id" => 101, "entry_id" => 2),
array("id" => 102, "entry_id" => 3),
array("id" => 103, "entry_id" => 4),
);
function AWS(&$item, $key) {
global $submittedEntries, $entriesToAdd, $entriesToRemove;
if(in_array($item["entry_id"], $submittedEntries))
{
array_push($entriesToAdd, $item);
}
else
{
array_push($entriesToRemove, $item);
}
}
array_walk( $currentEntries, 'AWS' );
echo "Add:";
print_r($entriesToAdd);
echo "Remove:";
print_r($entriesToRemove);
This outputs:
Add:Array
(
[0] => Array
(
[id] => 100
[entry_id] => 1
)
[1] => Array
(
[id] => 102
[entry_id] => 3
)
[2] => Array
(
[id] => 103
[entry_id] => 4
)
)
Remove:Array
(
[0] => Array
(
[id] => 101
[entry_id] => 2
)
)

Related

Create an array of object PHP

I am trying to create this structure on PHP
and I don't know how to I create an array of object on PHP. It always get the last data from the object.
This is my current code:
array(
"description": getDescription($id),
"deposit": getPrices($id);
)
function getPrices($id) {
$test = Prices::where('price_id',$id)->where('promo',0)->get();
$price = [];
$data = [];
foreach($test as $t) {
$data["item_id"] = $t->id;
$data["price"] = $t->list;
$data["type"] = $t->type;
$price = $data;
}
return $price;
}
Fixing the actual issue with not receiving all records from the getPrices function:
array(
"description": getDescription($id),
"deposit": getPrices($id);
)
function getPrices($id) {
$test = Prices::where('price_id',$id)->where('promo',0)->get();
$price = [];
foreach($test as $t) {
$price[] = ["item_id" => $t->id, "price" => $t->list, "type": $t->type];
}
return $price;
}
You're missing the square brackets after $price (Correct: $price[]) variable which tells PHP to append to array rather than actually replace it.
The other option is to use array_push, which is more explicit but does the same; Read more here.
Fixing the issue of serialisation:
You can use json_encode to serialise the array into JSON (JavaScript Object Notation).
$dataArray=array();
foreach($test as $t) {
$dataArray[] = array('item'=> $t->id,'item'=> $t->price,'type'=> $t->type);
}
$finalArray= array('deposit'=>$dataArray);
convert final array to json using json_encode
$structure = new stdClass();
$structure->description = 'tobedefined'; // Define the description here
$structure->deposit = getPrices($id);
function getPrices($id) {
$deposits = array();
// Change this to contain the real data
// $test = Prices::where('price_id',$id)->where('promo',0)->get();
$test = array(
array(
'item_id' => 100,
'price' => '1, 2, 3, 4, 5',
'type' => 'child'
),
array(
'item_id' => 101,
'price' => '2, 4, 6, 8, 10',
'type' => 'child'
),
array(
'item_id' => 102,
'price' => '2, 4, 6, 8, 10',
'type' => 'child'
)
);
foreach ($test as $t) {
$deposit = new stdClass();
$deposit->item_id = $t['item_id'];
$deposit->price = $t['price'];
$deposit->type = $t['type'];
$deposits[] = $deposit;
}
return $deposits;
}
echo 'PHP Structure';
echo '<pre>';
print_r($structure);
echo '</pre>';
echo 'JSON string';
echo '<pre>';
print_r(json_encode($structure, JSON_PRETTY_PRINT));
echo '</pre>';
Output will be:
PHP Structure
stdClass Object
(
[description] => tobedefined
[deposit] => Array
(
[0] => stdClass Object
(
[item_id] => 100
[price] => 1, 2, 3, 4, 5
[type] => child
)
[1] => stdClass Object
(
[item_id] => 101
[price] => 2, 4, 6, 8, 10
[type] => child
)
[2] => stdClass Object
(
[item_id] => 102
[price] => 2, 4, 6, 8, 10
[type] => child
)
)
)
JSON string
{
"description": "tobedefined",
"deposit": [
{
"item_id": 100,
"price": "1, 2, 3, 4, 5",
"type": "child"
},
{
"item_id": 101,
"price": "2, 4, 6, 8, 10",
"type": "child"
},
{
"item_id": 102,
"price": "2, 4, 6, 8, 10",
"type": "child"
}
]
}

PHP: How to initialize cells in a 2D array with all existing keys, so that all rows have the same number of elements

Given this example array, with dynamic keys (not known in advance) :
[
["blep" => 32, "blip" => 42],
["blap" => 99, "blep" => null],
["lel" => "hulo"]
]
I would like to be able to get this output :
[
["blap" => null, "blep" => 32, "blip" => 42, "lel" => null],
["blap" => 99, "blep" => null, "blip" => null, "lel" => null],
["blap" => null, "blep" => null, "blip" => null, "lel" => "hulo"]
]
How would I achieve that? Should I just loop over the array elements to get all the keys that exist, then re-loop over those elements to declare the keys that are not declared in the element? Is there no better way?
Thank you !
Try this one.
$collection = collect([
["blep" => 32, "blip" => 42],
["lel" => "hulo"]
]);
$existsKeys = collect(['blap'=>null, 'blep'=>null, 'blip'=>null, 'lel'=>null]);
$newCollection = $collection->map(function($item, $key) use ($existsKeys) {
$diff = $existsKeys->diffKeys($item);
return collect($item)->merge($diff);
});
dd( $newCollection );
For more information please take a look on documentation.
<?php
$array=[
["blep" => 32, "blip" => 42],
["blap" => 99, "blep" => null],
["lel" => "hulo"]
];
$counter=0;
foreach($array as $data){
isset($data['blep'])?true:$array[$counter]['blep']=null;
isset($data['blip'])?true:$array[$counter]['blip']=null;
isset($data['blap'])?true:$array[$counter]['blap']=null;
isset($data['lel'])?true:$array[$counter]['lel']=null;
$counter++;
}
echo '<pre>';
print_r($array);
This code will go through your array and if it finds a value already set will keep it else will add a new array field with the value null. At the end of the loop all the nested array will have the same fields.
Output is:
Array
(
[0] => Array
(
[blep] => 32
[blip] => 42
[blap] =>
[lel] =>
)
[1] => Array
(
[blap] => 99
[blep] =>
[blip] =>
[lel] =>
)
[2] => Array
(
[lel] => hulo
[blep] =>
[blip] =>
[blap] =>
)
)

Get specific key value pairs from associative array

I`m new to PHP and probably this one is basic question, but...I have an associative array (result of json_decode function). For example it looks like this:
$cars = array
(
array("brand"=>"Volvo", "price" => 10000, "type"=> 1),
array("brand"=>"Audi", "price" => 20000, "type"=> 2),
array("brand"=>"Ford", "price" => 30000, "type"=> 3),
array("brand"=>"Audi", "price" => 31000, "type"=> 3),
array("brand"=>"Ford", "price" => 32000, "type"=> 2),
array("brand"=>"Audi", "price" => 33000, "type"=> 2)
);
I need to loop $cars and get just brand and price as key value pair where brand is Audi because of a need to convert each to an object then.
Thanks!
Pretty simple. Use foreach to iterate through each car. If car brand name is 'Audi' then it will add it the entry it's on to an array.
<?php
$cars = array
(
array("brand"=>"Volvo", "price" => 10000, "type"=> 1),
array("brand"=>"Audi", "price" => 20000, "type"=> 2),
array("brand"=>"Ford", "price" => 30000, "type"=> 3),
array("brand"=>"Audi", "price" => 31000, "type"=> 3),
array("brand"=>"Ford", "price" => 32000, "type"=> 2),
array("brand"=>"Audi", "price" => 33000, "type"=> 2)
);
$audis = [];
foreach ($cars as $car) {
if ($car['brand'] == 'Audi') {
$audis[] = ['price' => $car['price'], 'type' => $car['type']];
}
}
foreach ($audis as $audi) {
print_r($audi);
}
This returns all Audi's
Array
(
[price] => 20000
[type] => 2
)
Array
(
[price] => 31000
[type] => 3
)
Array
(
[price] => 33000
[type] => 2
)
Link: https://eval.in/769607

PHP array_udiff weird behavior

I have 2 arrays, $array0 and $array1. Let's pre-fill them:
$user01 = array("no" => 1, "name" => "john");
$user02 = array("no" => 2, "name" => "lewis");
$user03 = array("no" => 3, "name" => "dan");
$array0 = array($user01, $user02, $user03, $user04);
$user11 = array("id" => 1, "name" => "john", "attr" => "foo");
$user12 = array("id" => 7, "name" => "mark", "attr" => "bar");
$array1 = array($user11, $user12);
I want to get all users from $array0 who are not in $array1, so I use array_udiff:
$diff = array_udiff($array0, $array1, function ($userA, $userB) {
return $userA['no'] == $userB['id'];
});
However, inside the anonymous compare function, if I do a var_dump of $userA and $userB, they both seem to belong to $array0, while the behavior I was expecting is for $userA to belong to $array0 and $userB to $array1.
I.e., the expected answer is [[2, "lewis"], [3, "dan"]], but I get a 'not found index': "Undefined index id" in the line of the comparison function.
Am I missing something on array_udiff behavior?
I'm pretty sure PHP expects the arguments to the comparison function to be interchangeable, you either need to change the array indexes to be common, or implement logic in the comparison function to deal with this.
That's not how a comparison function works.
The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
So:
$user01 = array("id" => 1, "name" => "john"); // "no" changed to "id"
$user02 = array("id" => 2, "name" => "lewis");
$user03 = array("id" => 3, "name" => "dan");
$array0 = array($user01, $user02, $user03); // non-existant $user04 removed
$user11 = array("id" => 1, "name" => "john", "attr" => "foo");
$user12 = array("id" => 7, "name" => "mark", "attr" => "bar");
$array1 = array($user11, $user12);
$diff = array_udiff($array0, $array1, function ($userA, $userB) {
if( $userA['id'] == $userB['id'] ) { return 0; } // compare function re-jiggered
else { return $userA['id'] - $userB['id']; }
});
print_r($diff);
Yields:
Array
(
[1] => Array
(
[id] => 2
[name] => lewis
)
[2] => Array
(
[id] => 3
[name] => dan
)
)

PHP: How to update/extend an multidimensional Array recursive and on-the-fly?

I've a multidimensional array and would like to update/add some values, recursive. I'd like to avoid building a new array, if possible. But I've two main problems:
How to update the values "on-the-fly"? It should be possible with the &-operator.
How to get values to extend the array if the function getDetails() is out of scope.
My alternative is to rebuild everything, but I think there should be a more clean possibility.
I've added some pseudocode and hope it's not too weird. I appreciate your help!
Here's the fiddle: http://phpfiddle.org/main/code/m2g-ign
PHP
// build the array
$myArray = array(
array(
"id" => 1,
"name" => "A (Level 1)",
"children" => array(
array(
"id" => 3,
"name" => "C (Level 2)",
"children" => array(
"id" => 4,
"name" => "D (Level 3)",
"children" => null
)
),
array(
"id" => 6,
"name" => "F (Level 2)",
"children" => array(
"id" => 7,
"name" => "G (Level 3)",
"children" => null
)
)
)
),
array(
"id" => 2,
"name" => "B (Level 1)",
"children" => array(
array(
"id" => 5,
"name" => "E (Level 2)",
"children" => null
)
)
)
);
// returns detailed data, important: it's out of scope
function getDetails($id) {
// select dataset from DB
// ...
return $details;
}
// loop the array
$RAI = new RecursiveArrayIterator($myArray);
function updateMyArray($iterator) {
while ($iterator->valid()) {
if ($iterator->hasChildren()) {
// recursive
updateMyArray($iterator->getChildren());
} else {
/*
// 1. set "name" to uppercase
// Pseudocode:
$iterator->activeChild()->change(function(&$value) {
$value = toUpperCase($value);
});
// 2. add Array
// Pseudocode:
$id = $iterator->activeChild()->getValue("id");
$iterator->activeChild()->add("details", getDetails($id)); // getDetails() is out of scope, I guess
*/
}
$iterator->next();
}
}
echo "<strong>Before:</strong><pre>";
print_r($myArray);
echo "</pre>";
iterator_apply($RAI, 'updateMyArray', array($RAI));
echo "<strong>After:</strong><pre>";
print_r($myArray);
echo "</pre>";

Categories