I have a SQLite3 database which contains 4 tables with 9 rows each.
I've tried to do each one of the arrays one-by-one, with basically the same code as below (everything in the foreach loop), and it worked fine. I guess I just made some stupid mistakes (I don't really use PHP, this is pretty much the only project I've used it in). I tried to fix it, but somehow PHP is not really friendly today.
Currently the code below returns a JSON with 4 empty arrays.
<?php
header('Content-type: application/json');
$db = new PDO('sqlite:whad.db')or die('Could not open database');
$arDaniel = array();
$arAndi = array();
$arDave = array();
$arSimon = array();
for ($j=0; $j < 4; $j++) {
$name;
$arr;
if (j == 0) {
$name = 'Daniel';
$arr = $arDaniel;
}
elseif (j == 1) {
$name = 'Andi';
$arr = $arAndi;
}
elseif (j == 2) {
$name = 'Dave';
$arr = $arDave;
}
elseif (j == 3) {
$name = 'Simon';
$arr = $arSimon;
}
$query = "SELECT Datum, ID, RR, RL, KB, BD, SD, KH, Reihenfolge FROM $name ORDER BY date(Datum)";
$i = 1;
foreach($res = $db->query($query) as $value) {
$curr = array();
array_push($curr["Datum"] = $value[0]);
array_push($curr["ID"] = $value[1]);
array_push($curr["RR"] = $value[2]);
array_push($curr["RL"] = $value[3]);
array_push($curr["KB"] = $value[4]);
array_push($curr["BD"] = $value[5]);
array_push($curr["SD"] = $value[6]);
array_push($curr["KH"] = $value[7]);
array_push($curr["Reihenfolge"] = $value[8]);
array_push($arr[$i] = $curr);
$i++;
}
}
$json = array(
"Daniel" => $arDaniel,
"Andi" => $arAndi,
"Dave" => $arDave,
"Simon" => $arSimon
);
echo json_encode($json);
$db = NULL;
?>
EDIT: Removed quotes around $curr.
You have many unnecassary variables with the same data.
You simply could do the following
<?php
header('Content-type: application/json');
$db = new PDO('sqlite:whad.db')or die('Could not open database');
$json = array(
"Daniel" => array(),
"Andi" => array(),
"Dave" => array(),
"Simon" => array()
);
foreach($json as $name => &$arr){
$query = "SELECT Datum, ID, RR, RL, KB, BD, SD, KH, Reihenfolge FROM $name ORDER BY date(Datum)";
$stmt = $db->query($query);
//now comes the trick, that you tell pdo to fecth them already as array
$arr = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
unset($arr);
echo json_encode($json);
?>
Look at the first example here: http://php.net/manual/de/pdostatement.fetchall.php
Also note the & before $arr, which will handle the $arr variable as reference (also the unset, because after the last pass, it would still be set, this is just good style to clean up)
Update:
As in the other answer you have to use PDO::FETCH_ASSOC to get an array with only the index names.
There are more than one error in your code:
$arDaniel = array();
$arAndi = array();
$arDave = array();
$arSimon = array();
for ($j=0; $j < 4; $j++) {
$name; # <---
$arr; # <---
This sort of ‘declaration’ in php is unnecessary, you can remove $name and $arr (it's not an error, btw);
if (j == 0) { # <---
In the for loop you use $j, you can't use j here: replace it with $j (in php variables are ever prepended by $);
$name = 'Daniel';
$arr = $arDaniel; # <---
By this assignment, you want change the original array, but with this assignment by value, you in fact create a copy of $arDaniel, and new elements are added only to $arr, not to $arDaniel; to do this, you have to do an assignment by reference through & keyword: replace this (and following similar) line with $arr = &$arDaniel;
}
elseif (j == 1) { # <--- see above
$name = 'Andi';
$arr = $arAndi; # <--- see above
}
elseif (j == 2) { # <--- see above
$name = 'Dave';
$arr = $arDave; # <--- see above
}
elseif (j == 3) { # <--- see above
$name = 'Simon';
$arr = $arSimon; # <--- see above
}
$query = "SELECT Datum, ID, RR, RL, KB, BD, SD, KH, Reihenfolge FROM $name ORDER BY date(Datum)";
$i = 1; # <---
The query is formally correct, but I don't know your table structure. $i = 1; is unnecessary (see below);
foreach($res = $db->query($query) as $value) {
$curr = array();
array_push($curr["Datum"] = $value[0]); # <---
array_push($curr["ID"] = $value[1]); # <---
array_push($curr["RR"] = $value[2]); # <---
array_push($curr["RL"] = $value[3]); # <---
array_push($curr["KB"] = $value[4]); # <---
array_push($curr["BD"] = $value[5]); # <---
array_push($curr["SD"] = $value[6]); # <---
array_push($curr["KH"] = $value[7]); # <---
array_push($curr["Reihenfolge"] = $value[8]); # <---
array_push($arr[$i] = $curr); # <---
$i++; # <---
}
}
The array_push syntax is not correct (see manual page): the correct syntax is array_push( $existentArray, $newElement ). In addition, you can't use array_push to add an associative value, you can use it only for numeric key. Change $curr assignments simply in $curr['Datum'] = $value[0]; etc...
To append $curr to $arr, you have to change the line in array_push( $arr, $curr ) or (better, as php recommends if only one element is appended) $arr[] = $curr;. After these changes, the $i++; line can be deleted.
$json = array(
"Daniel" => $arDaniel,
"Andi" => $arAndi,
"Dave" => $arDave,
"Simon" => $arSimon
);
echo json_encode($json);
$db = NULL;
Now your script is clean (I hope).
Your script remain a bit redundant. You can simplify it in this way:
$array = array( 'Daniel'=>array(), 'Andi'=>array(), 'Dave'=>array(), 'Simon'=>array() );
foreach( $array as $key => &$val )
{
$query = "SELECT Datum, ID, RR, RL, KB, BD, SD, KH, Reihenfolge FROM $key ORDER BY date(Datum)";
$result = $db->query( $query );
$val = $result->fetchAll( PDO::FETCH_ASSOC );
}
$json = json_encode( $array );
echo $json;
By this way, you init an array with names as key, then, in a foreach loop by reference (&$val) you perform a sql query searching in table $key and you fetch all results directly in array (in this example the values are stored as associative arrays, like in your example, but you can use PDO::FETCH_OBJ to store data as object). At the end, you encode the array end echo it.
Edit:
I see a previous answer nearly identical to mine...
BTW, I leave mine because I have spent a lot of time to explain various errors...
Related
This question already has answers here:
Check if all values in an array exist in a database column
(2 answers)
Closed 1 year ago.
I have an array that looks something like this -> ["john.smith#gmail.com", "jane.doe#gmail.com", "jack.smith#gmail.com"]. I want to increment $count for each email that exists in the database. If it doesn't exist (invalid), then I want to push it to the $invalidEmails array.
After that, I want to set my $output according to whether all the emails in the original array are valid or not. They're valid if all of them exist in the database. I'd appreciate some help with this as I'm not sure how to go about it from here. It doesn't work for all cases right now, for example if first email is valid but second one is invalid.
This is what I have so far:
$result = $conn->query("SELECT mail FROM dej_colleagues");
$rows = mysqli_fetch_all($result, MYSQL_ASSOC);
$tags = preg_split("/\,/", $_POST['tags']);
$invalidEmails = array();
$count = 0;
for ($i = 0; $i < sizeof($tags); $i++) {
$trim_brackets = trim($tags[$i], '[]');
$trim_quotes = trim($trim_brackets, '"');
foreach($rows as $row) {
if ($trim_quotes == $row["mail"]) {
$count += 1;
break;
}
}
if ($count == 0) {
array_push($invalidEmails, $tags[$i]);
}
}
$output = array();
if (sizeof($tags) == $count) {
$output = array("validity => "valid emails");
}
else {
$output = array("validity" => "invalid emails", "emails" => $invalidEmails;
}
echo json_encode($output);
Your code seems convoluted, so rather than debug it I started with a more focussed query and worked from there.
Basically, the query asks the database for a list of emails that appear in your $tags array, then uses array_diff() to find any that appear in $tags, but not in the database.
From there you can produce your output directly.
ini_set('display_errors',1);
$mysqli = new mysqli('mysql.lv.local','userName', 'userPassword','schemaName' );
// Assuming the input is a string and not an array, json_decode it.
$tags = '["john.smith#gmail.com", "Jane.doe#gmail.com", "jack.smith#gmail.com","fred.jones#gmail.com"]';
$tags = json_decode($tags);
// switch everything to lower case
$tags = array_map('strtolower', $tags);
// Build and prepare a query with placeholders. Note conversion to lower case
$sql = 'select distinct lower(`mail`) from `emails` where lower(`mail`) in (?'.str_repeat(',?', count($tags)-1).')';
//echo $sql;
$stmt = $mysqli->prepare($sql);
// Bind the values from $tags to the query
$stmt->bind_param(str_repeat('s', count($tags)), ...$tags);
// Execute
$stmt->execute();
// Bind a variable for the result
$stmt->bind_result($email);
// Retrieve the emails in to $dbMails
$dbMails = [];
while ($stmt->fetch()) {
$dbMails[] = $email;
}
//var_dump($dbMails);
// Anything that's in $tags but not in $dbMails is invalid
$absentEmails = array_diff($tags, $dbMails);
//var_dump($absentEmails);
if ($absentEmails) {
$op= ["validity"=>"Invalid enails", 'emails'=>array_values($absentEmails)];
} else {
$op= ["validity"=>"Valid enails"];
}
echo json_encode($op);
I have a phone book array I get from a database, where everyone appears once with their stationary phone number and a second with their mobile number.
I need to make this an array where everyone has only one line, with their phone number and mobile number
//My array
$data = array(
array('name'=>'robert','family'=>'bridgstone','home'=>'0258101234'),
array('name'=>'robert','family'=>'bridgstone','phone'=>'07258101235'),
array('name'=>'dan','family'=>'swartz','home'=>'098101244'),
array('name'=>'ben','family'=>'wais','home'=>'0447256155778'),
array('name'=>'ben','family'=>'wais','phone'=>'04472861558878'),
);
//The result that should come out
$data = array(
array('name'=>'robert','family'=>'bridgstone','home'=>'0258101234','phone'=>'07258101235'),
array('name'=>'dan','family'=>'swartz','home'=>'098101244','phone'=>''),
array('name'=>'ben','family'=>'wais','home'=>'0447256155778','phone'=>'04472861558878')
);
I would do it the following way:
first I would generate a unique key that identify the row (in your case the name and the family, for example).
then check if a element with the same key exist, if it already exist merge the two component.
Optional if you only want an array of values transform the result with array_value function.
$dataArray = array(
array('name'=>'robert','family'=>'bridgstone','home'=>'0258101234'),
array('name'=>'robert','family'=>'bridgstone','phone'=>'07258101235'),
array('name'=>'dan','family'=>'swartz','home'=>'098101244'),
array('name'=>'ben','family'=>'wais','home'=>'0447256155778'),
array('name'=>'ben','family'=>'wais','phone'=>'04472861558878'),
);
$result = [];
foreach($dataArray as $data){
//Just in case that the name or the family is not assigned (operator ??)
$key = ($data['name']??'').'-'.($data['family']??'');
$result[$key] = array_merge($result[$key]??[],$data);
}
//Optional, get only the array values
$result = array_values($result);
I did so
$data = array(
array('name'=>'robert','family'=>'bridgstone','home'=>'0258101234'),
array('name'=>'robert','family'=>'bridgstone','phone'=>'07258101235'),
array('name'=>'dan','family'=>'swartz','home'=>'098101244'),
array('name'=>'ben','family'=>'wais','home'=>'0447256155778'),
array('name'=>'ben','family'=>'wais','phone'=>'04472861558878'),
);
count($data) < 2 ? exit(): $data;
for($i=0;$i<count($data);$i++){
$array_unique[$i] = $data[$i]["name"];
$array_unique[$i] = $data[$i]["family"];
}
$array_unique = array_unique($array_unique);
if(count($array_unique) == 1){
$last_array[0]=$array_unique[0];
$last_array[0]["phone"]=$array_unique[0]["phone"];
}
else{
$array_uniqueKeys = array_keys($array_unique);
for($i = 0;$i < count($array_unique);$i++){
$firstIndex = $i + 1;
$firstIndex == count($array_unique) ? $nextKey = count($data) : $nextKey = $array_uniqueKeys[$firstIndex];
$paar = $nextKey - $array_uniqueKeys[$i];
$dataslice = array();
$i3=0;
for($i2 = $array_uniqueKeys[$i];$i2 < ($array_uniqueKeys[$i]+$paar);$i2++){
if(in_array($i2,$array_uniqueKeys)){
$last_array[$i]=$data[$i2];
}
else{
$last_array[$i]["phone"]=$data[$i2]["phone"];
}
$i3++;
}
}
}
print_r($last_array);
Post Updated
I would like to create dynamic Array in PHP to provide the same output like static Array below, I have tried to do it with while statement but it doesn't work. Could you please provide me some tips?
I would like to use 2 values from MySQL and save them in to $to variable
so first send_to1 (user account) and then value1 (amount)
<?php
$con=mysqli_connect("localhost","test","test","test");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT * FROM users");
$to=Array(
while($row = mysqli_fetch_array($result))
{
$send_to1 => $value1,
$send_to2=> $value2
}
);
mysqli_close($con);
?>
It's as simple as just adding elements to the array:
//Setup blank array
$example = array();
//Create a loop, for example purposes.
foreach(range(0, 99) as $i){
//Create random variable that we'll add to our array
$randVar = mt_rand(1, 90000);
//$i will be our array key/index
$example[$i] = randVar;
}
//var_dump the array so you can see the structure / end result
var_dump($example);
You could also create it like so:
//Create random array key/index
$myRandKey = mt_rand(1, 90000);
//Create random variable value.
$myRandVar = mt_rand(1, 90000);
//Setup an array
$example = array(
$myRandKey => $myRandVar
);
//Another array key that we'll add to our array
$secondKey = 'test';
//Add it
$example[$secondKey] = 'This is just an example!';
//Dump out the array
var_dump($example);
array_push will also work (using mysql_fetch_assoc, like in your example):
$example = array();
while($row = mysql_fetch_assoc($result)){
array_push($example, $row);
}
var_dump($example);
In your particular example (since you added your code):
print_r($new_array[] = $row[]);
should be changed to:
print_r($new_array[] = $row);
In your code, I'd change it to:
$new_array = array();
while($row = mysqli_fetch_array($result)){
$new_array[] = $row;
}
Or, if you want to key your array by a unique column (Primary key, for example):
$new_array = array();
while($row = mysqli_fetch_array($result)){
$new_array[$row['id']] = $row;
}
Look, this is so easy, you just need to pay more attention to the answers you're getting here.
Here is the simplest way you can do it:
$to = array();
$to[] = array($send_to1 => $value1);
$to[] = array($send_to2 => $value2);
while ( $row = mysqli_fetch_array($result) ) {
$to[] = array($row['send_tox' => $row['valuex']);
}
You need to first understand how Arrays and Loops work in PHP, then try to make a dynamic array in a loop.
Actually you almost got it. It's lower A in 'array'
To initialize an empty array:
$to = array();
In your case (you already have some values), you can do:
$to = array(
$send_to1 => $value1,
$send_to2=> $value2
);
In either case, you can later add more elements doing
$to[$someOtherKey] = $someOtherValue;
Hi I am trying to store MySQL result into a global array
class db
{
function CustomLoad($table_name,$Fields)
{
global $_MYSQL_DATA;
$_MYSQL_DATA=array();
$qry = mysql_query("SELECT * FROM $table_name") or die(mysql_error());
while($row = mysql_fetch_assoc($qry))
{
foreach($Fields as $r=>$key)
{
$_MYSQL_DATA[$r] = $row[$r];
}
}
}
}
I am calling like this
$dbObj = new db();
$fields = array("FIELD_1"=>"FIELD 1","FIELD_2"=>"FIELD 2","FIELD_3"=>"FIELD 3","FIELD_4"=>"FIELD 4");
$dbObj->CustomLoad("registrations",$fields);
print_r($_MYSQL_DATA);
The problem is I am getting the last result only. like Array ( [FIELD_1] => A [FIELD_2] => B [FIELD_3] => C [FIELD_4]=> D )
Just use the following:
$_MYSQL_DATA = array(); // you should declare your variables, even if it's not mandatory
while($row = mysql_fetch_assoc($qry)) // USE PDO or MySQLi !!!!!
{
$_MYSQL_DATA[] = $row;
}
Note
The [] operator generates the smallest, positive, numeric key that is not used in your array.
Examples:
$array = array(0 => 'b', 1 => 'a');
$array[] = 'c'; // will place it in $array[2]
$array = array();
$array[] = 'a'; // will place in $array[0]
And now ... the rant about PDO / MySQLi (because I have to say it :P).
MySQL is officially deprecated since PHP 5.5, and it will no longer be maintained. You should consider porting your code to either MySQLi or PDO.
in foreach there should be $row not $Field. Also run a counter
$i=0;
while($row = mysql_fetch_assoc($qry))
{
foreach($row as $r=>$key)
{
$_MYSQL_DATA[$i][$r] = $key;
}
$i++;
}
I have an array of my inventory (ITEMS A & B)
Items A & B are sold as sets of 1 x A & 2 x B.
The items also have various properties which don't affect how they are distributed into sets.
For example:
$inventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK")
);
I want to redistribute the array $inventory to create $set(s) such that
$set[0] => Array
(
[0] => array(A,PINK)
[1] => array(B,RED)
[2] => array(B,BLUE)
)
$set[1] => Array
(
[0] => array(A,MAUVE)
[1] => array(B,YELLOW)
[2] => array(B,GREEN)
)
$set[2] => Array
(
[0] => array(A,ORANGE)
[1] => array(B,BLACK)
[2] => NULL
)
$set[3] => Array
(
[0] => array(A,GREY)
[1] => NULL
[2] => NULL
)
As you can see. The items are redistributed in the order in which they appear in the inventory to create a set of 1 x A & 2 x B. The colour doesn't matter when creating the set. But I need to be able to find out what colour went into which set after the $set array is created. Sets are created until all inventory is exhausted. Where an inventory item doesn't exist to go into a set, a NULL value is inserted.
Thanks in advance!
I've assumed that all A's come before all B's:
$inventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK")
);
for($b_start_index = 0;$b_start_index<count($inventory);$b_start_index++) {
if($inventory[$b_start_index][0] == 'B') {
break;
}
}
$set = array();
for($i=0,$j=$b_start_index;$i!=$b_start_index;$i++,$j+=2) {
isset($inventory[$j])?$temp1=$inventory[$j]:$temp1 = null;
isset($inventory[$j+1])?$temp2=$inventory[$j+1]:$temp2 = null;
$set[] = array( $inventory[$i], $temp1, $temp2);
}
To make it easier to use your array, you should make it something like this
$inv['A'] = array(
'PINK',
'MAUVE',
'ORANGE',
'GREY'
);
$inv['B'] = array(
'RED',
'BLUE',
'YELLOW',
'GREEN',
'BLACK'
);
This way you can loop through them separately.
$createdSets = $setsRecord = $bTemp = array();
$bMarker = 1;
$aIndex = $bIndex = 0;
foreach($inv['A'] as $singles){
$bTemp[] = $singles;
$setsRecord[$singles][] = $aIndex;
for($i=$bIndex; $i < ($bMarker*2); ++$i) {
//echo $bIndex.' - '.($bMarker*2).'<br/>';
if(empty($inv['B'][$i])) {
$bTemp[] = 'null';
} else {
$bTemp[] = $inv['B'][$i];
$setsRecord[$inv['B'][$i]][] = $aIndex;
}
}
$createdSets[] = $bTemp;
$bTemp = array();
++$bMarker;
++$aIndex;
$bIndex = $bIndex + 2;
}
echo '<pre>';
print_r($createdSets);
print_r($setsRecord);
echo '</pre>';
To turn your array into an associative array, something like this can be done
<?php
$inventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK")
);
$inv = array();
foreach($inventory as $item){
$inv[$item[0]][] = $item[1];
}
echo '<pre>';
print_r($inv);
echo '</pre>';
Maybe you can use this function, assuming that:
... $inventory is already sorted (all A come before B)
... $inventory is a numeric array staring at index zero
// $set is the collection to which the generated sets are appended
// $inventory is your inventory, see the assumptions above
// $aCount - the number of A elements in a set
// $bCount - the number of B elements in a set
function makeSets(array &$sets, array $inventory, $aCount, $bCount) {
// extract $aItems from $inventory and shorten $inventory by $aCount
$aItems = array_splice($inventory, 0, $aCount);
$bItems = array();
// iterate over $inventory until a B item is found
foreach($inventory as $index => $item) {
if($item[0] == 'B') {
// extract $bItems from $inventory and shorten $inventory by $bCount
// break out of foreach loop after that
$bItems = array_splice($inventory, $index, $bCount);
break;
}
}
// append $aItems and $bItems to $sets, padd this array with null if
// less then $aCount + $bCount added
$sets[] = array_pad(array_merge($aItems, $bItems), $aCount + $bCount, null);
// if there are still values left in $inventory, call 'makeSets' again
if(count($inventory) > 0) makeSets($sets, $inventory, $aCount, $bCount);
}
$sets = array();
makeSets($sets, $inventory, 1, 2);
print_r($sets);
Since you mentioned that you dont have that much experience with arrays, here are the links to the php documentation for the functions I used in the above code:
array_splice — Remove a portion of the array and replace it with something else
array_merge — Merge one or more arrays
array_pad — Pad array to the specified length with a value
This code sorts inventory without any assumption on inventory ordering. You can specify pattern (in $aPattern), and order is obeyed. It also fills lacking entries with given default value.
<?php
# config
$aInventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK"),
array("C","cRED"),
array("C","cBLUE"),
array("C","cYELLOW"),
array("C","cGREEN"),
array("C","cBLACK")
);
$aPattern = array('A','B','A','C');
$mDefault = null;
# preparation
$aCounter = array_count_values($aPattern);
$aCurrentCounter = $aCurrentIndex = array_fill_keys(array_unique($aPattern),0);
$aPositions = array();
$aFill = array();
foreach ($aPattern as $nPosition=>$sElement){
$aPositions[$sElement] = array_keys($aPattern, $sElement);
$aFill[$sElement] = array_fill_keys($aPositions[$sElement], $mDefault);
} // foreach
$nTotalLine = count ($aPattern);
$aResult = array();
# main loop
foreach ($aInventory as $aItem){
$sElement = $aItem[0];
$nNeed = $aCounter[$sElement];
$nHas = $aCurrentCounter[$sElement];
if ($nHas == $nNeed){
$aCurrentIndex[$sElement]++;
$aCurrentCounter[$sElement] = 1;
} else {
$aCurrentCounter[$sElement]++;
} // if
$nCurrentIndex = $aCurrentIndex[$sElement];
if (!isset($aResult[$nCurrentIndex])){
$aResult[$nCurrentIndex] = array();
} // if
$nCurrentPosition = $aPositions[$sElement][$aCurrentCounter[$sElement]-1];
$aResult[$nCurrentIndex][$nCurrentPosition] = $aItem;
} // foreach
foreach ($aResult as &$aLine){
if (count($aLine)<$nTotalLine){
foreach ($aPositions as $sElement=>$aElementPositions){
$nCurrentElements = count(array_keys($aLine,$sElement));
if ($aCounter[$sElement] != $nCurrentElements){
$aLine = $aLine + $aFill[$sElement];
} // if
} // foreach
} // if
ksort($aLine);
# add empty items here
} // foreach
# output
var_dump($aResult);
Generic solution that requires you to specify a pattern of the form
$pattern = array('A','B','B');
The output will be in
$result = array();
The code :
// Convert to associative array
$inv = array();
foreach($inventory as $item)
$inv[$item[0]][] = $item[1];
// Position counters : int -> int
$count = array_fill(0, count($pattern),0);
$out = 0; // Number of counters that are "out" == "too far"
// Progression
while($out < count($count))
{
$elem = array();
// Select and increment corresponding counter
foreach($pattern as $i => $pat)
{
$elem[] = $inv[ $pat ][ $count[$i]++ ];
if($count[$i] == count($inv[$pat]))
$out++;
}
$result[] = $elem;
}