Implode ids within a while loop and add commas between - php

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.

Related

Why PHP Mysql query inside a foreach loop always returns the first result from database?

I'm trying to run a MYSQL query inside a foreach loop.
here's the scenario:
I have a comma separated string with some names in it.
I use explode() and foreach() to get the separate values/names from this comma separated string.
Then I need to search mysql database for each of these values/names that I get from this string and if that value exists in the database, I then get its ID and create a new recrord in another table in the database.
However, when I run my code, I only get the ID of the first instance from the comma separated string.
my mysql database looks like this:
id category_name
3 Hotel
4 Restaurants
This is my code:
//My comma separated string///
$biz_cat = 'Hotel, Restaurants';
///i do the explode and foreach here///
$arrs = explode(',', $biz_cat);
foreach($arrs as $arr){
$sql99 = "SELECT * FROM categories WHERE category_name='$arr'";
$query99 = mysqli_query($db_conx, $sql99);
while($row99 = mysqli_fetch_array($query99, MYSQLI_ASSOC)){
$catIDS = $row99['id'];
}
//this is where i need to insert my new data in different tabel.
echo $catIDS.'<br>;
}
so when the i run my code, I get the ID of the Hotel twice like so:
3
3
I'm expecting it to be like below based on what I have in MYSQL:
3
4
Could someone please advice on this issue?
First of all such things should be done using prepared statements. Not only it is easier and faster, but also more secure. Remember to always use prepared statements.
//My comma separated string///
$biz_cat = 'Hotel, Restaurants';
$stmt = $db_conx->prepare('SELECT * FROM categories WHERE category_name=?');
$stmt->bind_param('s', $cat);
foreach(explode(',', $biz_cat) as $cat){
$cat = trim($cat); // remove extra spaces at the beginning/end
$stmt->execute();
// we fetch a single row, but if you expect multiple rows for each category name, then you should loop on the $stmt->get_result()
$row99 = $stmt->get_result()->fetch_assoc();
// echo it in the loop or save it in the array for later use
echo $row99['id'];
}
In the example here I prepare a statement and bind a variable $cat. I then explode the string into an array on which I loop straight away. In each iteration I execute my statement, which in turn produces a result. Since you seem to be interested only in the first row returned, we do not need to loop on the result, we can ask for the array immediately. If you would like to loop just replace
$row99 = $stmt->get_result()->fetch_assoc();
with
foreach($stmt->get_result() as $row99) {
echo $row99['id'];
}
Once you get the id in the array, you can either print it out or save it into an array for later use.
As of now, you are re-assigning a new value to scalar variable $catIDS for each record returned by the query, then you echo it one you are done looping. You would need to put the echo/insert logic inside the loop (or maybe store the values in array).
Another thing to note is that you are splitting with , (a single comma), but you have a space between the two words. As a result, the second value (Restaurant) starts with a space, which will cause the query to return an empty resultset. You probably want to split with , (a comma followed by a space).
$biz_cat = 'Hotel, Restaurants';
$arrs = explode(', ', $biz_cat);
foreach($arrs as $arr){
$sql99 = "SELECT * FROM categories WHERE category_name='$arr'";
$query99 = mysqli_query($db_conx, $sql99);
while($row99 = mysqli_fetch_array($query99, MYSQLI_ASSOC)){
$catIDS = $row99['id'];
//this is where i need to insert my new data in different tabel.
echo $catIDS.'<br>';
}
}
The code below can do what you need.
Update INSERT YOUR NEW DATA HERE
$biz_cat = 'Hotel, Restaurants';
$arrs = explode(',', $biz_cat);
foreach ($arrs as $arr) {
$query99 = mysqli_query($db_conx, "SELECT * FROM categories WHERE category_name='$arr'");
while ($row99 = mysqli_fetch_array($query99, MYSQLI_ASSOC)) {
$catIDS = $row99['id'];
// INSERT YOUR NEW DATA HERE
echo $catIDS . '<br/>';
}
}

perform two different fetch on the same query result

I have this query:
$all = $dbh->query("SELECT DISTINCT movimenti.nome, SUM(movimenti_carta.importo)
FROM movimenti_carta JOIN movimenti ON movimenti_carta.movimento=movimenti.id
WHERE month(data)='$mese' AND year(data)='$anno' GROUP BY movimenti.nome");
It retrieves two columns from my db. What I want to do is to put each column in a separate array.
If I do:
$labels=$all->fetchAll(PDO::FETCH_COLUMN,0);
I get the values for the first column with the format I am looking for.
I tried to do:
$values=$all->fetchAll(PDO::FETCH_COLUMN,1);
after the first fetch but $all is unset by the first fetch and the result is that $values is an empty array (I was pretty sure of this but did give it a try).
I can build the arrays in php after I fetch an array with both columns but I was wondering how to get my goal using PDO api.
Of course it will never work this way, as fetchAll() returns data only once.
The only idea I could think of is PDO::FETCH_KEY_PAIR constant:
$data = $all->fetchAll(PDO::FETCH_KEY_PAIR);
$labels = array_keys($data);
$values = array_values($data);
It feels like you are overcomplicating this. It's easily done in PHP, and if you just use PDOStatement::fetch, you don't need to worry about array manipulation; it will also be more friendly to your memory usage if you have a lot of data.
$labels = [];
$values = [];
while ($row = $all->fetch(PDO::FETCH_NUM)) {
$labels[] = $row[0];
$values[] = $row[1];
}
Maybe you could use array_column.
$all = $dbh->query("
SELECT DISTINCT movimenti.nome, SUM(movimenti_carta.importo) AS importo
FROM movimenti_carta
JOIN movimenti ON movimenti_carta.movimento=movimenti.id
WHERE month(data)='$mese'
AND year(data)='$anno'
GROUP BY movimenti.nome
");
// set of results indexed by column name
$results = $all->fetchAll(PDO::FETCH_ASSOC);
// set of values from the column 'nome'
$nomes = array_column($results, 'nome');
// set of values from the column 'importo'
$importos = array_column($results, 'importo');

Dynamic multi-diemnsional array sorting

Hello everyone I have a simple question. How to choose by string which column of multidimensional array to sort. Here is some informations you should know.
I have table with eshops data and a function which shows me orders for particular eshop like this
$sql = mysql_query("SELECT * FROM eshops WHERE active = 1");
while($data = mysql_fetch_assoc($sql)){
$res = showOrders($data['host'],$data['user'],$data['pass'],$data['db'],$data['prefix']);
echo $res;
}
This was my first try how to show all orders i made filters by passing sql condition to my function. But then i wanted to sort the result, and Here comes the problem i can sort every eshop but i want to sort all eshops at once it means that if i sort them by order date the eshops mix up but that is not possible right now so i made this.
Example:
$GLOBALS['container'] = array();
and in a function i put datas to array like this
$GLOBALS['container'][] = array($data['eshop_id'],$data2['order_id']
,$data2['order_status'],$data2['order_number'],$data2['d_f_name'],$data2['d_l_name']
,$data2['order_total'],$data2['payment_method_id'],$data2['shipping_method_id']
,$data2['Exportovano'],$data2['C_Baliku'],date("d.m.Y",strtotime($data2['order_date'])));
Then i sort i like that
foreach($GLOBALS['container'] as $key => $datas){
$eshop_id[$key] = $datas[0];
$order_id[$key] = $datas[1];
$order_st[$key] = $datas[2];
$order_nm[$key] = $datas[3];
$d_f_name[$key] = $datas[4];
$d_l_name[$key] = $datas[5];
$order_tl[$key] = $datas[6];
$pay_m_id[$key] = $datas[7];
$shp_m_id[$key] = $datas[8];
$exported[$key] = $datas[9];
$parc_num[$key] = $datas[10];
$ord_date[$key] = $datas[11];
}
array_multisort($ord_date, SORT_DESC,$d_f_name, SORT_ASC, $GLOBALS['container']);
Here we go now i can sort as i wish then by foreach container select order by order also adding a condition but how to choose what i want to sort? P.e. i pass data by get
?sort=ord_date&orn=asc
I want sort ord_date variable ascending how? PLease help me thanks.
I am also open for other solutions.
It will be easier to write in SQL query, just after WHERE statement use a ORDERED BY (column) statement.
EDIT:
Using ORDER BY statement

Double Dollar Sign - Assign Array key=>value

I would like to create 3 different arrays which can change depending on which fields are pulled from some mysql tables.
This is the code I have:
// Gather db rows with query
$compQuery['subCats'] = mysql_query("SELECT id,name,category FROM subcategories ORDER BY id DESC");
$compQuery['cats'] = mysql_query("SELECT id,name FROM categories ORDER BY id DESC");
$compQuery['mans'] = mysql_query("SELECT id,name,link FROM manufacturers ORDER BY id DESC");
// Place rows into arrays
foreach($compQuery as $name=>$query){
$name = array();
while($data = mysql_fetch_array($compQuery[$name])){
foreach($data as $key=>$value){
$$name[$key] = $value;
}
}
}
What I would expect this to produce is 3 arrays: subCats, cats and mans each with the value pairs. Instead of finding the $$name variable and assigning [$key] = $value to the array it is taking a single letter out of the $$name variable and assigning the $value to this new variable.
For example, if $name = 'subCats', $key = '3', and value = 'machine tools'
It would create the variable $C using the 3rd letter in subCats:
$C = 'machine tools'
What it should do is create:
$subCats[3] = 'machine tools';
Now, obviously there are easier ways to create separate arrays for each query, and I have modified my code to a lazier/easier version. However, I am still curious as to how I would go about assigning a key value pair to a double dollar sign variable.
Any help would be greatly appreciated! I have the simple code working now, but would like to implement this new code to be more dynamic and allow for more queries as needed without hassle.
Thanks!
Josh
${$name}[$key]
But I do not like to create 'unknown' variable, as in variables whose name is not in the code... What if the name is 'key','db','_GET','compQuery' etc? All hell breaks loose...
In this line:
$name = array();
You're overwriting $name. You probably meant to write to $$name:
$$name = array();

php & mysql - loop through columns of a single row and passing values into array

I have a mysql table with columns id, f1, f2, f3, ..., f20 where id is productID and f1,...f20 are product features. Depending on each product, some might have all, none or only some columns filled.
Each column holds a delimited string like a#b#c#d where a,b,c,d are values in different languages (a=english, b=french etc)
I need to select a row by it's id, explode each column's value (f1,f2...) with '#' in order to get the language part I need and then pass the values to an array in order to use in my product spec page.
How do I loop through the fetched row (i'm using $row = my_fetch_array) and put the exploded value into a one dimension array like $specs=('green', 'M', '100', 'kids'...) etc?
PS:I know, is complicated but I cant come up with a better idea right now.
Try this:
$result = mysql_query("...");
while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
$arr = array();
foreach ($row as $k=>$v)
{
$features = explode("#", $v);
$value = $features[1]; // get the specific language feature
$arr[] = $value;
}
$specs = join(", " , $arr);
}
Not sure this is the best way togo but you could define an array with your langs, then access the result by lang
<?php
$langs=array('eng'=>0,'fr'=>1,'ger'=>2,'geek'=>3);
while ($row=mysql_fetch_assoc($result)) {
$specs=explode('#',$row['f1']);
$other=explode('#',$row['f2']);
...
}
//Get lang from cookie that you could set elsewhere
$lang=(isset($_COOKIE['lang']))?$_COOKIE['lang']:'eng';
echo $specs[$langs[$lang]];
?>
My solution for how I understand you question:
// Make a MySQL Connection
$sQuery = "SELECT f1,f2,... FROM table WHERE id = ...";
$oResult = mysql_query($sQuery) or die(mysql_error());
//Fetch assoc to use the column names.
$aRow = mysql_fetch_assoc($oResult);
//Prepare the product properties array
$aProductProperties = array("English"=>array(),"French"=>array(),"Dutch"=>array());
//Loop over all the columns in the row
foreach($aRow as $sColName=>$sColVal){
//Explde the column value
$aExplodedCol = explode("#",$sColVal);
//The code below could be nicer when turned into a looped that looped over every language,
//But that would make the code less readable
$aProductProperties['English'][$sColName] = $aExplodedCol[0];
$aProductProperties['French'][$sColName] = $aExplodedCol[1];
$aProductProperties['Dutch'][$sColName] = $aExplodedCol[2];
}
//Done, you should now have an array with all the product properties in every language

Categories