PHP MYSQL Depth Querying - php

I'm new and I feel lost. Is this code doing a infinite loop?
Should I remove line 2-4? Is line 19 "$_row['employee_manager_id']," even important?
Any advice on how I should do this? Thank you.
function get_employees_by_hierarchy( $_employee_id = 0,$_depth = 0,$_org_array = array() ) {
if ( $this->org_depth < $_depth ) {
$this->org_depth = $_depth;
}
$_depth++;
$_query = "SELECT * FROM employees WHERE ";
if ( !$_employee_id ) {
$_query .= "employee_manager_id IS NULL OR employee_manager_id = 0";
}
else {
$_query .= "employee_manager_id = " . $this->dbh->quoteSmart( $_employee_id );
}
$_result = $this->query( $_query );
while ( $_row = $_result->fetchRow() ) {
$_row['depth'] = $_depth;
array_push( $_org_array, $_row );
$_org_array = $this->get_employees_by_hierarchy(
$_row['employee_manager_id'],
$_depth,
$_org_array
);
}
return $_org_array;
}

From the looks of it:
It does do an infinite loop. There isn't a terminating condition on the recursion. you need a condition that causes this:
$_org_array = $this->get_employees_by_hierarchy(
$_row['employee_manager_id'],
$_depth,
$_org_array
);
to not run, or at least to assign it to something that isn't get_employees_by_hierarchy.
after you fix that there it will be an infinite loop if an employee is their own manager at some point.
Impossible to say, is 'depth' used anywhere else? This function returns the $_org_array that has the 'depth' field but we can't see if it's used. It certainly isn't breaking anything in this code.
Without seeing sample data I'd say, yes it's important. The code recurses using the self referential employees table using the manager's id as the next level of the hierarchy.
put a check in before you assign the $_org_array that checks if the manager's id is null, if that happens do something like this: $_org_array = $this.

Related

Dynamic Table Name in Propel Query

I am wondering if you can make the Table name of the propel query dynamic(sort of like a variable variable)? An example would be like \"DynamicVar"Query::create(). I have it working in ifs like in my example below, but could get rid of quite a few lines if made more dynamically. The tables are all setup the same, so they can be treated like the same object they just have different names.
Currently have something like this happening:
//$dynamic is a result of grabbing it from a different table
//that corresponds to values passed by AJAX
$dyanmic = "Customer"
$query = null;
If( $dynamic == "Customer" ) $query = \CustomerQuery()::create();
If( $dynamic == something2 ) $query = \Table2Query()::create();
If( $dynamic == something3 ) $query = \Table3Query()::create();
If( $query != null ) {
$query->filterBy("something");
$query->find();
}
I played around with the code some, and the code below will work for dynamically changing the table as long as each table can be treated like the same object. You can define your $table and use it in this fashion for a function that returns the object that you want
function Get_Table($table,$id){
$query = null;
$queryClass = '\\'. ucfirst($table) . 'Query';
if ( class_exists( $queryClass ) ) {
$$dynamics = $queryClass::create()
->filterById($id)
->find();
if( $dynamics->getFirst() == null ) { return false; }
/** #var \Base\.ucfirst($table) $dynamic*/
$dynamic= $dynamics->getFirst();
return $dynamic;
}
//On Failure
else {
return false;
}
}

query inside while loop only shows 1 result

i'm making a while loop in php and it all goes well but the problem is that
I don't only want to get the id of the user but also some other stuff that is inside another table, so when I go ahead and make a query inside this while loop and select everything from that second table (where the id is equal to the id of the result from the first query), it only returns 1 result...
So this is the code that I currently have:
public function getFriends($id)
{
global $params;
$get = $this->db->select("{$this->DB['data']['friends']['tbl']}", "*",
array(
"{$this->DB['data']['friends']['one']}" => $id
)
);
if($get)
{
while($key = $get->fetch())
{
$query = $this->db->query("SELECT * FROM {$this->DB['data']['users']['tbl']}
WHERE {$this->DB['data']['users']['id']} = :id",
array(
"id" => $key->{$this->DB['data']['friends']['two']}
)
);
while($row = $query->fetch())
{
$params["user_friends"][] = [
"id" => $key->{$this->DB['data']['friends']['two']},
"name" => $row->{$this->DB['data']['users']['username']},
"look" => $row->{$this->DB['data']['users']['figure']}
];
}
}
}
else
{
$params["update_error"] = $params["lang_no_friends"];
}
}
Thanks in advance!
Please help me out!
In the absence of answers, I don't know what db framework you are using behind the scenese...PDO, mysqli_, or (hopefully not) mysql_. But, in any case, the problem might be that your second query stops the first from continuing. I would use PDO->fetchAll() to get them all...but you say you can't do that...so, looping the first and loading those results into an array is the first thing I would do to see if this is the problem:
public function getFriends($id)
{
global $params;
$get = $this->db->select("{$this->DB['data']['friends']['tbl']}", "*",
array(
"{$this->DB['data']['friends']['one']}" => $id
)
);
$firstResults = array();
if( $get ) {
while( $key = $get->fetch() ) {
$firstResults[] = $key;
}
}
else
{
$params["update_error"] = $params["lang_no_friends"];
}
foreach( $firstResults AS $key )
{
$query = $this->db->query("SELECT * FROM {$this->DB['data']['users']['tbl']}
WHERE {$this->DB['data']['users']['id']} = :id",
array(
"id" => $key->{$this->DB['data']['friends']['two']}
)
);
while($row = $query->fetch())
{
$params["user_friends"][] = [
"id" => $key->{$this->DB['data']['friends']['two']},
"name" => $row->{$this->DB['data']['users']['username']},
"look" => $row->{$this->DB['data']['users']['figure']}
];
}
}
}
If this doesn't work, then we need more data...e.g. what is the query generated? When you run it manually does it return more than one result? If you get rid of the inner-query, does this fix it? etc.
The first step when diagnosing PHP and Mysql issues is to add lines to your code that tell you what each line is doing (declare each time a loop is entered; when each mysql query is run, spit out the query string) so you can narrow down where the problem is. Often this makes you feel stupid in retrospect: "Duh, this query didn't return anything because I formatted the record ID wrong" and so forth.
The code snippet you've provided above isn't super helpful to me. I'm a troubleshooter (not a parser) so I need diagnostic data (not straight code) to be of any more help than this.

PDO prepare/execute the table and append WHERE's

I'm trying to do the following:
public function checkResult($table, $appends)
{
$append = null;
foreach ($appends as $key => $val)
$append = " AND `{$key}` = '{$val}'";
$result = $this->fetchObj("
SELECT *
FROM :cms_table
WHERE id :append
", array(
":cms_table" => $table
":append" => $append
));
return ($result ? true : false);
}
But I can't get this working because I don't know how to do this in PDO.
Also when I leave the :append my query isn't working either. It looks like I can't execute a table. When I change :cms_table to the cms_pages (table I need) it works correctly.
I couldn't find a thing about such query's in PDO. Anyone who can help me out?
Don't try to outsmart yourself.
You don't need no checkResult() function, as well as no other function of similar structure.
$sql = "SELECT 1 FROM table WHERE field = ? AND col = ?";
$found = $db->fetchObj($sql, array(1,2));
is all you actually need.

next_record called with no query pending

I want to call a PHP function :
$rights = $user->recupererDroitCreateur($_SESSION[CODE_USER]);
Code of recupererDroitCreateur is :
function recupererDroitCreateur($user_id) {
$ret = array();
$sSQL = "SELECT cm.class_menu_code
FROM menu m
LEFT JOIN classe_menu cm
ON m.class_menu_code = cm.class_menu_code
WHERE m.menu_deleted = 0 AND m.menu_visible = 1 AND cm.class_menu_parent IS NULL AND cm.class_menu_deleted = 0
ORDER BY cm.class_menu_lib, m.menu_titre";
$this->db->query($sSQL);
while ( $this->db->next_record() ) {
$code = $this->db->f('class_menu_code');
$strMenus = $code.";";
$this->recupererMenus($code, $code, $user_id, $strMenus);
}
return (explode(";", $strMenus));
}
Code of recupererMenus is :
function recupererMenus($classRoot, $classParentDirect, $user_id, &$menus)
{
$sSQL1 = "SELECT class_menu_code FROM classe_menu WHERE class_menu_parent = '$classParentDirect' AND class_menu_deleted = 0";
$this->db->query($sSQL1);
while ( $this->db->next_record() ) {
$this->recupererMenus($classRoot, $this->db->f('class_menu_code'), $user_id, $menus);
}
$sSQL = "SELECT m.menu_code
FROM menu m
LEFT JOIN classe_menu cm
ON m.class_menu_code = cm.class_menu_code
WHERE m.menu_deleted = 0 AND m.menu_visible = 1 AND cm.class_menu_parent = '$classParentDirect' AND cm.class_menu_deleted = 0
ORDER BY cm.class_menu_lib, m.menu_titre";
$this->db->query($sSQL);
while ( $this->db->next_record() )
{
$menus .= $this->db->f('menu_code').";";
}
}
In runtime there is the error next_record called with no query pending : the error output tells the lines which cause the error and it says the line corresponding to this statement : while ( $this->db->next_record() ) { , there is also line pointing to the statement $this->recupererMenus($code, $code, $user_id, $strMenus);
So what is wrong in my codes ?
In recupererMenus you recursively call recupererMenus. Since there's no query identifier passed to next_record, using multiple querys will create a big mess.. When you return from the recursive call, you are going to try to fetch the next record with next_record for a previous query, but your DB framework doesn't know about this..
I don't know the framework you use, but you either have to pass the identifier (if it's possible at all), or first fetch all the results, and then do the recursive call.

Trouble with MySQLi and while loops

I have this code here within a class:
function getRolePerms($role)
{
if (is_array($role))
{
$roleSQL = "SELECT * FROM `role_perms` WHERE `roleID` IN (" . implode(",",$role) . ") ORDER BY `ID` ASC";
} else {
$roleSQL = "SELECT * FROM `role_perms` WHERE `roleID` = " . floatval($role) . " ORDER BY `ID` ASC";
}
var_dump($roleSQL);
$this->database->dbquery($roleSQL);
$perms = array();
while($row = $this->database->result->fetch_assoc())
{
$pK = strtolower($this->getPermKeyFromID($row['permID']));
var_dump($pK);
if ($pK == '') { continue; }
if ($row['value'] === '1') {
$hP = true;
} else {
$hP = false;
}
$perms[$pK] = array('perm' => $pK,'inheritted' => true,'value' => $hP,'Name' => $this->getPermNameFromID($row['permID']),'ID' => $row['permID']);
}
return $perms;
}
The var_dump() for $roleSQL is:
SELECT * FROM role_perms WHERE roleID = 1 ORDER BY ID ASC
and for $pK:
Admin
When running the query in the database directly i get a result with 8 rows.
Why is it that the loop does not recognize the multiple rows.
Also if i add the statement:
var_dump($this->database->result->fetch_assoc());
It dumps the array of the first row then the loop does the second row.
Im really baffled,
Please help
The culprit is this line here:
$perms[$pK] = array('perm' => $pK,'inheritted' => true,'value' => $hP,'Name' => $this->getPermNameFromID($row['permID']),'ID' => $row['permID']);
What happens is that all of the 8 rows you expect result in $pK == 'Admin'. When you do $perms[$pK] = array(...), each one of the 8 loop iterations ends up writing to the same array key. In the end, there is only one value in the array.
If you change it to
$perms[] = array(...);
it should work as expected, because each iteration will add a new array element with a unique integer key.
Side note:
Avoid doing this:
$roleSQL = "SELECT * FROM `role_perms` WHERE `roleID` = " . floatval($role) ...
Since roleID surely is an integer, use the right tool for the job: intval($role).
Lol the answer actually lies outside the loop.
Calling this function $this->getPermKeyFromID($row['permID']) actually override the results from the database as it was using the same database object. I fixed it by storing the results in a separate variable local to that loop.

Categories