Arrange parent-child relationship - php

I have read the Build a tree from a flat array in PHP and the Convert a series of parent-child relationships into a hierarchical tree? but could not figure out how to implement it for my problem. There is a pairs of relations as such:
Array
(
[0] => catalog.iden = catalog_sub.parent
[1] => catalog.group = catalog_group.iden
[2] => catalog_photo.iiden = catalog.iden
)
I have not NULL, or 0, or any explicit condition to stop looping. All what I know is what field has primary key with auto_increment attribute. Say in that example it will be field named 'iden' so in the relation it will be "parent".
I have spent a week to resolve this problem but with no result. So could anybody help me to arrange this array in order of relations. It may be tree of flat array.
Thanks in advance.
UPDATE
So far I only managed to do so:
foreach($matches[0] as &$match) {
$ref = explode('=', $match); // split by = sign
$lft = explode('.', $ref[0]);
$rgt = explode('.', $ref[1]);
if($lft[1] == 'iden') {
$arr[$lft[0]][$rgt[0]] = $rgt[1];
} else {
$arr[$rgt[0]][$lft[0]] = $lft[1];
}
}
What gives sorting by primary key and grouping by used tables:
Array
(
[catalog] => Array
(
[catalog_sub] => parent
[catalog_photo] => iiden
)
[catalog_group] => Array
(
[catalog] => group
)
)

Related

PHP if condition for adding and removing without completely rebuilding

I'm creating a PostgreSQL table column management tool to quickly add, remove and rearrange columns in tables. Thus far it is working great in simple scenarios where I simply append a column to the end or remove an existing column. Each of my if conditions call other functions to append a new column, delete an existing column or to rebuild the table as a whole; these functions work great as far as I can currently test.
How do I create an if condition where I'll call both the append function and the delete function instead of the rebuild function?
I have several arrays to help me determine the logic though I'm having trouble getting it worked out. Here are the arrays of column names and again in this scenario I should not be calling the rebuild function, need to call the append function and the delete function.
In this scenario all I'm going to do is delete the column id_2 and add the column id_4 so there is no need to rearrange the order or columns.
$columns_db - The columns as they exist in the PostgreSQL database.
Array
(
[0] => id
[1] => id_1
[2] => id_2
[3] => id_3
)
$columns_updated - The columns in the database that we're going to keep.
Array
(
[0] => id
[1] => id_2
[2] => id_3
)
$columns_submitted - The final way the columns should appear when all is done,
Array
(
[0] => id
[1] => id_2
[2] => id_3
[3] => id_4
)
$columns_slice
$columns_slice = array_slice($columns_submitted,0,(count($columns_updated) - 1),true);
Array
(
[0] => id
[1] => id_2
)
$columns_remove - The column(s) that will be dropped.
Array
(
[1] => id_1
)
$columns_append - The column(s) that will be created.
Array
(
[id_4] => bigint
)
Perform column deletions first
implode column list after deletions ($before = implode($columns_updated);)
implode column list after additions ($after = implode($columns_submitted))
if (strpos($after, $before) === 0) { /* the additions are at the end */ }
Make sure you use the === operator.
As a one-liner:
$rebuild = (strpos(implode($columns_submitted), implode($columns_updated)) !== 0);
I generally prefer straight forward if / else if conditions though it seemed that it would be simply too wildly convoluted to maintain. #AbraCadaver had the good sense to keep the add/remove detection separate which I adapted (would have up-voted if it wasn't deleted). I've tested about a dozen tricky combinations and haven't been able to find any false-positives. Here is the debug version I used to help visualize the logic:
$rebuild = 0;
foreach ($columns_append as $k1 => $v1)
{
//echo '<div class="clear">k1 = '.$k1.'</div>';
if (in_array($k1,$columns_slice)) {$rebuild = 1; break;}
else
{
$columns_submitted_key = array_search($k1,$columns_submitted);
//echo '<div class="clear">columns_submitted_key: '.$columns_submitted_key.', $columns_updated count = '.count($columns_updated).'</div>';
if ($columns_submitted_key<count($columns_updated)) {$rebuild = 1; break;}//echo '<div class="error">Yeah, rebuild here.</div>';
}
}
if ($rebuild>0) {echo '<div class="clear">1, rebuild.</div>';}
else
{
if (count($columns_append)>0) {echo '<div class="clear">2,append</div>';}
if (count($columns_remove)>0) {echo '<div class="clear">3,delete</div>';}
}

PHP Recursion with Associative Array (Menu structure)

I've been banging my head against a wall today. I have a mysql table that has a list of menu items which have a recursive parent/child relationship. I need to create an associative array that matches it.
Here is my code, and below it is an explanation of my problem.
MySQL Database
CREATE TABLE IF NOT EXISTS `menus` (
`sectionid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`parentid` int(10) unsigned NOT NULL DEFAULT '0',
`name` varchar(128) NOT NULL DEFAULT '',
PRIMARY KEY (`sectionid`)
);
INSERT INTO `menus` (`sectionid`, `parentid`, `name`) VALUES
(1, 0,'DOWNLOADS'),(4, 1,'Player Scenarios'),
(5, 1,'Co Op Scenarios'),(9, 1,'MAPS');
PHP CODE
function get_db_children($parentid) {
$mysqli = mysqli_open();
$sqlStr = "select sectionid as childid from menus where parentid=$parentid order by sectionid";
$result = $mysqli->query($sqlStr);
$mysqli->close();
return $result;
}
function get_children(&$node) {
foreach ($node as $key=>$value) {
$result = get_db_children($key);
while ($row = $result->fetch_assoc()) {
$tmp = array($row['childid'] => array());
$node[$key][$row['childid']]= get_children($tmp);
}
}
return $node;
}
===========================================
The above functions are called from my main script as follows:
$categories[0] = array ();
get_children($categories);
print "Categories=".print_r($categories);
exit;
==============
My PROBLEM.
My problem is that the structure of the returned array is not QUITE how I want it.
The code above returns:
Categories=
Array ( [0] => Array
( [1] => Array
( [1] => Array
( [4] => Array
( [4] => Array ( ) )
[5] => Array
( [5] => Array ( ) )
[9] => Array
( [9] => Array ( ) )
)
)
)
)
What I want is:
Categories=
Array ( [0] => Array
( [1] => Array
(
( [4] => Array ( ) )
( [5] => Array ( ) )
( [9] => Array ( ) )
)
)
)
A null array indicates no children.
I can't figure out how to get rid of the double up on key values. :(
If anyone can help, would be much appreciated.
Cheers,
Nap
Changing the approach a little has fixed my problem. Instead of passing the $categories array by reference, I just pass the ID of the parent menu item and return the array.
Code below uses same SQL data and SQL accessor function get_db_children($parentid) as given in my OP. I'm sure this could be improved upon, but at least I've got my result.
#Josh, thnx for your input.
PHP Functions
function get_twigs($nodeid) {
$result = get_db_children($nodeid);
if ($result->num_rows != 0) {
while ($row = $result->fetch_assoc()) {
$node[$row['childid']] = array();
$node[$row['childid']] = get_twigs($row['childid']);
}
} else {
$node=NULL; // or any other 'no children below me indicator.
}
return $node;
}
function get_branch($nodeid) {
$node[$nodeid] = array();
$node[$nodeid] = get_twigs($nodeid);
return $node;
}
PHP Caller
$categories = get_branch(0);
Finally got it going.
:)
you are passing in the $node by reference therefore instead of doing $node[$key][$row['childid']] = get_children($tmp); you should really be doing
$value[$row['childid']] = get_children($tmp)
or
$node[$row['childid']] = get_children($temp)
but if you go with the second option you will have to pass in $categories[0] on the first call to get_children (which is what you are doing when you are making the recurring calls)
update:
ill try and explain the reason for that...
as you can see the first entry (0) is not duplicated. only after the first recurring call is where your problem starts, the reason for that is because you are passing in the child array by reference therefore the second time around [as a example] when you call get_children the $node var actually already refers to the nested part
array(
0=>array(
1=>array(/*this is what $node actually is the second time around*/
/*when you say $node[$key][$row['childid']] what you are actually saying is assign the value to array[0][1][1][4] = array())*/
)
)
);
i hope this helps. if i can think of a way to explain it batter ill come back and update...

Show Can I pull Each Of These Out Of An Array?

I am having trouble pulling elements out of this multi-dimensional array?
Here is my code below:
$ShowTables = $Con->prepare("SHOW TABLES");
$ShowTables->execute();
$ShowTResults = $ShowTables->fetchAll();
If I print_r($ShowTResults); I get this multi-dimensional array:
Array (
[0] => Array ( [Tables_in_alltables] => userinformation [0] => userinformation )
[1] => Array ( [Tables_in_alltables] => users [0] => users )
)
Foreach new table is loaded it adds another dimension of the array. I want to pull each of the table names, out of the multi-dimensional array into a new array which I can use for future plans.
Would anyone have any ideas?
I have tried 1 foreach Loop; but this served no justice.
You want to fetch all results of the first column in form of an array:
$ShowTResults = $Con->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN, 0);
print_r($ShowTResults);
This gives you:
Array (
[0] => userinformation
[1] => users
)
Which I think is what you're looking for.
Another variant (a bit more complicated, but fitting for similar but little different cases) is to fetch the results as function (PDO::FETCH_FUNC) and directly map the result:
$ShowTResults = $ShowTables->fetchAll(PDO::FETCH_FUNC, function($table) {
return $table;
});
A Solution I tried: Perhaps not as other will do, which is in full respect. But Here is mine:
$DatabaseTables = array();
foreach($ShowTResults AS $ShowTResult)
{
foreach ($ShowTResult AS $ShowT)
{
$DatabaseTables[] = $ShowT;
}
}
$DatabaseTables = array_unique($DatabaseTables); //Deletes Duplicates in Array
unset($ShowTResult);
unset($ShowT); // Free up these variables
print_r($DatabaseTables);

PHP - Removing one array layer

I have a simple PHP function that will grab information from a database based on a unique ID:
function oracleGetGata($query, $id="id") {
global $conn;
$results = array();
$sql = OCI_Parse($conn, $query);
OCI_Execute($sql);
while ( false!==($row=oci_fetch_assoc($sql)) ) {
$results[ $row[$id] ] = $row;
}
return $results;
}
So for example $array = oracleGetData('select * from table') would return:
[1] => Array
(
[Title] => Title 1
[Description] => Description 1
)
[2] => Array
(
[Title] => Title 2
[Description] => Description 2
)
This is fine, however, if I just want to return one record $array = oracleGetData('select * from table where id = 1') it returns the data like:
[] => Array
(
[Title] => Title 1
[Description] => Description 1
)
Not only am I unsure of how to reference this (there is nothing identifying the array) I'd also like to somehow change my function so if it just returns one record, it will just be a simple one dimensional array.
I've looked into the usual PHP array functions but can't find anything that'll help, nor an easy way of identifying how deep the array is.
Would really appreciate any help, thank you
Use array_pop():
$array = array_pop(oracleGetData('select * from table where id = 1'));
You will then get one single array:
Array
(
[Title] => Title 1
[Description] => Description 1
)
Instead of an array embedded in another one:
Array
(
[] => Array
(
[Title] => Title 1
[Description] => Description 1
)
}
I think there is an logic error in your script:
Change
$results[ $row[$id] ] = $row;
into
$results[] = $row;
The problem is, that you want to have the Database key value as array key value, but you don't know the Database key, since you don't know what the query will look like.
You could try:
$results[$row['id']] = $row;
But this only works when all of your results have a Database key named "id".
You pass a $id in the function signature, but in the loop you uses $row[$id], Why? Maybe the error is there.
If you want a sequencial id in your result set, you don't need use the $id, you can uses array_push() function
array_push($result, $row);
OR
$results[] = $row;

Need an Array Count On Common Values

I am Using PHP and Mysql, Apachhe
I Have an Array
Array
(
[2] => Array
(
[0] => 6
[1] => 2
)
[1] => Array
(
[0] => 6
[1] => 2
)
)
Here The middle container is the Document ID and the final children are userids, Here I am looking for a way to find a method to count the common user ids among all the different Documents. I also need it specified that a particular user id available in which documentids...
could Some one guide me to achieve this?
Thanks in Advance,
OM
$unique_users = array();
foreach ($docs as $doc_id => $users)
{
foreach ($users as $user_id)
{
if (!isset($unique_users[$user_id]))
$unique_users[$user_id] = array($doc_id);
else
$unique_users[$user_id][] = $doc_id;
}
}
echo count($unique_users); // number of users
var_dump($unique_users[1]); // list of documents user_id #1 is in
Add all the ids from the first element to an array. Then continue to loop through the other elements and keep only the ids that are also in the current element.

Categories