php mysql select for organizational chart / multi level structure - php

I have build my user table like this:
Now I would like to select the 3 blue rows.
I have build the following function:
function display_children($parent, $array = array()) {
global $db;
$stmt = $db->prepare("SELECT id AS man, parent_id FROM user WHERE parent_id= ?");
$stmt->execute(array($parent));
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
display_children($row['man'], $array);
$array[] = array("man" => $row['man'], "parent_id" => $row['parent_id']);
echo $row['man']."\n"; //for debug
}
return $array;
}
print_r(display_children(50001));
My Output is:
50002
50004
50003
Array
(
[0] => Array
(
[man] => 50002
[parent_id] => 50001
)
[1] => Array
(
[man] => 50003
[parent_id] => 50001
)
)
The first three lines are correct, but the array is missing one.
The problem is, that the first parent_id has two rows. But the array is empty at the beginning. Is there a solution for my query?

the solution was to change the following line from
display_children($row['man'], $array);
to
$array = display_children($row['man'], $array);

Related

select query to make one column as key in mysql

I need the array as (2) from a single query
can anyone help ?
1. Array
(
[0] => Array
(
[crop_id] => 3
[crop_name] => Barley
)
2. Array
(
[0] => Array
(
[Barley] => 3
)
)
Don't know about query but you can do that simply using array_map()
$array[] = array('crop_id' => 3, 'crop_name' => "Barley");
$result = array_map("myfunction",$array);
print_r($result);
function myfunction($v)
{
$data = [];
$data[$v['crop_name']] = $v['crop_id'];
return $data;
}
Let's suppose you have stored your data in array named as crop_data like
$crop_data[0][crop_id]=3;
$crop_data[0][crop_name]='Barley';
....
$crop_data[n][crop_id]=187;
$crop_data[n][crop_name]='Wheat'
Try this code:
$new_crop_result=array()
foreach($crop_data as $key=>$record)
{
$new_crop_result[$key][$record[crop_name]]=$record[crop_id];
}

PHP - Compaire Two Multidimensional Arrays and Append to One Array Accordingly

Today I'm having a bit of trouble figuring out a few things in PHP. As I normally do have the tendency to ramble a bit, I will try to keep my question short but concise. Here's what I'm trying to do.
Array #1 is a multidimensional array containing the results from MySQL query done against a user table in the database. It would look as such:
Array ( [0] => Array ( [id] => 79 [firstname] => John [lastname] => Doe [province] => Province [email] => someemail#gmail.com [primaryphone] => 123-456-7890 ) [1] => Array ( [id] => 113 [firstname] => Jane [lastname] => Doe [province] => Province [email] => email#gmail.com [primaryphone] => 123-456-7890 ) )
Array #2 is another multidimensional array containing the results from a MySQL query done against a membership table in the database that contains the id of the user that is associated with the current group. It looks as follows:
Array ( [0] => Array ( [userid] => 79 ) [1] => Array ( [userid] => 115 ) [2] => Array ( [userid] => 124 ) )
What I am trying to do, is for every user returned in array #1, look for a value in array #2 under [userid] that matches the value [id] in array #1. If a match is found for each user, append the key and value [ismember] => 1 for that user in array #1 - if there is not a match, then append the pair [ismember] => 0 to array #1.
I feel that this should be a very simple process, and I'm probably just missing something that is elementary... But I've been going at it for a while now and haven't made much progress. Thank you all for your time and help.
== EDIT ==
The first array is generated by the following MySQL Query:
$query = "
SELECT
id,
firstname,
lastname,
province,
email,
primaryphone
FROM userstable
";
try
{
$stmt = $db->prepare($query);
$stmt->execute();
}
catch(PDOException $ex)
{
die("Failed to run query: " . $ex->getMessage());
}
$allusersdetails = $stmt->fetchAll();
The second array is generated by the query:
$query = "
SELECT
userid
FROM membershipstable
WHERE templateid = :currenttemplateid
";
try
{
$stmt = $db->prepare($query);
$stmt->bindParam(':currenttemplateid', $currenttemplateid);
$stmt->execute();
}
catch(PDOException $ex)
{
die("Failed to run query: " . $ex->getMessage());
}
$templateusers = $stmt->fetchAll();
You can replace the 2 queries with one query like this:
$query = "
SELECT
u.id,
u.firstname,
u.lastname,
u.province,
u.email,
u.primaryphone,
(CASE WHEN m.userid IS NULL THEN 0 ELSE 1 END) AS ismember
FROM userstable AS u
LEFT JOIN membershipstable AS m ON
m.templateid = :currenttemplateid AND
u.id = m.userid
";
try
{
$stmt = $db->prepare($query);
$stmt->bindParam(':currenttemplateid', $currenttemplateid);
$stmt->execute();
}
catch(PDOException $ex)
{
die("Failed to run query: " . $ex->getMessage());
}
$allusersdetails = $stmt->fetchAll();
This will still pull all users, whether they are members or not but, it will add ismember as column.
(the AS x part of userstable AS u and membershipstable AS m just assigns the letter as an alias of the table for the duration of the SELECT. Basically, it mostly helps you save on typing but also lets you JOIN on tables with columns of the same name.)
Welcome to the wonderful world of Structured Query Languages :D
EDIT
And just in case someone comes here trying to do exactly what the question title is asking for but doesn't happen to be querying the database but does have a arrays in the exact format that the OP had:
<?php
$array =
Array ( 0 => Array ( 'id' => '79','firstname' => 'John','lastname' => 'Doe','province' => 'Province','email' => 'someemail#gmail.com','primaryphone' => '123-456-7890',), 1 => Array ( 'id' => '113','firstname' => 'Jane','lastname' => 'Doe','province' => 'Province','email' => 'email#gmail.com','primaryphone' => '123-456-7890',) )
;
$array2 =
Array ( 0 => Array ( 'userid' => '79'), 1 => Array ( 'userid' => '115'), 2 => Array ( 'userid' => '124') );
foreach($array as $key => $userInfo) {
$isMember = 0;
foreach($array2 as $user) {
if($userInfo['id'] == $user['userid']) {
$isMember = 1;
break;
}
}
$array[$key]['ismember'] = $isMember;
}
Try this,
$firstArray = //your first array
$secondArray = // your second array
foreach($firstArray as $fa) {
$id = $fa['id'];
}
foreach($secondArray as $sa) {
$userId = $sa['userid'];
}
if($id === $userID) {
$firstArray['ismember'] = 1;
} else {
$firstArray['ismember'] = 0;
}

key value pair addition from query result, php

I am having some issues with the below, wanting to add the query result "id" as the key to the value "concat" -- Do I need a foreach for this? What is the best way?
$concatCol = mysqli_query( $connS, "SELECT id, ShipmentNumber, InvoiceNumber, BillofLading from testTable");
$data =array();
while ($row = mysqli_fetch_array($concatCol)) {
$id = $row["id"];
$ShipmentNumber = $row["ShipmentNumber"];
$InvoiceNumber = $row["InvoiceNumber"];
$BillofLading = $row["BillofLading"];
$concat = $ShipmentNumber.$InvoiceNumber.$BillofLading;
echo $concat."<br>";
$data[] = $concat;
}
I'm not really sure what your expected output is. But I think one of the following will work for you:
$data[]['id'] = $concat;
which will result in an array like this:
Array
(
[0] => Array
(
[id] => ShipmentNumberInvoiceNumberBillofLanding
)
[1] => Array
(
[id] => ShipmentNumberInvoiceNumberBillofLanding
)
)
The second option would be:
$data[$id] = $concat;
Which will yield a result like:
Array
(
[1] => ShipmentNumberInvoiceNumberBillofLanding
[4] => ShipmentNumberInvoiceNumberBillofLanding
)
Where the keys 1 and 4 are the $id for each returned row. In both example the ShipmentNumberInvoiceNumberBillofLanding would of course be the concatenated values for each row.

PHP Unique Values from Column in Array

I have an array that is generated from a SQL query that I run. It looks like the following:
$arr[$i]['id'] = $id;
$arr[$i]['name'] = $name;
$arr[$i]['email'] = $email;
How can I get the unique values from the email column? I appreciate the help.
The best answer is :
array_unique(array_column($arr, 'email'))
Either filter it in your column using the DISTINCT method in MySQL, or use something like
$uniqueEmails = array();
foreach($arr as $array)
{
if(!in_array($array['email'], $uniqueEmails)
$uniqueEmails[] = $array['email'];
}
Since PHP 5.5, a new function called array_column() is also available.
You can use it following way:
$allEmails = array_column($arr, 'email');
$uniqueEmails = array_unique($allEmails);
Remove duplicates from array comparing a specific key
Consider the same array but id of 3rd index is different:
$all_array = Array
(
[0] => Array
(
[id] => 1
[value] => 111
)
[1] => Array
(
[id] => 2
[value] => 222
)
[2] => Array
(
[id] => 3
[value] => 333
)
[3] => Array
(
[id] => 4
[value] => 111
)
)
Now, both 1 & 4 have same values. So we want to remove any of them:
$unique_arr = array_unique( array_column( $all_array , 'value' ) );
print_r( array_intersect_key( $all_array, $unique_arr ) );
If you get the list sorted by email from SQL you can improve performance by looping through the array like Gareth does, but instead only compare current email address with the last inserted email address. Below is a code example for this:
$uniqueEmails = array();
$lastemail = '';
foreach($arr as $array)
{
if($array['email'] != $lastemail)
{
$uniqueEmails[] = $array['email'];
$lastemail = $array['email'];
}
}

Recursive PHP function for adjacency-list display

I have a DB like so:
id text parent
1 Parent 1 0
2 Child of 1 1
3 Sibling 1
4 Another Parent 0
5 A first child 4
So I'm trying to capture a tree structure my listing the parents. I'm aware of the other option (nested sets I think?) but I'm going to stick with this for now. I'm now trying to get the data out of the DB and into a nested array structure in PHP. I have a function like this:
class Data_Manager
{
public $connection = '';
public $collection = array();
function __construct() {
$this->connection = mysql_connect('localhost', 'root', 'root');
$thisTable = mysql_select_db('data');
// error handling truncated
}
function get_all() {
$arr = &$this->collection;
$this->recurseTree('', 0, $arr);
var_dump($arr);
}
function recurseTree($parent, $level, $arrayNode) {
$result = mysql_query('SELECT * FROM tasks WHERE parent="' . $parent . '";');
while ($row = mysql_fetch_array($result)) {
$row['children'] = array(); //where I'd like to put the kids
$arrayNode[$row['id']]= $row;
$this->recurseTree($row['id'], $level+1, $arrayNode[$row['id']]);
}
}
}
So what I'd like to come out with is some kind of nested tree of associative arrays, but I can't figure out quite how to do that. Nothing seems to be writing to the array I pass in, and I'm sort of losing track of myself in the recursion. Can anyone help get me over this last hump that will result in something like:
[
Parent1 => [
children => ['Child of 1', 'Sibling']
],
AnotherParent => [
children => ['First Child']
]
]
And I'm less concerned with the specific form of the output. It will be turned into JSON and I haven't dealt with writing up the client-side handler yet, so no worries on exact structure.
Thanks!
Try this.
$sql = "SELECT * FROM tasks";
$r = mysql_query($sql, $conn);
$arr = array();
while ($row = mysql_fetch_assoc($r))
$arr[] = $row
function build($arrayIn, $parent)
{
$makeFilter = function($p) {return function($x) use ($p) {return $x['parent'] == $p;};};
$f = $makeFilter($parent);
$these = array_filter($arrayIn, $f);
$remaining = array_diff_assoc($arrayIn, $these);
$ans = array();
foreach($these as $cur)
{
$ans[$cur['text']] = build($remaining, $cur['id']);
}
return $ans ? $ans : null;
}
$tree = build($arr, 0)
echo_r($arr);
echo "becomes<br />";
echo_r($tree);
Here is my output:
Array
(
[0] => Array
(
[text] => a
[id] => 1
[parent] => 0
)
[1] => Array
(
[text] => b
[id] => 2
[parent] => 0
)
[2] => Array
(
[text] => c
[id] => 3
[parent] => 1
)
[3] => Array
(
[text] => d
[id] => 4
[parent] => 2
)
[4] => Array
(
[text] => e
[id] => 5
[parent] => 2
)
[5] => Array
(
[text] => f
[id] => 6
[parent] => 3
)
)
becomes
Array
(
[a] => Array
(
[c] => Array
(
[f] =>
)
)
[b] => Array
(
[d] =>
[e] =>
)
)
This bit of pseudo code should help.
function getTasks($parent = 0){
$tasks = array();
$query = mysql_query("select * from table where parent = $parent");
$rows = array();
while(($row = mysql_fetch_assoc($query)) !== FALSE){ $rows[] = $row; }
if(count($rows)){
$tasks[$parent][] = getTasks($parent);
} else {
return $tasks;
}
}
$tasks = getTasks();
You really don't need a recursive function here. Get all the data using one database query and loop over it. It will be much faster then multiple database calls.
Assuming you're storing the data in MySQL, see the answer to this question for instructions on how to write a SELECT statement against an Adjacency List table that returns everything in a hierarchy. In short, use MySQL session variables. Then take the resultset and loop over it, use a stack to push - pop - peek the last parent id to determine indentation of your data structures.
Here is a PHP class I wrote for handling all kinds of Adjacency list tasks.
http://www.pdvictor.com/?sv=&category=just+code&title=adjacency+model

Categories