Array to string conversion error - php

I have a query that's pulling a list of IDs. Those IDs are in an array and I need to search another table with those IDs. I tried using implode to make those IDs a string that I could use in a where clause but I keep getting this error.
My current code is:
$query = $this->db->query('
SELECT *
FROM system_scoperights
WHERE user = '. $this->session->userdata('username') .'
');
foreach ($query->result() as $row) {
$scope = $row->site;
$data[] = $scope;
}
$dataScope[] = $data;
$idList = implode(',', $dataScope); <---- Error Line
$where = 'WHERE scope_scopes.sc_ID IN '. $idList .'';
I've tried different things I found on forums like:
$idList = implode(',', array_values($dataScope));
and
$idList = implode(',', join($dataScope));
but none of those work. (I've never even heard of the join function)
Thanks in advance for the help.

$dataScope[] = $data;
but
$data[] = $scope;
therefore $dataScope has an array inside it's array. implode only work on one level, so that why you're getting this error.
You should note that this is actually possible in SQL:
SELECT * FROM some_table WHERE id IN (SELECT site FROM another_table WHERE ... )
which would eliminate the entire need for this code.
That is:
$where = 'WHERE scope_scopes.sc_ID IN (SELECT site
FROM system_scoperights
WHERE user = '. $this->session->userdata('username') . ')';

I partially agree with Jay's answer...just remove the line:
$dataScope[] = $data
and use the $data variable directly since it's already an array:
$idList = implode(',', $data);
However you also should use ( and ) in your where clause:
$where = 'WHERE scope_scopes.sc_ID IN (' . $idList . ')';
Using sub-queries in your where clauses, although they do have their place at times, can cost a lot of overhead, especially using 'SELECT *'. Never ask for more than you need from your db tables :)

Related

using implode for array inside mysql where in clause

im trying to use array for mysql where in clause
$result= $myDB->query("SELECT sum(total) as total FROM ".$myDB->prefix("mydata")." WHERE categoryname IN ('".$categoryname."') AND year='$year' AND stat_id='$stat_id'");
current ouput for the categoryname is
('Cat1,Cat2,Cat3')
desired output
('Cat1','Cat2','Cat3')
i tried it like so far but its not working
$categoryname_new = implode(',',$categoryname);
$result= $myDB->query("SELECT sum(total) as total FROM ".$myDB->prefix("mydata")." WHERE categoryname IN ('".$categoryname_new."') AND year='$year' AND stat_id='$stat_id'");
the naive solution will be:
$array = ['Cat1', 'Cat2', 'Cat3'];
echo "'" . implode("','", $array) . "'";
but it could introduce sql injection, so you need properly escape data in array first
sample one-line with escaping:
echo "'" . implode("','", array_map('mysql_escape_string', $array)) . "'";
note: mysql_* functions are deprecated, you need to use mysqli_* which require connection link
I did something similar a while ago using array_map, hope it helps:
$args = array_map(function($a) {
return sprintf("'%s'", $a);
}, $args);
$args = join(",", $args);
The above code will iterate over the array and modifies every single element to surround it with ''. Finally, I join the array with ,.

Implode ids within a while loop and add commas between

I'm trying to display some sub-content so I need to get the child id's of their parent.
This is how I wanted to do it:
$ids = "SELECT * FROM `web_categories` WHERE parent_id = 14 AND published = 1";
$idscon = $conn->query($ids);
while ($ids = $idscon->fetch_array()){
$idss .= $ids['id'];
}
$project1 = "SELECT * FROM `web_content` WHERE catid in ('$idss') AND state = 1";
$projectcon1 = $conn->query($project1);
$projectcr1 = array();
while ($projectcr1[] = $projectcon1->fetch_array());
I tried imploding $idss like this:
$implode = implode(',', $idss);
But this gives me Invalid arguments passed. What am I doing wrong?
You are doing wrong in the first while loop.
Here it is, $idss .= $ids['id'];, You are doing wrong this. You are storing value in a variable as string, but when you try to implode this... It throws an error!!! Cause implode() use to make array into string. So follow the below steps.
Change $idss .= $ids['id']; to $idss[] = $ids['id']; and instead of implode() use the join().
Create an array names $idss, and push or insert the ids into that array. Then implode/join that IDs.
$idss = array();
while ($ids = $idscon->fetch_array()){
$idss[] = $ids['id'];
}
$implode = implode(',', $idss);
Now you can use this $implode variable in the next query.
You just need to store all IDs in an array, something like $yourIDs[] = $ids['id']; inside your first while loop.
With $idss .= $ids['id']; you can't use implode() because result of this action should be something like "1234" without any single comma.
You just need to use like that:
<?php
$yourIDs = array();
while ($ids = $idscon->fetch_array()){
$yourIDs[] = $ids['id']; // this will save all IDs into $yourIDs array.
}
$idss = implode(',',$yourIDs); // result of this should be 1,2,3,4 etc.
?>
I think you could most likely do that in one query
SELECT * FROM `web_content` WHERE `catid` in (
SELECT `id` FROM `web_categories` WHERE `parent_id` = 14 AND `published` = 1
) AND `state` = 1
The original code was, in effect, doing exactly this but in two stages - sub-queries can be slow sometimes but it does depend on the size of the db and the number of expected results. It is true that joins can be and generally are more efficient than dependant subqueries so perhaps that is another option to explore. As mysql executes the query plan from the outside to the inside rather than the intuitive inside to outside subqueries can cause the server to crawl - it really depends on the complexity of the subquery and the amount of data that has to be processed.

Passing a Non-Value in a mySQL WHERE clause

The following is the query that I'm trying to get to work.
$array = array();
SELECT * FROM ENTRIES
WHERE
entry_id = '12'
OR
entry_id_extra IN ('$array')
This is of course simplified. The problem is that it works great if the array has items and it returns everything fine. But if the array has no item it fails to work.
What is the correct way to construct this statement that doesn't break if there are no items in the array? I tried IN ('NULL','$array') but that didnt work.
Any help is appreciated.
You can make the OR portion of the where clause go through a conditional check:
$sql = "SELECT * FROM entries WHERE entry_id = 12"
if (count($array) > 0) {
$sql .= ' OR entry_id_extra IN ($array)';
}
$array = array(...);
$array = array_map('mysql_escape_string', $array); // make sure it's safe
$query = "SELECT *
FROM entries
WHERE entry_id = '12'"
. (count($array) > 0
? " OR entry_id_extra IN ('" . implode("','", $array) . "')"
: "");
// echo the query to see what it looks like (optional)
echo "<pre>{$query}</pre>";
You can use implode, but also make sure you escape the values so quotes don't set the query off.

PHP array_sum function in codeigniter

The following code is a simple select statement that should use the array_sum function to return a value. The result should be getting stored in an array and then getting added up in the SUM function:
$this->db->select('period')
->from('calcdata');
$query = $this->db->get()->result_array();
$query = array_sum($query);
echo "SUM " . $query . "\n" ;
return $query;
the result of this is "SUM 0" but it should be 147 after adding all values up in the period column.
The following code works so i don't understand why the array would be any different from this:
$a = array(2, 4, 6, 8);
echo "sum(a) = " . array_sum($a) . "\n";
I am using codeigniter to create the arrays, does anyone know what is wrong here?
Thanks
Try calling the content of the field instead, not of the whole result array:
$this->db->select('period')->from('calcdata');
$query = $this->db->get();
$period_array = array();
foreach ($query->result_array() as $row)
{
$period_array[] = intval($row['period']); //can it be float also?
}
$total = array_sum($period_array);
UPDATE:
#uzsolt is right, I almost forgot there's a dedicated function in the Active Record class, select_sum(); you might want to try that out also, something like
$this->db->select_sum('period')->get('calcdata');
Quoting from the docs:
$this->db->select_sum();
Writes a "SELECT SUM(field)" portion for your query. As with
select_max(), You can optionally include a second parameter to rename
the resulting field.
$this->db->select_sum('age'); $query = $this->db->get('members');
//> Produces: SELECT SUM(age) as age FROM members

Build SQL Select a better way ? (Oracle)

i have the following code part in one of my classes:
$l = new Location();
$result = $l->getLocIdsbyCity($city); // returns csv
$ids = explode(',', $result);
$where = 'LOC_ID = ' . $ids[0];
unset($ids[0]);
foreach ($ids as $id) {
$where .= ' OR LOC_ID = ' . $id;
}
$select->where($where);
Is there an more "elegant" way to build the select stmt? I need all records with one of the provided ids..
Assuming your csv is injection safe (contains trusted values and no user-provided input):
$l = new Location();
$result = $l->getLocIdsbyCity($city); // returns csv
$where = "LOC_ID IN ($result)";
$select->where($where);
If it's not, you should explode it, mysql_real_escape_string each value and implode back.
You can use the in operator to form a condition like:
where LOC_ID in (1,2,3,4,5)
If you are sure that $result can't contain anything harmful, you should be able to use it directly without having to split it and loop.

Categories