Reusing a PDO Query block in another area best practices - php

I'm just transitioning over to PDO from mysql_
I have been pointed in the direction of some helpful tutorials, but there is one issue I haven't seen raised and I wanted to check I am doing it in the 'correct way'
I want to reuse the same values that I am dropping into an array in two different areas (both different PHP code blocks) within one page. Both are styled differently depending on media queries (hidden/not hidden etc.)
At the moment I am running a query like this:
<?php
$data = $pdo->query("SELECT * FROM sitelinks WHERE `show` = 'yes' ORDER BY `Order` ASC")->fetchAll();
foreach ($data as $links)
{
echo "\n<li class=\"linkitem\">{$links['Text']}</li>";
}
?>
So my understanding is that I should then be able to load and loop through the $links variable somewhere else on the page. I am doing that like this:
<?php
foreach ($data as $links)
{
echo "\n<li class=\"desktoplinkitem\">{$links['Text']}</li>";
}
?>
Is that correct? It's working, but seems a little crazy to use ($data as $links) again. Following on, really stupid question but why does the $data variable then have to be stored as $links. Could it not just be run as foreach ($links) to begin with?

Assuming you do not write some code later that changes/destroys the $data variable between these 2 usages there is no problem doing this. It in fact reduces the runtime to reuse data if you can rather than getting it again.
What you need to remember is that ->fetchAll() returns all the rows from your resultset into an array. Its your array from then on, which you can do whatever you like with once the ->fetchAll() is completed
Second question:
the foreach
foreach ($data as $links)
processes over an array $data and returns one occurance (row in your case) at a time. So you have to give it another variable name. That name can be anything.
If you use sensible names for things they normally look like this
foreach ($rows as $row)
foreach ($sitelinks as $sitelink)
Using the plural for the original array and the singular for the single occurance returned by each iteration over the array.
So I would amend your code like so:
<?php
$sitelinks = $pdo->query("SELECT *
FROM sitelinks
WHERE `show` = 'yes'
ORDER BY `Order` ASC")
->fetchAll();
foreach ($sitelinks as $sitelink) {
echo "\n<li class=\"linkitem\">{$links['Text']}</li>";
}
?>
And the second use of the array
<?php
foreach ($sitelinks as $sitelink) {
echo '\n<li class=\"desktoplinkitem\">{$sitelink['Text']}</li>";
}
?>

Related

How to get each value in a column of database in php

I don't have enough knowledge about this criteria:
I want to loop inside the for each loop to get all values in a particular column.
For example: I got the values from DB through get_result and store the result in $results.
After that use:
for each($results as $result)
❴
$output = $result->message
❵
Where message is a column in DB.
I want to loop over all the messages instead of storing last one by replacing.
Can you please give me suggestions on how to loop inside for each?
Try this:
$output[] = $result ->message;
Now $output will contain all messages on index 0, 1, 2 ...
You are facing the issue because:
$output=$result ->message;
the above line is present inside the loop, and each new iteration onerride the old value.
Well if you just looking for foreach inside foreach then you can try the following.
<?php
foreach($results as $result){
$output=$result->message;
foreach($output as $messages){
echo $messages;
}
}
?>
You don't need to put the message into another variable. You can do whatever you need to do inside the loop. For example, if you are displaying the messages, you can get it done inside the loop:
foreach ($results AS $result) {
echo $results->message . "<br>";
}

PHP - Looping through an object keys, one cycle per key

I have this object containing one row and many keys/variables with numbered names.
I need to pass each of them one at a time to another function. How do I loop through the keys instead of the rows?
The code would look like this:
foreach ($object['id'] as $row):
$i++;
$data['myInfo'][$i] = $this->get_data->getInfo('data1', 'id', $row->{'info'.$i.'_id'});`
but this obviously won't work since it's looping through the rows/instances of an object, and I have only one row in my $object['id'] object (with info1_id, info2_id, info3_id, info4_id... etc keys), so the loop stops after just one cycle. And I really don't feel like typing all of that extra code by hand, there's gotta be solution for this. :)
You can just iterate through your object like an array :
foreach ($object['id'] as $row) {
foreach ($row as $k => $v) {
$id = substr($k, 4, strpos($k, '_')-4);
$data['myInfo'][$id] = $this->get_data->getInfo('data1', 'id', $v);`
}
}
Thanks for the directions Alfwed, I didn't know you could use foreach loop for anything other than instances of an object or arrays (only started learning php a week or so ago), but now it looks pretty straight forward. that's how I did it:
foreach ($object['id'] as $row):
foreach ($row as $k=>$v):
$i++;
if ($k == print_r ('info'.$i.'_id',true)){
$data['myinfo'][$i] = $this->get_db->getRow('products', 'id','info'.$i.'_id');
<...>
in my case, I knew how many and where were those values, so I didn't have to worry about index values too much.

PHP: foreach loop inside PHP variable?

I'm trying to dynamically generate html select options using PHP based on whatever its stored in mysql database.
the column that stores the data called sizez.
the data in that column is stored like so:
small,large,xlarge,xxlarge
so basically the data is separated by a comma.
now in my php page I simply pull the data and display it on my page using a while loop for each product that is stored in the mysql database.
the issue that I am having is that I need to generate a select option dropdown list based on the sizez column for each item.
for that I am using the explode() function and it will generate the select option successfully too.
however, the issue is that it will only get the strings from the first sizez column and ignores the rest of the items But it will display the string from the first column for other items too and it repeats them!
this is my code:
while($row = mysqli_fetch_array($query, MYSQLI_ASSOC)){
$id = $row["id"];
$sizez = $row["sizez"];
$sizez = preg_replace('/\.$/', '', $sizez); //Remove dot at end if exists
$array = explode(',', $sizez); //split string into array seperated by ','
foreach($array as $value) //loop over values
{
//echo $value . PHP_EOL; //print value
$sizesOption .='<option>'.$value.'</option>';
}
$all_list .="<select>
'.$sizesOption.'
</select>";
so I thought to put the foreach($array as $value) inside the $all_list .= but that approach is wrong.
could someone please advise on this issue?
any help would be appreciated.
EDIT:
The expected result should be like this:
item one item two item three
small large small
large xxlarge xxlarge
However, with my code I get the result like this:
item one item two item three
small small small
large large large
small small
large large
small
large
so basically, it will get the sizes column from the first item and it will repeat it inside select options for other items exactly like the example above.
Since you are generating separate <select> for each iteration, you have to reset $sizeOptions. I suggest using arrays instead of just concatenating strings:
$allList = array();
while($row = mysqli_fetch_array($query, MYSQLI_ASSOC)){
$sizesOption = array();
$sizez = preg_replace('/\.$/', '', $row["sizez"]);
$array = explode(',', $sizez);
foreach ($array as $value) {
$sizesOption[] = "<option>{$value}</option>";
}
$all_list[] = '<select>'.implode("\r\n", $sizesOption).'</select>';
}
echo implode("\r\n", $allList);
From what you have posted it looks like you're regenerating $all_list in every iteration of your while loop.
So if you echo $all_list outside of the while loop it will only have the last iteration available - all the other ones having been overwritten during the process of the while loop.
Maybe I am wrong. but as simple as:
$all_list ="<select>".$sizesOption."</select>";
Close the opening braces for while loop before the '$all_list .="' statement.You are iterating the statement inside while loop.
`
while($row = mysqli_fetch_array($query, MYSQLI_ASSOC))
{
$id = $row["id"];
$sizez = $row["sizez"];
$sizez = preg_replace('/\.$/', '', $sizez); //Remove dot at end if exists
$array = explode(',', $sizez); //split string into array seperated by ','
foreach($array as $value) //loop over values
{
//echo $value . PHP_EOL; //print value
$sizesOption .='<option>'.$value.'</option>';
}
}
$all_list .="<select>
'.$sizesOption.'
</select>";
`
May be this will work
I figured it out. Thanks to Justinas's answer. I realized that I had to put my php variable inside the while loop.
so all I had to do was to put $sizesOption =array(); inside my while loop and everything works fine now.
P.S. i haven't made any other changes to my code above.

ideal method of building tables in PHP

As an intern I realized that I spend the bulk of my time building and manipulating tables from sql queries in PHP. My current method is to use two foreach loops:
foreach($query as $record){
foreach($record as $field => $value){
*Things that need to be done on each field-value pair*
}
*Things that need to be done on each row*
}
Is there a better way of doing this?
Also I tend to pack data together as a ~ separated list and store it in the server, is this a bad practice?
I'd rather put some code up for review but I don't want to risk exposing the internals of the company cod.
Foreach loops are the best way to iterate through your data. If you are looking to make your code a bit prettier, try using the ternary version
<?php foreach($query as $record) : ?>
<?php foreach($record as $field => $value) : ?>
*Things that need to be done on each field-value pair*
<?php endforeach; ?>
*Things that need to be done on each row*
<?php endforeach; ?>
Also, like mentioned in the comments above, you lose a lot of functionality when storing ~ seperated data in the db. If you must do this, you can try storing serialized objects instead of delimited strings. You can manipulate the objects in a number of ways such as json_encode() and json_decode()
$myArray = array();
$myArray['User1']['book'] = 'Pride and Prejudice';
$myArray['User1']['favorites'] = 'Water skiing';
$myArray['User2']['book'] = 'Mansfield Park';
$myArray['User2']['favorites'] = array('skateboarding', 'surfing', 'running');
$myArray['description'] = 'Things people like.';
echo '<pre>';
print_r(json_encode($myArray)); //This will convert your array to a string for the db
echo '</pre>';
echo '<pre>';
$myArrayString = json_encode($myArray);
print_r(json_decode($myArrayString)); //This will convert the db string to an object for manipulation
echo '</pre>';
There is no built in way to produce a HTML table from the result of a query. If you find yourself writing that sort of code over and over, then it would be a good candidate to make a reusable class or library. For example:
$table = new HTMLTable();
$table->setData($data);
echo $table->toHTML();
The above is not working code, just an example of how you could create reusable code instead of repeating the same table building code many times.
I tend to use a while loop with one of the mysql_fetch_.. functions. But essentially it's the same as what you do.
$query = 'SELECT
stuff
FROM
table';
if ($query = mysql_query($query)) {
while ($row = mysql_fetch_assoc($query)) {
foreach ($row as $key => $value) {
/* Things that need to be done on each field-value pair */
}
/* Things that need to be done on each row */
}
}
And as to the ~ separated list. I strongly recommend to save the data in separate DB fields, instead of packing it like that. Just create a new table for each such pack.

Convert foreach to for in PHP

foreach ( $this->parent->get_sections(null, $this->parent->author) as $section)
{
//...
}
I'm trying to do is force the loop to output each $section in the order I want. Each $section's name can be retrieved by $section->name. Let's say that I want to output $section "Section 2" first and then "Section 1" (and not in the order of the foreach). How can I force it do that? I presume the proper way would be a for loop with an if checking section names each time.
The proper way would be sorting the results when you call parent->get_sections(). How you would do this is entirely up to the implementation of that class and method. Changing this foreach to for for the sake of sorting seems like a code smell to me.
For the sake of answering the question as technical as possible.
$sections = $this->parent->get_sections(null, $this->parent->author);
$num_sections = count($sections);
for ($i = 0; $i < $num_sections; $i++) {
// what you do here is up to you $sections[$i]
}
Especially if you are not aware of the specific number of sections, you could use usort() to do a dynamic custom sort on the get_sections()-returned array or object and then utilize the existing code. (This is a little more elegant, imo, than doing the same in a for/foreach loop).
Not knowing the structure of your code, I would do something like.
// Get Org Sections
$sections = $this->parent->get_sections(null, $this->parent->author);
// Loop thru sections to get an array of names
foreach ( $sections as $key=>$section)
{
$sorted_sections[$section->name] = $key;
}
// Sort Array
//ksort — Sort an array by key
//krsort — Sort an array by key in reverse order
krsort($sorted_sections);
foreach ( $sorted_sections as $section)
{
// Orig Code
}
$section = $this->parent->get_sections(null, $this->parent->author);
echo $section[2]->name;
echo $section[1]->name;//just output the indexes the way you want
if you want it sorted, in say descending order, you can sort it that way and then use a for loop to display.

Categories