I want to retrieve xml data from three table stored in MySQL. I used the below code it works fine but first it retrieve one record from first table than iterate to second table and print the whole table and then iterate to third table and print the whole table but I want to print first table along with relevant records in second table (not whole table) then from third table and so on. My code is:
$table_first = 'recipe';
$query = "SELECT * FROM $table_first";
$resouter = mysql_query($query, $conn);
$table_second='instructions';
$query="SELECT instructions.instruction_id,instructions.instruction_text FROM $table_second";
$resinner=mysql_query($query, $conn);
$table_third='ingredients';
$query="SELECT ingredients.ingredient_id,ingredients.ingredient_name,ingredients.ammount FROM $table_third";
$resthird=mysql_query($query, $conn);
$doc = new DomDocument('1.0');
$root = $doc->createElement('recipes');
$root = $doc->appendChild($root);
while($row = mysql_fetch_assoc($resouter)){
$outer = $doc->createElement($table_first);
$outer = $root->appendChild($outer);
foreach ($row as $fieldname => $fieldvalue) {
$child = $doc->createElement($fieldname);
$child = $outer->appendChild($child);
$value = $doc->createTextNode($fieldvalue);
$value = $child->appendChild($value);
}// foreach
//while
$inner = $doc->createElement($table_second);
$inner = $outer->appendChild($inner);
while($row = mysql_fetch_assoc($resinner)){
// add node for each record
$inner1=$doc->createElement('instruction');
$inner1=$inner->appendChild($inner1);
// add a child node for each field
foreach ($row as $fieldname => $fieldvalue) {
$child = $doc->createElement($fieldname);
$child = $inner1->appendChild($child);
$value = $doc->createTextNode($fieldvalue);
$value = $child->appendChild($value);
} // foreach
}// while
$inner=$doc->createElement($table_third);
$inner=$outer->appendChild($inner);
while($row=mysql_fetch_assoc($resthird)){
$inner2=$doc->createElement('ingredient');
$inner2=$inner->appendChild($inner2);
foreach($row as $fieldname=> $fieldvalue)
{
$child=$doc->createElement($fieldname);
$child=$inner2->appendChild($child);
$value=$doc->createTextNode($fieldvalue);
$value=$child->appendChild($value);
}
}
}
mysql_close($conn);
$xml_string = $doc->saveXML();
echo $xml_string;
There is a much better way to accomplish what you're doing. It looks as though you pulling data from 3 different tables, using three different SQL queries, and three calls to the database.
The best way to accomplish this would be to build your table on the SQL side, using a single query. The queries are a little more complicated (you'll need JOIN) however the result will be much easier to work with in your program. You'll also probably avoid having to create your document on the fly using DOM. You could simple build your recipe using SQL, pull the whole result back and simply iterate through the table with the result.
Related
I am trying to create a loop that displays each row in a table. I think I need to make an array out of the PK, but I can't figure out how to do that. Here is my code so far:
$conn = dbConnect('read');
$getData = 'SELECT * FROM table';
$allData = $conn->query($getdata);
if (!$allData) {
$error = $conn->error;
} else {
$data = $allData->fetch_assoc();
$rowId = array($data['PK']);
} while ($rowId <= count($rowId)) {
// code to be run for each row
$rowId++;
}
EDIT: Sorry my question is confusing, I'm new to PHP.
Your question is a bit confusing but I think this is what you are trying to do:
$sql = 'SELECT * FROM table';
$query = $conn->query($sql);
while ($row = $query->fetch_assoc()) {
$data[$row['PK']] = $row;
}
That would iterate over each row, creating an array and using the row's value for column PK as an associative array key.
fetch_assoc() (I assume mysqli here now) doesn't fetch all data from a result, but one row after each other. So you don't need to make an array of $row['PK'], but need to loop over the results.
$conn = dbConnect('read');
$getData = 'SELECT * FROM `table`'; // you would need backticks here, if the table really is called "table" (what you shouldn't do...)
$result = $conn->query($getData); // it's not 'allData', it is a result_set. And be carefull about Case! $getData!=$getdata
if (!$result) {
$error = $conn->error;
} else {
$cnt=0;
while($row = $result->fetch_assoc()) {
// code to be run for each row
// you can display $row['PK'] now:
echo $row['PK'];
// or add that value to something else, whatever you need
$cnt = $cnt+$row['PK'];
// or to have a new array with the values of one table-column:
$columnRows[] = $row['PK'];
}
// now you can use the created array
foreach($columnRows as $PK) {
echo $PK;
}
}
I have a project here that has a LOT of this kind of code below.
It is everything in mysql and I want to change do mysqli or PDO.
The problem is that the code make the fields of the table be variables, inside the loop. So, If I need to change to something different, I will have to re-write thousand of lines of code. Because inside the loops below I will change every call of the var. Example: $row["product_name"] instead of $product_name
This is the code:
$query = "SELECT product_name, product_price from products";
$result = mysql_query($query_sql);
while($row = mysql_fetch_array($result)) {
$j = mysql_num_fields($query);
for($i=0;$i<$j;$i++) {
$k = mysql_field_name($query,$i);
$$k = $row[$k];
}
//Here, inside the loop, I use $product_name instead of $row["product_name"]
}
It there a way to change the code to do the same with mysqli or PDO? I want to keep using $field_name instead of $row["field_name"].
mysqli object method shown. I don't recommend doing it this way, but it can be done. I would highly suggest you learn how to deal with either a result object or array directly. Dynamically setting variables like this will introduce a lot of unnecessary overhead.
$result = $mysqli->query($query_sql);
while($row = $mysqli->fetch_assoc($result)) {
extract($row);
//Here, inside the loop, I use $product_name instead of $row["product_name"]
}
Here is what you are looking for: http://www.doctrine-project.org/
I specifically do not like this specific project, because it tends to be slow with larger amounts of data, but provides what you need:
You specify domain classes (understand map database lines to php objects) and you only have to specify the exact name of the table column, if it does not match up with the class variable name.
So you set every column once for every object type and you use that definition throughout you code, you are making a request for the object, that has a mapping to the database.
so it goes like: $entitiy_manager->getReference('myobject', $objectid = 1 );
Creating a new object is just adding a new instance of the class.
If I understood you properly this should be you are looking for.
Thank you for every answer and opinion, but I just found the solution for my question.
I will leave here, for future reference.
This code is in mysql:
$result = mysql_query($query);
while($row = mysql_fetch_array($result))
{
$j = mysql_num_fields($query);
for($i=0;$i<$j;$i++) {
$k = mysql_field_name($query,$i);
$$k = $row[$k];
}
}
And this would be the same in mysqli:
$result = mysqli_query($link, $query);
while($row = $query->fetch_assoc())
{
$j = mysqli_num_fields($query);
for($i=0;$i<$j;$i++) {
$k = mysqli_fetch_field_direct($query, $i)->name;
$$k = $row[$k];
}
}
I need to print a wine list from a database.
I need to print at first a categorie and after all the items that are inside. Thats the order. And i have multiple categorie. So at the end the result will be categorie1, many items, categorie2 many items...
This is the code that i write from now: I think that my problem is to print items according to the id of the alcool_categorie !!
$q_vine = "SELECT * FROM alcool_categorie ";
$r_vine = mysql_query($q_vine,$connection);
$n_vine = mysql_num_rows($r_vine);
$q_bouteille = "SELECT * FROM alcool_item where ALCNID = '$alid'";
$r_bouteille = mysql_query($q_bouteille,$connection);
$n_bouteille = mysql_num_rows($r_bouteille);
for($i = 0; $i < $n_vine; $i++){
echo mysql_result($r_vine,$i,'named').'<br/><br/>';
for($z = 0; $k < $n_bouteille; $k++){
echo mysql_result($r_bouteille,$k,'name').'<br/>';
}
}
I think it's best to use a "JOIN" in your query and then order the rows in the way you want them to be ordered, then you'll only need one loop. While running the loop you compare the category name with the previous category name and if it changes display the category name.
Example
$sql = "SELECT categoryName, bottleName FROM category INNER JOIN bottle ON category.categoryId = bottle.categoryId ORDER BY category.categoryId";
$result = mysql_query($sql,$connection);
$categoryName = ''; //just to make sure the first time the Category is named
while ($row = mysql_fetch_assoc($result)) {
if($categoryName != row['categoryName']){
$categoryName = row['categoryName'];
echo '<h1>'.$categoryName.'</h1>';
}
echo row['bottleName'].'<br/>';
}
Try this after correctly giving the category id field name in the query and inside the first while loop.
$q_vine = "SELECT id, named FROM alcool_categorie ";
$r_vine = mysql_query($q_vine,$connection);
$n_vine = mysql_num_rows($r_vine);
while ($row = mysql_fetch_assoc($r_vine)) {
$categories[$row['id']] = $row;
}
$q_bouteille = "SELECT name, ALCNID FROM alcool_item ";
$r_bouteille = mysql_query($q_bouteille,$connection);
$n_bouteille = mysql_num_rows($r_bouteille);
while ($row = mysql_fetch_assoc($r_bouteille)) {
$items[$row['ALCNID']] = $row;
}
foreach ($categories as $category_id=>$category) {
echo "<ul><li>{$category['named']}<ul>";
foreach ($items[$category_id] as $item) {
echo "<li>{$item['name']}</li>";
}
echo "</ul></li></ul>";
}
You will want to look into PHP's foreach construct. Foreach loops through an entire array of results, for each element inside the array, it extracts its value and optionally also its key. This will not require the use of mysql_num_rows.
Instead of calling mysql_result, you could use mysql_fetch_assoc to get a row's value from your mysql_query. The row's To get all values, you can incorporate this into a loop even. If you do the latter, you can create your own array of key/value pairs and use this inside a foreach construct.
Also note that the use of mysql is outdated, you will want to use mysqli now, which is very similar to mysql.
i want to make a website something like popurls.com, but I will use static data stored in MySQL database. Btw I use php/mysql.
In each list i want to show around 10 links (just like on popurls). In that case, if I would have 20 lists, i would need to make 20 'for' loops (for each particular list).
My question is; is there some better way to print that 20 lists instead of using 20 'for' loops in php.
a for loop or a foreach loop will work fine, but it will be a lot less coding if you just create a single for loop and push content into an array of arrays or an array of strings... you can then do whatever you'd like with the actual content (assuming we're grouping by a column category. I'll use an example that uses an array of strings (and the query that I reference is explained here: http://explainextended.com/2009/03/06/advanced-row-sampling/)
$query = mysql_query([QUERY THAT GETS ALL ITEMS, BUT LIMITS BY EACH CATEGORY]) or die(mysql_error());
$all_items = array();
while($row=mysql_fetch_array($query)){
if (!isset($all_items[$row['category']])){ //if it isn't created yet, make it an empty string
$all_items[$row['category']] = "";
}
$all_items[$row['category']] .= "<li><a href='".$row['url']."'>".$row['title]."</a></li>"; //concatinate the new item to this list
}
Now we have an array where the block of HTML for each section is stored in an array keyed by the name of the category. To output each block, just:
echo $all_items['category name'];
PHP's foreach http://php.net/manual/en/control-structures.foreach.php
Depends a lot on your data input but I could imagine something like this:
<?php
$lists = arrray('list1', 'list2', 'list3');
foreach ($lists as $current) {
$data = fetch_data_from_mysql($current);
foreach ($data as $link) {
echo "Link";
}
}
function fetch_data_from_mysql($current)
{
$list_data = array();
// do whatever is required to fetch the list data for item $current from MySQL
// and store the data in $list_data
return $list_data;
}
You just need two foreach loops. Assuming that you take the data from a mysql table (like you wrote), this could be like this:
$list_query = mysql_query("SELECT * FROM lists";)
while( $list = mysql_fetch_array($list_query) )
{
echo "<h1>{$list['title']}</h1>";
$query = mysql_query("SELECT * FROM entries WHERE list_id = {$list['id']}");
while( $entry = mysql_fetch_array($query) )
{
echo "- {$entry['name']}<br />";
}
}
You can get all the information from the database and parse it into an array, something like
array[<news type1>] = array( link1, link2, link3, etc);
array[<news type2>] = array( link1, link2, link3, etc);
and so on
and on the layout you can use
foreach ($newsCategory AS $categoryLinks) {
foreach ($categoryLinks AS $newsLink) {
<show the link and / or extra data>
}
}
Just store your links in two-dimensional array. That way you'll have to make 1 outer loop (iterating over lists) and 1 inner loop iterating over links in a particular list.
$links = array(
'science' => array('link1', 'link2', ...),
'sports' => array('link1', 'link2'),
// ... and so on
);
foreach ($links as $category => $urls) {
echo "Links in category: $category\n";
foreach ($urls as $url) {
echo $url . "\n";
}
}
Say I have a table containing articles (article_id, article_name) and another table containing the names of people (person_id, person_name) that ordered the articles. Plus an intermediary table, say articles-people (article_id, person_id).
Is there an elegant way I could do a single SELECT to get all the articles and the associated purchasers such that the articles would each listed in headers and the people are listed under the respective articles they've bought?
Also, is there a SELECT that would fetch the needed information but avoid a result like this (which looks like a badly structured DB):
article_id:1,article_name:penlight,purchaser_id:1, purchaser_name:fred
article_id:1,article_name:penlight,purchaser_id:2, purchaser_name:albert
article_id:1,article_name:penlight,purchaser_id:3, purchaser_name:sonia
...
This should print out rows with values.
$res = mssql_query('SELECT *
FROM articles a
join articles-people ap on a.article_id=ap.articleid
join people p on ap.person_id=p.personid');
$results = array();
$finalResuls = array();
while($row = mssql_fetch_assoc($res))
{
$results[] = $row;
}
foreach($results as $result)
{
/* This makes an array with key:value pairs as string. */
foreach($result as $k => $v)
{
$finalResults[] = $k . ': ' . $v;
}
$string = '';
/* Will concatenate data for each result row into a single string */
foreach($result as $k => $v)
{
$string .= $k . ': ' . $v;
}
$finalResults[] = $string;
}
So that you can have both solutions in the same post, here is the solution you were talking about with JNK.
$res = mssql_query('SELECT * from article');
$results = array();
while($row = mssql_fetch_assoc($res))
{
$id = $row['article_id'];
$res2 = mssql_query("SELECT * from people p join articles-people ap on p.person_id=ap.person_id where ap.article_id='$id'");
while($row2 = mssql_fetch_assoc($res2))
{
foreach($row2 as $k => $v)
{
$results[$id][] = $k . ': ' . $v;
}
}
}
Aesthetic or display requirements like that should be handled in your application layer, not at the database layer.
Getting a DB to return unassociated rows is possible but not recommended. What you are basically asking for is to return the data without the relational information, which can cause issues.
It's a much better idea to return the data that you need, then filter the display accordingly. SQL is not optimized for work like this, and it will be much slower and much more cumbersome to format the display at the database level than at the app level.