Loop through PDO statment fetch(PDO::FETCH_OBJ) using a class - php

I have class called posts in a separate file :
<?php
class POSTS {
//Start of class properties:
private $db_connection;
public $post_id;
public $section_id;
public $user_id;
public $post_title;
public $post_details;
public $post_date;
public $post_category;
public $post_display;
public $num_of_rows;
public function getRelatedPosts($section_name, $category, $display) {
$stm = $this->db_connection->prepare("SELECT * FROM posts WHERE section_name!=:Section_name AND category=:Category AND display=:Display ORDER BY id DESC");
$stm->bindParam(":Section_name", $section_name);
$stm->bindParam(":Category", $category);
$stm->bindParam(":Display", $display);
$stm->execute();
$this->num_of_rows = $stm->rowCount();
if ($this->num_of_rows >= 1) {
$post_data = $stm->fetch(PDO::FETCH_OBJ);
$this->post_id = $post_data->id;
$this->section_id = $post_data->section_id;
$this->user_id = $post_data->user_id;
$this->post_title = $post_data->title;
$this->post_details = $post_data->details;
$this->post_date = $post_data->date;
$this->post_category = $post_data->category;
$this->post_display = $post_data->display;
}
}
}
?>
Then I want to loop through the results in my Index file:
$section_name = 'PHP';
$display = 'yes';
$POSTS->getRelatedPosts($section_name, $category $display);
$num_of_rows = $POSTS->num_of_rows;
if ($num_of_rows >= 1) {
for ($m=1; $m<=$num_of_rows; $m++) {
$post_id = $POSTS->post_id;
$section_id = $POSTS->section_id;
$user_id = $POSTS->user_id;
$post_title = $POSTS->post_title;
$post_details = $POSTS->post_details;
$post_date = $POSTS->post_date;
?>
<div id="related_post">
<h4><?php echo $post_title;?></h4>
<p><?php echo $post_details;?></p>
</div>
<?php
}
} else {
echo 'Sorry no related posts now!';
}
Unfortunately The results are only one record repeated as many as the $num_of_rows variable equal.
I tried some different ways with fetch methods like:
fetchAll() and others styles but always the result is an error or only one record repeated.
Someone help me with my code please.

If you want to loop, try looping in your method:
public function getRelatedPosts($section_name, $category, $display)
{
$stm = $this->db_connection->prepare("SELECT * FROM posts WHERE section_name!=:Section_name AND category=:Category AND display=:Display ORDER BY id DESC");
$stm->bindParam(":Section_name", $section_name);
$stm->bindParam(":Category", $category);
$stm->bindParam(":Display", $display);
$stm->execute();
$this->num_of_rows = $stm->rowCount();
if ($this->num_of_rows >= 1) {
while($post_data = $stm->fetch(PDO::FETCH_OBJ)) {
$this->post_id[] = $post_data->id;
$this->section_id[] = $post_data->section_id;
$this->user_id[] = $post_data->user_id;
$this->post_title[] = $post_data->title;
$this->post_details[] = $post_data->details;
$this->post_date[] = $post_data->date;
$this->post_category[] = $post_data->category;
$this->post_display[] = $post_data->display;
}
}
}
Your loop would likely be something like:
for ($m=1; $m<=$num_of_rows; $m++) {
$post_id = $POSTS->post_id[$m];
$section_id = $POSTS->section_id[$m];
$user_id = $POSTS->user_id[$m];
$post_title = $POSTS->post_title[$m];
$post_details = $POSTS->post_details[$m];
$post_date = $POSTS->post_date[$m];
?>
<div id="related_post">
<h4><?php echo $post_title;?></h4>
<p><?php echo $post_details;?></p>
</div>
<?php
}

In my class I should use the following instead of the current one:
$results = $stm->fetchAll(PDO::FETCH_OBJ);
I will not get any advantages of my current class properties.
In my index file I will loop through the $results using foreach loop as the following:
foreach($results as $post){
$post_title = $post->title;
$post_details = $post->details;
}
and so on...

I'm experimenting with PDO and I had the same issue with PDO::FETCH_OBJ
I'm using PHP 5.6 in xampp 5.6.30
needless to say that
- the DB name is animals
- it has three columns only : animal_id, animal_type, animal_name
the following test code works fine and outputs all the records (that in my test DB are only eleven)
$stmt = $dbh->prepare("SELECT * FROM animals");
$stmt->execute();
if($stmt->rowCount() > 0) {
while($obj = $stmt->fetch(PDO::FETCH_OBJ)) {
echo $obj->animal_type . " " . $obj->animal_name . "<br>";
}
}
perhaps you may insert the counters inside the loop or, even better, make the query to properly limit the range.
Anyway, the code above, as expected outputs what follow
kookaburra bruce
emu bruce
goanna bruce
dingo bruce
kangaroo bruce
wallaby bruce
wombat bruce
koala bruce
kiwi cambiato
pippo zollo
pippz zoll2

Related

How can i create a new section with only 5 elements in PHP?

i have a PHP code that creates a team page with team member boxes on my website. The code for every team meber is fetched from the database, and it works fine, but time has passed and we are many now. So many, that I need to display only 5 team members per section. Like 5 team members in one line, the next 5 in the other line, .. - I tried a few things to do that, but I got stuck. Sometimes members were missing, sometimes he created many lines with the same members, and so on. That's why I'm asking here. I already searched a bit but couldn't find anything that helps me.
Currently, my code creates a new <section> for ALL team members. But that's not what I need. It should create a section for 5 members, the next section for the next 5 members, and so on. How can I do that?
(btw I'm a complete beginner in PHP and want to learn something from it so you can improve my code if you want.)
function team_helfer() {
$db = new mysqli("ip", $username, $password, $database);
$result = mysqli_query($db, "SELECT code FROM team_data WHERE rank = 'HELFER'");
$team_list = "";
$count = 0;
while ($row = mysqli_fetch_assoc($result)) {
foreach ($row as $field => $value) {
$team_list .= "$value";
++$count;
}
}
if ($count == 2) {
$code = '<section class="elementor-section elementor-inner-section elementor-element elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-element_type="section">
<div class="elementor-container elementor-column-gap-default" style="left: 17%;">
'.$team_list.'
</div>
</section>';
} elseif ($count == 1) {
$code = '<section class="elementor-section elementor-inner-section elementor-element elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-element_type="section">
<div class="elementor-container elementor-column-gap-default" style="left: 33%;">
'.$team_list.'
</div>
</section>';
} else {
$code = '<section class="elementor-section elementor-inner-section elementor-element elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-element_type="section">
<div class="elementor-container elementor-column-gap-default">
'.$team_list.'
</div>
</section>';
}
mysqli_free_result($result);
$db->close();
return $code;
}
add_shortcode( 'team_helfer', 'team_helfer' );
Code from HTMHell's answer:```php
function team_helfer() {
$db = new mysqli("ip", $username, $password, $database);
$result = mysqli_query($db, "SELECT code FROM team_data WHERE rank = 'HELFER'");
$rows = mysqli_fetch_all($result, MYSQLI_ASSOC);
$sections = array_chunk($rows, 5);
foreach ($sections as $section) {
$teamList = implode(",", array_map(function($row) {
return $row['code'];
}));
$code = '<section class="elementor-section elementor-inner-section elementor-element elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-element_type="section">
<div class="elementor-container elementor-column-gap-default">'.$teamList.'</div></section>';
}
mysqli_free_result($result);
$db->close();
return $code;```
Sadly that doesn't help, all elements are vanished now, i can't see them.
I think you are looking for array_chunk.
$rows = mysqli_fetch_all($result, MYSQLI_ASSOC);
$sections = array_chunk($rows, 5);
foreach ($sections as $section) {
$teamList = implode(",", array_map(function($row) {
return $row['code'];
}, $section));
echo "<section>$teamList</section>";
}
Here's a live example:
https://3v4l.org/mXRtV

How to PDO query to retrieve rows that match a value in an array

I have a table with column nearbyAttractions which contains values seperated by a comma. For example A001,A002
I am querying that column then converting the contents to an array called $NearbyAttractionsArray.
print_r($NearbyAttractionsArray);
Array ( [0] => A001 [1] => A003 )
I want to run a PDO SQL query to find records that match for each value of the array then output them in a loop.
$arrayQuery = $this->con->prepare("SELECT attid, attTitle, attThumbnail, AttTagline FROM attractions WHERE
attid=$NearbyAttractionsArray AND attStatus=1");
$arrayQuery->execute();
when I try this it converts $NearbyAttractionsArray to a string called array...
What would be the correct syntax to output values attid, attTitle, attThumbnail, AttTagline for each row where attId matches one of the values in the array?
I suspect some kind of foreach loop would be needed but cannot find the correct way to write this as a PDO statement.
Many thanks
For perspective my complete class code is:
<?php
class NearbyAttractionsProvider {
private $con, $attId;
public function __construct($con, $attId) {
$this->con = $con;
$this->attId = $attId;
} // end of constructor
public function createNearbyAttractionsList($con, $attId) {
$query = $this->con->prepare("SELECT nearbyAttractions FROM attractions WHERE attId=:attId");
$query->bindParam(":attId", $attId);
$query->execute();
$this->sqlData = $query->fetch(PDO::FETCH_ASSOC);
$NearbyAttractions = $this->sqlData["nearbyAttractions"];
$NearbyAttractionsRemoveCommas = str_replace(',', '',$NearbyAttractions);
$NearbyAttractionsArray = str_split($NearbyAttractionsRemoveCommas, 4);
print_r($NearbyAttractionsArray);
$CountNearbyAttractions = sizeof($NearbyAttractionsArray);
if($NearbyAttractionsArray[0] != "") {
$results = "<h3>There are $CountNearbyAttractions Nearby Attractions</h3>";
$arrayQuery = $this->con->prepare("SELECT attid, attTitle, attThumbnail, AttTagline FROM attractions WHERE
attid=$NearbyAttractionsArray AND attStatus=1");
$arrayQuery->execute();
$results .= "<div class='nearbyAttractionsItemsContainer'>";
while($row = $arrayQuery->fetchAll(PDO::FETCH_ASSOC)) {
$id = $row["attid"];
$img = $row["attThumbnail"];
$title = $row["attTitle"];
$tagline = $row["AttTagline"];
$results .= "<div class='nearbyAttractionListItem'>
<a href='Attraction.php?attId=$id&title=$title' data-AttractionId='$id'
class'NearbyAttractionItem-url'>
<img class='NearbyAttractionItem-thumbnail' src='$img' height='220' width=300'>
<h3 class='NearbyAttractionItem-title'>$title</h3>
<p class='NearbyAttractionItem-tagline'>$tagline</p>
</a>
</div>";
} // End of while loop
$results .= "</div>"; // End of nearbyAttractionsItemsContainer
} // End of IF statement
else {
$results = "<h3>There are No Nearby Attractions</h3>";
} // End of Else statement
return $results;
} // End of public function createNearbyAttractionsList
} // End pf class NearbyAttractionsProvider
Your query should look like:
SELECT attid, attTitle, attThumbnail, AttTagline
FROM attractions
WHERE attid IN('A001', 'A003')
AND attStatus=1
Of course I assume that attid stores atomic values. To convert array items to string you can use foreach() loop or implode() function. In second case, you'll need wrap it with apostrophes before you'll join it.
Many hours of fannying around and it works with a foreach loop.
<?php
class NearbyAttractionsProvider {
private $con, $attId;
public function __construct($con, $attId) {
$this->con = $con;
$this->attId = $attId;
} // end of constructor
public function createNearbyAttractionsList($con, $attId) {
$query = $this->con->prepare("SELECT nearbyAttractions FROM attractions WHERE attId=:attId");
$query->bindParam(":attId", $attId);
$query->execute();
$this->sqlData = $query->fetch(PDO::FETCH_ASSOC);
$NearbyAttractions = $this->sqlData["nearbyAttractions"];
$NearbyAttractionsRemoveCommas = str_replace(',', '',$NearbyAttractions);
$NearbyAttractionsArray = str_split($NearbyAttractionsRemoveCommas, 5);
$CountNearbyAttractions = sizeof($NearbyAttractionsArray);
if($NearbyAttractionsArray[0] != "") {
$results = "<h3>There are $CountNearbyAttractions Nearby Attractions</h3>";
foreach($NearbyAttractionsArray as $row) {
$arrayQuery = $this->con->prepare("SELECT attId, attTitle, attThumbnail, AttTagline FROM attractions WHERE
attId=:row AND attStatus=1");
$arrayQuery->bindParam(":row", $row);
$arrayQuery->execute();
$results .= "<div class='nearbyAttractionsItemsContainer'>";
while($row = $arrayQuery->fetch(PDO::FETCH_ASSOC)) {
$id = $row["attId"];
$img = $row["attThumbnail"];
$title = $row["attTitle"];
$tagline = $row["AttTagline"];
$results .= "<div class='nearbyAttractionListItem'>
<a href='Attraction.php?attId=$id&title=$title' data-AttractionId='$id'
class'NearbyAttractionItem-url'>
<img class='NearbyAttractionItem-thumbnail' src='$img' height='220' width=300'>
<h3 class='NearbyAttractionItem-title'>$title</h3>
<p class='NearbyAttractionItem-tagline'>$tagline</p>
</a>
</div>";
} // End of while loop
$results .= "</div>"; // End of nearbyAttractionsItemsContainer
} // End of foreach loop
} // End of IF statement
else {
$results = "<h3>There are No Nearby Attractions</h3>";
} // End of Else statement
return $results;
} // End of public function createNearbyAttractionsList
} // End pf class NearbyAttractionsProvider

Recursive function for comment and reply PHP application

I am having difficulty conceptualizing a recursive function for appending replies to comments, replies to replies, replies to replies to replies, etc.
This is my comments table:
Which SHOULD look something like this when rendered:
As it stands I can render each comment associated with the article_id (excluding those that are NOT NULL, of course):
$comments = $commentClass->fetch_article_comments($article_id);
foreach($comments as $comment) {
$comment_id = $comment['comment_id'];
$member_id = $comment['member_id'];
$comment_text = $comment['comment_text'];
$comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago
//render comment using above variables
}
Now I'm assuming I need to add a recursive function at the end of the above foreach statement, but I have yet to come up with anything remotely successful in appending the comments replies and the replies to each reply.
Can anyone help me accomplish this or perhaps point me in the right direction. I am not entirely familiar with recursive functions. I have done some scanning of the internet and on stackoverflow looking for something that helps, but haven't found anything helpful yet.
I did come across this post which recommended using a hierarchical database system, but I think I would prefer to use a php recursive function for this.
Thanks.
edit
By using the below answers I am only returning the results first comment and then it iterates and displays that one comment indefinitely. I can't figure out why?
My php:
function display_comments($article_id, $parent_id=0, $level=0) {
global $comment;
global $member;
global $signed_in;
global $username;
$comments = $comment->fetch_article_comments($article_id, $parent_id);
foreach($comments as $data) {
$comment_id = $data['comment_id'];
$c_member_id = $data['member_id'];
$comment_text = $data['comment_text'];
$comment_timestamp = timeAgo($data['comment_timestamp']); //get time ago
$member_data = $member->fetch_member_data($c_member_id);
$c_member_username = $member_data['member_username'];
$c_member_avatar = $member_data['member_avatar'];
//render HTML here
$parent = $data['comment_parent'];
display_comments($article_id, $parent, $level+1);
}//end foreach
}//end display_comments()
and my PDO query:
public function fetch_article_comments($article_id, $parent_id) { //$page = (int)(!isset($_GET['page'])) ? 0 : $_GET['page'];
if ($parent_id > 0) {
$parent_id = "= $parent_id";
} else {
$parent_id = "IS NULL";
}
$query = $this->db->prepare("SELECT * FROM `comments2` WHERE `article_id` = $article_id AND `comment_parent` $parent_id ORDER BY `comment_timestamp` DESC");
try{
$query->execute();
$comments = $query->fetchAll(); //returns an array
$query->closeCursor();
return $comments;
} catch(PDOException $e){
die($e->getMessage());
}
}
The core of the problem is this:
$comments = $commentClass->fetch_article_comments($article_id);
I assume, this function somwhere creates and runs SQL, that is similar to SELECT ... WHERE comments.article_id=$article_id. This is not sufficient - you need something like
$comments = $commentClass->fetch_article_comments($article_id, $parent_id);
that translates into SQL similar to SELECT ... WHERE comments.article_id=$article_id AND comments.comment_parent ($parent_id>0)?"=$parent_id":"IS NULL"
Now you can write your PHP function:
function display_comments ($article_id, $parent_id=0, $level=0) {
$comments = $commentClass->fetch_article_comments($article_id, $parent_id);
foreach($comments as $comment) {
$comment_id = $comment['comment_id'];
$member_id = $comment['member_id'];
$comment_text = $comment['comment_text'];
$comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago
//render comment using above variables
//Use $level to render the intendation level
//Recurse
display_comments ($article_id, $comment_id, $level+1);
}
}
And finally call it with display_comments ($article_id);
You could do something like:
function getCommentsForParent($parent="") {
echo "<div class=\"comment\">";
$db = get("select your db logics where parent = $parent");
foreach ($db as $comment) {
echo "print your comment in a box and make a div around the hole comments"
getCommentsForParent($comment['parent_id']);
}
echo "</div>";
}
invoke function with getCommentsForParent()
With your code it should be something like:
function getCommentForParent($parent="") {
global $commentsClass, $article_id;
$comments = $commentClass->fetch_article_comments($article_id,$parent);
foreach($comments as $comment) {
$comment_id = $comment['comment_id'];
$member_id = $comment['member_id'];
$comment_text = $comment['comment_text'];
$comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago
getCommentForParent($comment['parent']);
}
}
Look closely, ive adjusted your fetch article_comments. It now has a listener for $parent. Make sure that when your $parent = "", the class will only select the comments with empty parent.
invoke with getCommentsForParent()
It will automatically loop through the parent. Ofcourse this is highly conceptual but given your code you should get the hang of it.

function returning only once, why?

During my coding I really got stuck into this problem.
I ran a foreach loop and for every item I had to get a certain value from a function.
But I got only one returned. I could not figure out what was happening. I hope you guys surely will.
Below is the short version of my program.
Database structure is given at last.
<?php
function opendb() {
mysql_connect("localhost", "root", "root");
mysql_select_db("something_db");
}
function sql_query($sql) {
$datas = array();
if ($res = mysql_query($sql)) {
$x = 0;
while ( $data = mysql_fetch_assoc($res) ) {
$datas[$x] = $data;
$x += 1;
}
}
return $datas;
}
function get_parent_id($table, $parent, $cid) {
// cid=>child id
$sql = "SELECT * FROM $table WHERE id=$cid";
$datas = sql_query($sql);
$pid = $datas[0]['parent'];
$p_id = $datas[0]['id'];
if ($pid != 0) {
get_parent_id($table, $parent, $pid);
} else {
return $p_id;
}
}
opendb();
$datas_pkg = sql_query("SELECT * FROM tbl_packages WHERE 1");
foreach ( $datas_pkg as $data_pkg ) {
echo $data_pkg['destination_id'] . '-->';
echo $parent_id = get_parent_id('tbl_destinations', 'parent', $data_pkg['destination_id']);
echo '<br/>';
}
?>
Database structure..
tbl_destinations
+--------+-------------------------+-----------+
| id(int)|destination_name(Varchar)|parent(int)|
+--------+-------------------------+-----------+
tbl_packages
+-------+---------------------+-------------------+
|id(int)|package_name(varchar)|destination_id(int)|
+-------+---------------------+-------------------+
If I did not clear my question please let me know so that I can help you to help me.
if($pid!=0)
{
get_parent_id($table,$parent,$pid);
}
You call the function, but never use its value.

How to make a php function contain mysql commands

I want to create a simple menu function which can call it example get_menu()
Here is my current code.
<?php
$select = 'SELECT * FROM pages';
$query = $db->rq($select);
while ($page = $db->fetch($query)) {
$id = $page['id'];
$title = $page['title'];
?>
<?php echo $title; ?>
<?php } ?>
How to do that in?
function get_menu() {
}
Let me know.
Here is the function for that:
function get_menu(&$db)
{
$select = 'SELECT * FROM pages';
$query = $db->rq($select);
$menu = '';
while ($page = $db->fetch($query)) {
$id = $page['id'];
$title = $page['title'];
$menu .= '<a href="page.php?id=' . $id . '" &title="' . $title .'></a>'
}
return $menu;
}
.
Some Quick Corrections In Your Script:
You were missing = after id
You were missing & after title
Suggestion:
You can give your menu links a class and style as per your menu needs :)
get_menu() has to get reference to $db somehow. Probably the best and easiest way is to pass that reference as parameter:
function get_menu(MyDatabaseHandler $db) {
// code proposed by Sarfraz here
}
now here you already have a mistake:
<?php echo $title; ?>
notice the = after id
you can't be too careful
First, separate the part where you're doing something, and the one used to display things.
Second, the alternative syntax looks better for the display part.
<?php
function get_menu(){
$items = array();
$select = 'SELECT * FROM pages';
$query = $db->rq($select);
while ($page = $db->fetch($query)) {
$items[] = $page['id'];
}
return $items;
}
$menuItems = get_menu();
?>
<ul>
<?php foreach($menuItems as $item): ?>
<li><?php echo $item['title']; ?></li>
<?php endforeach;?>
</ul>
The code Sarfraz posted is going to create invalid anchor tags (i.e. links). They'll also be missing names. Here is the shorter/faster version:
function get_menu($db)
{
$result = $db->rq('SELECT id,title FROM pages');
$menu = '';
while ($page = $db->fetch($result))
{
$id = $page['id'];
$title = $page['title'];
$menu .= "<a href='page.php?id={$id}&title={$title}'>{$title}</a>\n";
}
return $menu;
}
To use that do this:
echo get_menu($db);
The error you were getting was probably resulting from not passing the database connection to the function.
NOTE: It's generally not a good idea to show database ID numbers to the user in the interest of security; slugs are much better for identifying pages and are SEO friendly. Also, there shouldn't be any need to pass the page title to page.php because if you've got the ID you can get that when you need it from the database. Here's the code with this in mind:
function get_menu($db)
{
$result = $db->rq('SELECT id,title FROM pages');
$menu = '';
while ($page = $db->fetch($result))
{
$menu .= "<a href='page.php?id={$page['id']}'>{$page['title']}</a>\n";
}
return $menu;
}
just put function get_menu() { above your code and } below
or like this??
function get_menu( $title, $id ) {
$menu = '';
$menu .= '<a href="page.php?id' . $id . '" title="' . $title .'></a>'
echo $menu;
}
------------------------
$select = 'SELECT * FROM pages';
$query = $db->rq($select);
while ($page = $db->fetch($query)) {
$id = $page['id'];
$title = $page['title'];
get_menu($title, $id );
}
function getMenu()
{
$select = 'SELECT FROM pages';
$query = $db->rq($select);
$menu = new Array;
while ($page = $db->fetch($query)) {
$menu[] = '';
}
return $menu;
}

Categories