codeigniter pass array to query - php

I'm trying to pass an array to a model which has a query. I'm not sure how to correctly pass the array or if i have to manipulate the array somehow.
I have this array:
Array
(
[0] => 1
[1] => 2
)
I have a controller with this line:
$ratings = $this->login_model->get_ratings($mechanicIds); // get the mechanic ratings
I have this model:
function get_ratings($mechanicId)
{
$sql = "select m.mechanic_id,
m.mechanic_name,
m.city,
m.state,
count(mr.rating_id) as num_ratings,
round(avg(mr.rating_id),2) avg_rating
from mechanic m, mechanic_rating mr, rating r
where m.mechanic_id in (?)
and m.mechanic_id = mr.mechanic_id
and mr.rating_id = r.rating_id";
$query = $this->db->query($sql, $mechanicId);
if($query->num_rows() > 0)
{
return $query->result_array();
}
else
{
return false;
}
}
It actually returns results, but the problem is it only returns the results 1 row when it should be returning 2 since there are 2 results in my array. Anyone know what i'm doing wrong?

I found this question which helped.
Below is the code I used.
Controller that contains this:
$mIds_size = count($mIds);
$i = 1;
foreach($mIds as $row)
{
if($i == $mIds_size)
{
$mechanicIds .= $row;
}
else
{
$mechanicIds .= $row.', ';
}
$i++;
}
$ratings = $this->login_model->get_ratings($mechanicIds); // get the mechanic ratings
Model which contains this:
function get_ratings($mechanicId)
{
$this->db->escape($mechanicId);
$sql = "select m.mechanic_id,
m.mechanic_name,
m.city,
m.state,
count(mr.rating_id) as num_ratings,
round(avg(mr.rating_id),2) avg_rating
from mechanic m, mechanic_rating mr, rating r
where m.mechanic_id in ($mechanicId)
and m.mechanic_id = mr.mechanic_id
and mr.rating_id = r.rating_id
group by mechanic_id";
$query = $this->db->query($sql, $mechanicId);
if($query->num_rows() > 0)
{
return $query->result_array();
}
else
{
return false;
}
}

Change this line:
$query = $this->db->query($sql, $mechanicId);
to this:
$query = $this->db->query($sql, array(implode(', ',$mechanicId)));
as per the manual

To pass an array into a raw query (not built with helper methods) for an IN condition, use the ? placeholder without wrapping in parentheses.
When binding the array to the placeholder, you must declare your array inside of an array. In other words, the "parameters" (2nd) argument of query() method expects an array which relates to each ? in the SQL string. Because the first ? is bound to an array, the $mechanicIds array must be declared as the first element of the "parameters" argument. I have tested this advice to work successfully in a CodeIgniter3 instance that I have access to.
$sql = "SELECT m.mechanic_id,
m.mechanic_name,
m.city,
m.state,
COUNT(mr.rating_id) AS num_ratings,
ROUND(AVG(mr.rating_id), 2) AS avg_rating
FROM mechanic AS m,
mechanic_rating AS mr,
rating AS r
WHERE m.mechanic_id IN ? /* <--- here */
AND m.mechanic_id = mr.mechanic_id
AND mr.rating_id = r.rating_id";
$query = $this->db->query($sql, [$mechanicIds]);
The DB_driver.php core file contains this portion of code in compile_binds() which escapes each value in the array and wraps the comma-joined string in parentheses before returning the sql string.
...
do
{
$c--;
$escaped_value = $this->escape($binds[$c]);
if (is_array($escaped_value))
{
$escaped_value = '('.implode(',', $escaped_value).')';
}
$sql = substr_replace($sql, $escaped_value, $matches[0][$c][1], $ml);
}
while ($c !== 0);
...

Related

PHP: If MYSQL Result greater than 0, add to array?

I have a MYSQL table with a list of services that user's provide:
The Enum values in these columns can be 0 or 1.
0 represents a service not offered and 1 represents a service offered.
Cleaning Tour Guide Cooking Parties
0 1 0 1
I am then running the following query In MYSQL to fetch my rows in the table:
<?php $myBio = $conn->query("SELECT * FROM user_data, user_services WHERE user_data.user_id = user_services.user_id AND user_id = $p_id");
if ($myBio->num_rows > 0) {
$row = $myBio->fetch_assoc();?>
I want to generate a list of the services the user provides (where the service has a value greater than 0) - and separate the list with commas like so:
Tour Guide, Parties
I am trying to do this by using an array:
$os = array(if($row['cleaning'] > 0) { echo 'cleaning';}, if($row['tour'] >0) { echo 'Tour Guide'; });
I am trying to use PHP if statements to decipher if a service is 0 or 1 before adding it to my list.
I do not believe it is possible to combine php if statements within an array.
Please can someone show me how I can achieve my desired result? Thanks in advance
Use array_keys() with the optional search parameter:
$services = array_keys($row, 1);
Example:
$row = [
'Cleaning' => 0,
'Tour Guide' => 1,
'Cooking' => 0,
'Parties' => 1,
];
$services = array_keys($row, 1);
var_export($services);
Result:
array (
0 => 'Tour Guide',
1 => 'Parties',
)
Demo
If your database columns have a speaking name, you can do it like this:
<?php
$arrayServices = array();
$arrayAllServices = array('Cleaning','Tour Guide','Cooking','Parties');
foreach($arrayAllServices as $service) {
if($row[$service] > 0) {
$arrayServices[] = $service;
}
}
$sServices = join(', ', $arrayServices);
echo $sServices;
If the speaking names are different from the column names, you need a second array to look up translations.
Would something like this achieve what you want?
$results=array();
if ($row['cleaning']>0) $results[]='Cleaning';
if ($row['tour']>0) $results[]='Tour Guide';
// ...
Also, please heed #tadman's comment about prepared statements!
<?php
$myResults = array();
$myBio = $conn->query("SELECT * FROM user_data, user_services WHERE user_data.user_id = ? AND user_id = ?");
$stmt->bind_param("ss",$user_services.user_id,$p_id);
$stmt->execute();
$result = $stmt->get_result();
if($result->num_rows === 0) exit('No rows');
while($row = $result->fetch_assoc())
{
$tempArray = array();
$Cleaning = $row['Cleaning'];
$Tour_Guide = $row['TourGuide'];
$Cooking = $row['Cooking'];
$Parties = $row['Parties'];
if($Cleaning == 1)
array_push($tempArray,$Cleaning)
if($Cleaning == 1)
array_push($tempArray,$Cleaning)
if($Cooking == 1)
array_push($tempArray,$Cooking )
if($Parties == 1)
array_push($tempArray,$Parties )
array_push($myResults,$tempArray);
}
?>
You will then get the myResult array which will be an array of arrays, you can then loop over the sub arrays to check values and construct the strings you intend to make.

Return value in foreach loop in CodeIgniter

I am having some trouble in returning values from model to controller Using CodeIgniter. I am passing two arrays from controller to model. I am checking whether both the arrays are not empty and looping them using foreach loop to fetch some values from database and returning the query to controller. Here's my current code
if (!empty($search_for_area) && !empty($search_for_requirement))
{ foreach($search_for_requirement as $search_value_1)
{
foreach($search_for_area as $search_value_2)
{
if($search_value_2 != null && $search_value_1 != null)
{
$nearbytution = $this->db->query('select name,area,contactno from tut_listing where area = "'.$search_value_2.'" and categoryfilter like "%'.$search_value_1.'%" and partner > "" group by name');
print_r($nearbytution->result());
}
}
}
//Line 1
}
print_r($nearbytution->result()); works fine and i am able to view the results. Where should i put return $nearbytution; so that i can get all the fetched values? I tried it in Line 1 but i was getting only values of last array value.
function returnStuff($search_for_area,$search_for_requirement) {
$arr_area = array();
$arr_filter = array();
if ( ! empty($search_for_area) and ! empty($search_for_requirement)) {
foreach($search_for_requirement as $search_value_1) {
foreach($search_for_area as $search_value_2) {
if($search_value_2 != null && $search_value_1 != null) {
$arr_area[] = $this->db->escape($search_value_2);
$arr_filter[] = $this->db->escape_like_str($search_value_1);
}
}
}
}
$str_area = 'NULL';
if ($arr_area)
$str_area = implode(', ', $arr_area);
$str_filter = "'^-$'";
if ($arr_filter)
$str_filter = "'(".implode('|', $arr_filter).")'";
$query = $this->db->query("
SELECT name, area, contactno
FROM tut_listing
WHERE area IN ({$str_area}) AND categoryfilter REGEXP {$str_filter} and partner > '' group by name
");
return $query->result();
}
Seriously, do consider this approach. You only need to bother the poor Mysql server with one call and you get all the data you want at the same time.
Apart from that, practice consistent style in your code. It will save both your time and your hair in the long run.
CodeIgniter escape()
MySQL REGEXP
Try this in the loop:
$nearbytution[] = $this->db->query('select name,area,contactno from tut_listing where area = "'.$search_value_2.'" and categoryfilter like "%'.$search_value_1.'%" and partner > "" group by name')->result();
return $nearbytution;may then be placed at your "Line 1". It will contain an array of query results.
Unless I misunderstand your question why don't you just store all the results in a big array and then return that array?
function returnStuff($search_for_area,$search_for_requirement) {
$data = array();
if (!empty($search_for_area) && !empty($search_for_requirement)) {
foreach($search_for_requirement as $search_value_1) {
foreach($search_for_area as $search_value_2) {
if($search_value_2 != null && $search_value_1 != null) {
$nearbytution = $this->db->query('select name,area,contactno from tut_listing where area = "'.$search_value_2.'" and categoryfilter like "%'.$search_value_1.'%" and partner > "" group by name');
$data[] =$nearbytution->result());
}
}
}
}
return $data;
}
Now $data will be an array of results, each containing the query results. If your result set has to be cleaned up (to remove duplicates for instance) you can just loop through it and do that cleanup.
What you could also maybe do is build a large SQL query in your foreach loops and then just do that one big query and return the results.

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.

Selecting PHP variables from joined tables

I am still trying to learn PHP and have some issues with this code. I have a field $youtubeurl in ID_Vehicles and I am trying to output some code if that field has data in it how do I select that field with this join to output the value like the sample below?
function getDealerSettings($vid)
{
include('db.php');
$query = "SELECT banner, ebay_htmlcss FROM ebay_dealersettings INNER JOIN ID_vehicles ON ebay_dealersettings.did=ID_vehicles.did WHERE vid='".$vid."'";
$result = #mysql_query($query);
if ($result)
{
$row = mysql_fetch_assoc($result);
return array("banner" => trim($row['banner']), "css" => str_replace(array("\n", "\t"), " ",$row['ebay_htmlcss']));
}
return "";
}
function getTemplate($vid)
{
$code = "";
extract($this->getDealerSettings($vid));
if (!empty($youtubeurl))
$code .= "$youtubeurl";
Seems like you just need to add that field to your select statement:
$query = "SELECT banner, ebay_htmlcss, youtubeurl FROM ebay_dealersettings INNER JOIN ID_vehicles ON ebay_dealersettings.did=ID_vehicles.did WHERE vid='".$vid."'";
You need to add youtubeurl to the SELECT statement as well as ensuring it's in your return array, then it should work.
I wasn't returning the value in the array return array("banner" => trim($row['banner']),"youtubeurl" => trim($row['youtubeurl']),
Not necessarily an answer, supplements my comment to the question, I couldn't find a $youtubeurl mentioned before the empty check. If the db does not return anything or the query fails, the needed error handling is also not present. I have added simple error handling to the script. the return array contains ($return_array[0]) $errflag, which can be read to see if there was an error, $errmsg is an array containing the error msg, the third element contains your return array.
function getDealerSettings($vid)
{
$errflag=false;
$errmsg=array();
$return=array();
include('db.php');
$query = "SELECT banner, ebay_htmlcss FROM ebay_dealersettings INNER JOIN ID_vehicles ON ebay_dealersettings.did=ID_vehicles.did WHERE vid='".$vid."'";
$result = #mysql_query($query);
if (!$result){
$errflag=true;
$errmsg[]="Error with db connection". mysql_error();
}else{
$row = mysql_fetch_assoc($result);
$return = array("banner" => trim($row['banner']), "css" => str_replace(array("\n", "\t"), " ",$row['ebay_htmlcss']));
}
$return_array=array($errflag, $errmsg, $return);
return $return_array;
}

Categories