How to echo a PHP variable from MySQL results - php

To automate my PHP to generate JSON, I saved the name of variable in database
(e.g. > $test_value_1).
In my php file I have the value of this variable (e.g. > $test_value_1 = "TEST VALUE 1")
After this I do a query to echo this variable, but, instead of returning the value of variable (TEST VALUE 1), always return just the text save in database ("$teste_value_1")
To understand better, look my database, variable, query, response and what I need:
TABLE: attributes
id_attribute | attribue_string | attribute_value
1 | test_string_1 | $test_value_1
2 | test_string_2 | $test_value_2
VARIABLES:
$test_value_1 = "Test Value 1";
$test_value_2 = "Teste Value 2";
QUERY:
$query_array = mysqli_query($connect,"
SELECT GROUP_CONCAT(CONCAT('{id:', a.attribute_string, ',value_name:', a.attribute_value, '}') SEPARATOR ', ') AS concat
FROM rel_categories_attributes AS rca
INNER JOIN categories AS c ON c.id_category = rca.categories_id_category
INNER JOIN attributes AS a ON a.id_attribute = rca.attributes_id_attribute
WHERE id_category = '{$id_category}'
");
WHILE ($reg_cat = mysqli_fetch_array($query_array)){
echo $teste_query = $reg_cat["concat"] . ",";
RESPONSE: {id:test_string_1,value_name:$test_value_1}, {id:teste_string_2,value_name:$test_value_2}, (WRONG)
WHAT I NEED: {id:test_string_1,value_name:TEST VALUE 1}, {id:teste_string_2,value_name:TESTE VALUE 2},

While this seems like a horrible design, you can do it using variable variables. But you'll need to do the output formatting in PHP, not in MySQL.
$query_array = mysqli_query($connect,"
SELECT a.attribute_string, a.attribute_value
FROM rel_categories_attributes AS rca
INNER JOIN categories AS c ON c.id_category = rca.categories_id_category
INNER JOIN attributes AS a ON a.id_attribute = rca.attributes_id_attribute
WHERE id_category = '{$id_category}'
");
$result = array();
while ($row = mysqli_fetch_assoc($query_array) {
$result[] = array('id' => $row['attribute_string'], 'value_name' => ${$row['attribute_value']});
}
echo json_encode($result);
However, variable variables can almost always be improved by using an associative array. Instead of having variables like $test_value_1 and $test_value_2, create an array whose keys are "test_value_1" and "test_value_2", and then use $array[$row['attribute_value']].
But even better would be to put all the details in the database itself, rather than hard-coding them in the scripts. You can then join with that table to translate the attribute value to the appropriate string.

Related

Get the ancestral data from database dynamically

I would like to get the ancestral or child data when I pass the value in a function.
This is my data from MySQL table.
If I pass the value of Document2 in my function i want to get the ancestral data, for example, if I pass Document2 it will get the Book2 then the Book2 will get the Document1 and Document1 will get the Book1 and so on, then same with the Profile1 it will get the Document0 dynamically.
Here's my code.
$binded = array('Document2');
$sources = [];
foreach ($binded as $document) {
$check = $this->db->where('binded',$document)
->get('binded_document');
$results = $check->result();
foreach($results as $key => $result){
array_push($sources, $result->source);
$ancestral = $this->db->where('binded',$result->source)
->get('binded_document');
$ancestrals = $ancestral->result();
foreach($ancestrals as $k => $r){
array_push($sources, $r->source);
}
}
}
The problem with my code is it will not dynamically get ancestral data if the passed value in the function has more than 2 ancestral.
DBFIDDLE
I did choose to separate the recursive parts with a -.
WITH RECURSIVE cte AS (
SELECT
source as s,
CAST(Binded AS CHAR(1024)) as b,
1 as c
FROM table1 WHERE Binded='Document2'
UNION ALL
SELECT table1.source, CONCAT(cte.s,'-',cte.b), c+1
FROM cte
LEFT JOIN table1 ON table1.Binded = cte.s
WHERE c<10 AND NOT cte.s IS NULL
)
select b
from cte
where cte.s is null and NOT b is null
group by b
;
output:
b
Document0-Profile1-Document2
Book1-Document1-Book2-Document2

Issue sorting inside while loop

I have a strange issue happening. I've got a table where I want to order the number of times a product was sold. I'll post the query, but the issue is inside the while loop.
Query:
$cat = $db->query("SELECT *, COUNT(id_produto) as quantos FROM produtos p JOIN pedidos m ON p.id_prod = m.id_produto GROUP BY id_produto ORDER BY quantos +0 DESC");
$cat->execute();
Now the loop:
while($res_cat = $cat->fetch(PDO::FETCH_ASSOC)){
$quantidade_ok = $res_cat['quantos'] * $res_cat['qtde'];
$quanti = array($quantidade_ok);
rsort($quanti);
foreach($quanti as $ord){
echo $ord."<br>";
}
The output is:
40
50
4
1
3
2
10
But I want it to be:
50
40
10
4
3
2
1
I'll be happy for any help.
You're sorting within a loop (so your sorting already happened), and you're sorting an array with just 1 value $quanti, so your sort does nothing.
You have 2 ways to approach this properly: edit your query to actually sort how you wish, or sort the PHP array before looping it.
Option 1: Edit your query
Based on your code it seems clear that you wish to sort by the product of quantos times qtde. So you can simply edit your query as follows:
SELECT *, COUNT(id_produto) as quantos
FROM produtos p JOIN pedidos m ON p.id_prod = m.id_produto
GROUP BY id_produto
ORDER BY (quantos*qtde) DESC
Option 2: Sort via PHP
If you prefer to sort via PHP as you don't want to change your query, you can simply populate a temporary array, the product of quantos times qtde as key and then use krsort to sort the array.
In code:
$array = [];
while ($res_cat = $cat->fetch(PDO::FETCH_ASSOC)) {
$key = $res_cat['quantos'] * $res_cat['qtde'];
$array[$key] = $res_cat;
}
krsort($array);
foreach ($array as $ord => $res_cat) {
echo $ord."<br>";
}
You overwrite $quanti each time so it always has a single value.
Try this:
$quanti = [];
while($res_cat = $cat->fetch(PDO::FETCH_ASSOC)) {
$quantidade_ok = $res_cat['quantos'] * $res_cat['qtde'];
$quanti[] = $quantidade_ok;
}
rsort($quanti);
foreach($quanti as $ord){
echo $ord."<br>";
}

Select from 2 tables not working with php mysql

I have two different tables of the following structure:
grouprel
id | userId | pupID | groupId
pupils
id | userId | fname | lname
pupId in groulrel is equal to id in pupils.
I want to fetch pupils from a different group and then order them by fname, lname.
Now I have two queries like this:
$q = "SELECT * FROM grouprel WHERE userid = ". $userid ." AND groupId = ". $_GET['id'] ."";
$r = mysqli_query($mysqli, $q);
while ($rows = mysqli_fetch_object($r)) {
$query = "SELECT id, fname, lname FROM pupils WHERE userid = ". $userid ." AND id = ". $rows->pupId ." AND status = 0 ORDER BY fname, lname";
$result = mysqli_query($mysqli, $query);
while($row = mysqli_fetch_object($result)) {
echo stuff...
}
}
This works, but it doesn't order the names alphabetically like I want to.
How could I fix this?
This is iterating over the first query:
while ($rows = mysqli_fetch_object($r)) {
And this iterates over each instance of the second query:
while($row = mysqli_fetch_object($result)) {
So if the first query returns 1,2,3, and each iteration of the second query returns A,B, then your output would be:
1 A
1 B
2 A
2 B
3 A
3 B
The second query is ordering by the ORDER BY clause you gave it. But you are ordering the entire output by the first query.
Ultimately, why do you need these separate queries at all? Executing a database query in a loop is almost always the wrong idea. It looks like all you need is one query with a simple JOIN. Guessing on your logic, something like this:
SELECT
pupils.id, pupils.fname, pupils.lname
FROM
pupils
INNER JOIN grouprel ON pupils.id = grouprel.pupId
WHERE
pupils.userid = ?
AND grouprel.groupId = ?
AND pupils.status = 0
ORDER BY
fname, lname
It may take a little tweaking to match exactly what you're looking for, but you can achieve your goal with a single query instead of multiple separate queries. Then the results of that query will be ordered the way you told MySQL to order them, instead of the way you told PHP to order them.

MySQL SELECT WHERE id IN() get num_rows

I use this code to show category from database
$select_newscats = $mysqli->query("SELECT * FROM news_cats order by ord_show asc");
while ($rows_newscats = $select_newscats->fetch_array(MYSQL_ASSOC)){
$id_newscats = $rows_newscats ['id'];
$title_newscats = $rows_newscats ['title'];
$ord_show_newscats = $rows_newscats ['ord_show'];
$icon_newscats = $rows_newscats ['icon'];
$kind_newscats = $rows_newscats ['kind'];
$description_newscats = $rows_newscats ['description'];
//here is my data
}
i have in news table row for categoies it's name is cats and i insert data inside it like that 1,5,6,8
and i use this code to count news inside each cat
$select_newsnum = $mysqli->query("SELECT id FROM news where $id_newscats IN (cats)");
$rows_newsnum = $select_newsnum->fetch_array(MYSQL_ASSOC);
$num_newsnum = $select_newsnum->num_rows;
it gets only first value for example if i have this values 1,5,6,8 it gets only 1 the first value
I would do the counting in a single sql call, not with php logic and separate sql calls. For this I would join the 2 tables using left join and use a join condition instead of an in clause:
SELECT nc.id, nc.title, nc.ord_show, nc.icon, nc.king, nc.description, count(n.id) as newsnum
FROM news_cats nc
LEFT JOIN news n ON nc.id=n.cats
GROUP BY nc.id, nc.title, nc.ord_show, nc.icon, nc.king, nc.description
ORDER BY nc.ord_show asc
Obviously, make sure that the join condition is the right one. When you loop through the resultset, the number of news per category will be in the newsnum field.
$select_newsnum = $mysqli->query("SELECT id FROM news where $id_newscats IN (cats)");
$rows_newsnum = $select_newsnum->fetch_array(MYSQL_ASSOC);
$num_newsnum = $select_newsnum->num_rows;
Here $rows_newsnum will only return the first row in the database.
Fetch Array only returns one row at a time, and then moves the row pointer forward. For example the following code on the dataset you provided (1, 5, 6, 8).
$rows_newsnum = $select_newsnum->fetch_array(MYSQL_ASSOC);
echo $rows_newsnum["id"]; // Will print 1
$rows_newsnum = $select_newsnum->fetch_array(MYSQL_ASSOC);
echo $rows_newsnum["id"]; // Will print 5
What you need to do is move it into a while loop (like your first example) to get to access each row, like below:
while($row = $select_newsnum->fetch_array(MYSQL_ASSOC)) {
echo $rows_newsnum["id"] . ", ";
}
// Will produce:
// 1, 5, 6, 8,
If you just want to get a count
Your existing code should work fine. And you can omit the call to fetch_array.
$num_newsnum = $select_newsnum->num_rows;
echo $num_newsnum; // Will display 4
Read more about fetch_array on the PHP documentation:
http://php.net/manual/en/mysqli-result.fetch-array.php
Hope this helps.

displaying data from inner join

i need help displaying this in two different lists
$domains_sql = mysql_query("SELECT domains_id, domains_url, keywords_id, keywords_word, domains_comments_comment
FROM
(
SELECT domains_id,domains_url
FROM domains
ORDER BY RAND()
LIMIT 1
) as d
INNER JOIN domains_comments
ON domains_comments_domain = domains_id
INNER JOIN domains_keywords
ON domains_keywords_website = domains_id
INNER JOIN keywords
ON domains_keywords_keyword = keywords_id
ORDER BY keywords_word ASC") or die (mysql_error());
$num = mysql_num_rows($domains_sql);
$current_price = "";
for($i=0;$i<$num;$i++){
$domains_result = mysql_fetch_array($domains_sql);
$domains_id = $domains_result['domains_id'];
$domains_url = $domains_result['domains_url'];
$domains_name = preg_replace('#^https?://www.#', '', $domains_url);
$keywords_id = $domains_result['keywords_id'];
$keywords_word = $domains_result['keywords_word'];
$domains_comments = $domains_result['domains_comments_comment'];
if($domains_url != $current_price) {
echo $domains_name."<br /><br />";
$current_price = $domains_url;
}
echo $keywords_word."<br />";
echo $domains_comments."<br />";
}
prints out:
MS Office
domain 1
MS Office
domain 1 - part 1
MySQL
domain 1
MySQL
domain 1 - part 1
PHP
domain 1
PHP
domain 1 - part 1
Visual Basic
domain 1
Visual Basic
domain 1 - part
and i need it to be:
(info from keywords)
MS Office
MySQL
PHP
Visual Basic
(info from comments)
domain 1
domain 1 - part 1
I'm not sure if I see how your domain comments and keywords are related, and if you simply want two lists or if you want one comment-list per keyword.
Anyway, you could rewrite your query logic to make a primary query for the keywords, and then run simpler queries for the comments (either one for all, or one per keyword), but if your query time and dataset is such that you prefer doing it in a single query you can restructure the data in multiple-leve arrays.
Also, i presume you only want to list every item once.
$keywords = array();
$comments = array(); //if you want all comments in one list
for($i=0;$i<$num;$i++){
$domains_result = mysql_fetch_array($domains_sql);
//Stores complete row data, only keeps the last, if the same value is fetched from the db several times
$keywords [$domains_result['keywords_word']] = $domains_result;
$comments[$domains_result['domains_comments_comment']] = $domains_result;
}
//Now you have the two list, could be printed several ways, to only print the values
print implode("<br />\n",array_keys($keywords));
print "<br />";
print implode("<br />\n",array_keys($comments));
//Loop trough
foreach ($keywords as $keyword=>$data) {
print "$keyword<br>\n";
print $data['keywords_word']."<br>\n";
print_r($data);
}

Categories