Good day :)
I have 2 tables - one containing the main headings and another which contains the subheadings and related paragraphs, which are related with a foreign key on TitleID and LinkID as shown here:
The idea is that I create a number of divs containing the main titles - from sectionamain with the related subcontent from sectiona, linked thru LinkID and TitleID.
<?php
function confirm_query($result_set) {
if (!$result_set) {
die("Database query failed.");
}
}
function get_practices() {
global $connection;
$query = "SELECT * FROM sectionamain ";
$query .= "LEFT JOIN sectiona ";
$query .= "ON sectiona.HeadingID = sectionamain.TitleID ";
$query .= "ORDER BY sectionamain.TitleID ASC";
$A_list = mysqli_query($connection, $query);
confirm_query($A_list);
return $A_list;
}
function display_practices() {
$output = "<div class=\"container inner\">\n";
$A_set = get_practices();
while ($list_A = mysqli_fetch_assoc($A_set)) {
$output .= "<div class=\"info\">\n";
$output .= "<div class=\"wrap\">\n";
$output .= "<h1 class=\"showcontent\" id=";
$output .= "". htmlentities($list_A["TitleID"]) ."";
$output .= ">";
$output .= htmlentities($list_A["MainTitle"]);
$output .= "</h1>\n";
$output .= "<div class=\"content\" id=\"content".htmlentities($list_A["TitleID"]) ."\">\n";
*** code would go here -
put items from sectiona with LinkID = 1 where TitleID = 1, etc until all data is sorted
$output .="</div>\n</div>\n</div>\n";
};
mysqli_free_result($A_set);
$output .= "</div>\n";
return $output;
}
?>
The end result would be something as shown below:
<h1>Main Title 1</h1>
<h3>Sub 1 with LinkID 1<h1>
<h3> ... </h3>
<h3>Sub n with LinkID 1</h3>
...
<h1>Main Title n</h1>
<h3>Sub 1 with LinkID n<h1>
<h3> ... </h3>
<h3>Sub n with LinkID n</h3>
Thank you in advance
xx
To solve your grouping issue, it's a matter of creating a data structure in an array. Since the database will give rows with repeating information, use this repeated information as a key in an array.
<?php
function get_practices() {
global $connection;
// It's good practice to specify which fields you want to get from the database.
// for clarity, I'm using heredoc format.
$query = >>>SECTIONAQUERY
SELECT am.TitleID, am.MainTitle, a.HeadingID, a.title, a.content
FROM sectionamain am
LEFT JOIN sectiona a
ON a.HeadingID = am.TitleID
ORDER BY sectionamain.TitleID ASC
SECTIONAQUERY;
$A_list = mysqli_query($connection, $query);
confirm_query($A_list);
return $A_list;
}
/**
* group_items
*
* takes database results and groups them by ID
*
* #param mysqli_result
* #return array
*/
function group_items($db_results) {
$data = array();
while($row = mysqli_fetch_assoc($db_results)) {
$title_id = htmlentities($row['TitleID']);
// group Main Title by title id
$data[$title_id]['title'] = htmlentities($row['MainTitle']);
// group data by title id
$data[$title_id]['data'][] = array(
'HeadingID' => htmlentities($row['HeadingID']),
'title' => htmlentities($row['title']),
'content' => htmlentities($row['content'])
);
}
return $data;
}
Then in your view, you could have something like this:
<?php
$A_list = get_practices();
$data = group_items($A_list);
// or, alternatively, $data = group_items(get_practices());
// now, go into "html mode" instead of in PHP,
// using PHP only for looping and variable substitution:
?>
<html>
<head>
...
</head>
<body>
<div>Your header stuff</div>
<div class="info">
<div class="wrap">
<?php foreach($data as $row): ?>
<h1 class="showcontent" id="<?= $row['title'] ?>"></h1>
<?php foreach($row['data'] as $sub_row): ?>
<h3><?= $sub_row['title'] ?></h3>
<div class="content"><?= $sub_row['content'] ?></div>
<!-- bonus: link to a new page? -->
<div><?= $sub_row['title'] ?></div>
<?php endforeach; ?>
<?php endforeach; ?>
</div>
</div>
</body>
</html>
Note, I personally would not stick output into a function; that's mixing logic and presentation. By using PHP's built-in templating, you don't have to worry about escaping quotes. Just use the <?= ?> syntax to drop in PHP variables. Use an include statement instead of calling the function. (or, you could always have the function include a partial view.)
Hope this addressed your question!
Related
In my 'magnums' table I have the following data:
What I want is to display the producer as a title and then the corresponding rows under that heading underneath that. My desired output:
I'm very new to PHP and mysql so I'm not sure how to go about this but this is what I have so far:
Model:
class Magnum_model extends CI_Model {
public function get_magnum_wines() {
$query = $this->db->query('SELECT * FROM magnums');
return $query->result();
}
}
Controller:
public function index() {
$data['magnums']= $this->Magnum_model->get_magnum_wines();
$this->load->view('magnums.php',$data);
}
View:
<h3>Domaine Vincent Rapet</h3>
<?php foreach($magnums as $magnum): ?>
<div id="magnum-img">
<div class="gallery">
<img src="/BurgundyDirect/gallery/<?php echo $magnum->Image; ?>">
</div><!-- gallery ends -->
<div class="desc">
<div id="wine-name">
<h5><?php echo $magnum->Name_of_wine; ?></h5>
</div>
<h6><?php echo $magnum->Producer; ?><h6>
<h4><?php echo $magnum->Magnum_price; ?></h4>
</div>
</div>
<?php endforeach; ?>
The output of the above code:
I don't know how to sort it to my desired output. Any help would be much appreciated and thank you in advance :)
If you need to show groups of products, you can get list of producers of producers and related products in controller.
In your producers model, create method, that get all producers (select * from producers).
Get producers in controller $producers = $this->Producer_model->get_producers();
Then create array with producer's name and products.
sample code:
$producerWithProducts = array();
foreach($producers as $producer) {
$producerId = $producer->Id;
$producerWithProducts[$producerId]['producerName'] = $producer->Name;
$producerWithProducts[$producerId]['products'] = $this->Magnum_model->get_magnum_wines_by_producer_id($producerId);
}
Then pass $producerWithProducts in template and iterate it.
I had the same thing but with wine categories / colours so this is what I did:
First make a new table called producers with 2 columns: id and name.
In the wine table make a new column with the name producer_id.
The value of this column is corresponds with the id in the producers table.
Then you can iterate through it like this:
function extractWines() {
$producers = mysqli_query("SELECT id FROM producers");
foreach($producers as $key => $value) {
$query = mysqli_query("SELECT * FROM wines WHERE producer_id = " . $value . "");
$rowname = mysqli_fetch_assoc($query);
$html = <<<HTML
<h1>{$rowname['producer']}</h1>
HTML;
echo $html;
while($row = mysqli_fetch_assoc($query)) {
$html = <<<HTML
(html code of the item with styling)
HTML;
echo $html;
}
}
}
This should help you with your problem.
I have searched for about 4 hours today on how to do this.
I want to pull all post titles and categories from the posts table and
essentially want to list the "Funny" category and then list all post that have the funny category under that category. Right now I am getting the following:
Funny
-post title
Funny
-post title
I want to output
Funny
-post title
-post title
<?php
$query = "SELECT post_category,post_title FROM posts ";
$select_categories_sidebars = mysqli_query($connection, $query);
?>
<h4>Blog Categories</h4>
<div class="row">
<div class="col-lg-12">
<ul class="list-group">
<?php
while($row = mysqli_fetch_assoc($select_categories_sidebars)) {
$post_title = $row['post_title'];
$post_tags = $row['post_category'];
echo "<li class='list-group-item'>$post_tags</li><ul>";
echo "<li class='list-group-item'><a href='category.php?category=$post_title'> {$post_title}</a></li></ul>";
}
?>
</ul>
That should do the trick:
First you should sort your query by category:
$query = "SELECT post_category,post_title FROM posts ORDER BY post_category";
Then do this:
<?php
while($row = mysqli_fetch_assoc($select_categories_sidebars)) {
$post_title = $row['post_title'];
$post_tags = $row['post_category'];
$used_tag = null,
// check if you already posted that category/tag. If not, show it:
if($used_tag!=$post_tags) {
echo "<li class='list-group-item'>$post_tags</li>"; // I removed a '</ul>' here
// set this title as 'used'
$used_tag=$post_tags;
}
echo "<li class='list-group-item'><a href='category.php?category=$post_title'> {$post_title}</a></li>"; // I removed a '</ul>' here too
}
?>
BUT
In an ideal world you'd have two tables to accomplish this.
One for the categories, one for the posts. Each table with id's to work with
This way you produce a lot of redundant data, it's more complicated to filter, and so on...
You might want to have a look at relational database design.
Well I basically got it working how I want I just need to format it correctly now, but it is working with some help from this question. PHP Group sql query under the same title
<?php
$query = "SELECT post_category,post_title FROM posts ORDER BY post_tags";
$select_categories_sidebars = mysqli_query($connection, $query);
?>
<h4>Blog Categories</h4>
<div class="row">
<div class="col-lg-12">
<ul class="list-group">
<?php
$title = "";
while ($row = mysqli_fetch_array($select_categories_sidebars)) {
if ($row['post_category'] != $title) {
echo '<li class="list-group-item">'.$row['post_category'].'</li><br>';
$title = $row['post_category'];
}
echo '<li class="list-group-item">'.$row['post_title'];
}
?>
How can i add a pagination system to this simple item display? And how i can add pagination for the results from filter? I just get lost that part and i cant figure it out!
I want to apply CSS on the menu too!
Here's the code:
<?php
include('db.php');
if(isset($_POST['filter']))
{
$filter = $_POST['filter'];
$result = mysql_query("SELECT * FROM products where Product like '%$filter%' or Description like '%$filter%' or Category like '%$filter%'");
}
else
{
$result = mysql_query("SELECT * FROM products");
}
while($row=mysql_fetch_assoc($result))
{
echo '<li class="portfolio-item2" data-id="id-0" data-type="cat-item-4">';
echo '<div>
<span class="image-block">
<a class="example-image-link" href="reservation/img/products/'.$row['imgUrl'].'" data-lightbox="example-set" title="'.$row['Product'].'""><img width="225" height="140" src="reservation/img/products/'.$row['imgUrl'].'" alt="'.$row['Product'].'" title="'.$row['Product'].'" />
</a>
</span>
<div class="home-portfolio-text">
<h2 class="post-title-portfolio"><font color="#666666">'.$row['Product'].'</font></h2>
<p class="post-subtitle-portfolio"><font color="#666666">Descrição: '.$row['Description'].'
<p class="post-subtitle-portfolio"><font color="#666666">Categoria: '.$row['Category'].'
<p class="post-subtitle-portfolio">Código: '.$row['Price'].'</p><br/></font></p>
</div>
</div>';
echo '</li>';
}
?>
EDITED:
<?php
include('db.php');
if(isset($_POST['filter']))
{
$filter = $_POST['filter'];
$result = mysql_query("SELECT * FROM products where Product like '%$filter%' or Description like '%$filter%' or Category like '%$filter%'");
}
else
{
$start=0;
$limit=6;
if(isset($_GET['id']))
{
$id = $_GET['id'];
$start = ($id-1)*$limit;
}
$result = mysql_query("SELECT * FROM products LIMIT $start, $limit");
}
while($row = mysql_fetch_array($result))
{
echo '<li class="portfolio-item2" data-id="id-0" data-type="cat-item-4">';
echo '<div>
<span class="image-block">
<a class="example-image-link" href="reservation/img/products/'.$row['imgUrl'].'" data-lightbox="example-set" title="'.$row['Product'].'""><img width="225" height="140" src="reservation/img/products/'.$row['imgUrl'].'" alt="'.$row['Product'].'" title="'.$row['Product'].'" />
</a>
</span>
<div class="home-portfolio-text">
<h2 class="post-title-portfolio"><font color="#666666">'.$row['Product'].'</font></h2>
<p class="post-subtitle-portfolio"><font color="#666666">Descrição: '.$row['Description'].'
<p class="post-subtitle-portfolio"><font color="#666666">Categoria: '.$row['Category'].'
<p class="post-subtitle-portfolio">Código: '.$row['Price'].'</p><br/></font></p>
</div>
</div>';
echo '</li>';
}
echo "</ul>";
$rows = mysql_num_rows(mysql_query("SELECT * FROM products"));
$total = ceil($rows/$limit);
if($id>1)
{
echo "<center><a href='?id=".($id-1)."' class='button'>Anterior</a></center>";
}
if($id!=$total)
{
echo "<center><a href='?id=".($id+1)."' class='button'>Próximo</a></center>";
}
?>
You should have something like this:
// declare a base query
$q = "SELECT * FROM products";
if(isset($_POST['filter']))
{
$filter = $_POST['filter'];
// append filter to query
$q += "where Product like '%$filter%' or Description like '%$filter%' or Category like '%$filter%'");
}
// check for "page" URL parameter, if not available, go to first page
$page = isset($_GET['page']) ? $_GET['page'] : 1;
// check for "pageSize" URL parameter, if not available, fall back to 20
$pageSize = isset($_GET['pageSize']) ? $_GET['pageSize'] : 20;
// append the pagination to your query
$q += sprintf("LIMIT %d,%d;", ($page-1)*$pageSize, $pageSize);
// execute the constructed query
$result = mysql_query($q);
Note that the code is "pseudoish", not tested, but should give you the base idea.
Also, you can check this SO post about pagination with MySQL.
UPDATE
In PHP if you use an uninitialized variable, then it will have a context-dependent default value. See the documentation about this here. Here is an extract:
It is not necessary to initialize variables in PHP however it is a
very good practice. Uninitialized variables have a default value of
their type depending on the context in which they are used - booleans
default to FALSE, integers and floats default to zero, strings (e.g.
used in echo) are set as an empty string and arrays become to an empty
array.
I was trying to create a commenting system like that uses facebook. I use php and jquery. My code works perfect. All I want is just to add a reply system in it. Any idea how to do this?
This is my main page: wall.php
<script>
$(document).ready(function(){
$("#comment_process").click(function(){
if($("#comment_text").val() != ""){
$.post("comments.php?action=post", { comment: $("#comment_text").val() }, function(data) {
$(".comments").html(data);
$("#comment_text").val("");
});
}
});
});
</script>
<div class="comment_container">
<div class="comment_form">
<textarea id="comment_text" ></textarea>
<input type="button" id="comment_process" value="Post"/>
</div>
</div>
<div class="comments"> <?php include_once("comments.php");?> </div>
?>
and this is comments.php
<?php
function getComments(){
$comments = "";
// use desc order by date in order to display comments by date
$sql = mysql_query("SELECT * FROM comments ORDER BY comment_date DESC ") or die (mysql_error());
if(mysql_num_rows($sql) == 0){
$comments = " <div class='each_comment'> There are no comments ...</div> ";
}else{
while ($row= mysql_fetch_assoc($sql)){
$comments .= "Says : <div class='each_comment'> <small><em> ".$row['comment_date']." </em></small><br />".$row['comment']."</div> </br>";
}
}
return $comments;
}
function postComments($comment){
$comment = mysql_real_escape_string(strip_tags($comment));
$sql = mysql_query(" INSERT INTO `comments` (comment, comment_date) VALUES ('".$comment."', now()) ");
return true;
}
if((isset($_GET['action'])) && ($_GET['action'] == "post")) {
postComments($_POST['comment']);
}
echo getComments();
?>
Orbling has it right. Let me show you what I did for my blog site that I am working on in ASP.NET MVC and maybe it will others in the future.
I have two classes named Article and Comment and they would have the following properties in php from what I remember. A little rusty on my php
class Article {
public $article_id;
public $user_id;
public $article_date;
//... more properties, ctors, methods
}
class Comment {
public $comment_id;
public $article_id;
public $isRoot;
public $parent_id;
public $comment_date;
public $content;
//... more properties, ctors, methods
}
Then I would user similar to what you constructed:
function getComments($article_id){
$str = "";
// This should put all the comment in order by date but we still have to separate the //comments from the replies so we will add an additional nest foreach loop following an if //statement inside the main foreach loop. What will happen is the newest/oldest comment //will be the first one appended to the string and then it will go to the inner foreach //loop to see if the $parent_id = $comment_id and if it does it will append to string.
//I have a different div class for replies so they are indented. This may not be the most //practical way, but considering that most articles are going to have less that a 1000 //comments if your lucky this wont be too bad.
$q = $this->db->query("SELECT * FROM comments WHERE article_id = $article_id ORDER BY comment_date DESC") or die (mysql_error());
if($q->num_rows() > 0):
foreach($q->result() as $row):
if($row->isRoot && $row->ParentId = null):
// here you will append to the $str where you will create a div container //for each comment which is a root comment. I included a user avatar, user link, date //create, content, and on the bottom of my div I have an <span>expand replies</span> and a //<span>reply<span> where I use JQuery to toggle the replies on and off etc.
// Now I do the same thing here as I will cycle through $q to find the //comments with the parent_id equal to the comment_id of this $row
//they will already be ordered by date. Cool thing is you could create an array of the reply and change the order so maybe you want newest comments on top but oldest replies on //top or I should say below the parent comment
foreach($q->result() as $row2):
if($row->comment_id = $row2->parent_id)
// do the same thing except html format for reply (eg: indent div)
endif;
endforeach;
endforeach;
}
else:
$str = "<div class='each_comment'> There are no comments ...</div> ";
endif;
echo htmlentities($str);
}
Then you will have to use some JQuery/Javascript as Orbling suggests: show(); hide(); replies and use a function such as slideDown(parent_id); once the reply button is hit where a <div> container appears below its parent comment.
How how would I just grab the first few words of a variable such as $data for example. I'm trying to create an article preview section and that variable is an article. I'm trying to display of course only a preview of it.
<?php
$sql = "SELECT author, data, postdate, Title, previewimg FROM articlepreview ORDER BY RAND() LIMIT 1";
$query = mysqli_query($db_conx,$sql);
$prev = "";
while ($row = mysqli_fetch_array($query, MYSQLI_ASSOC)) {
$a = $row["author"];
$data = $row["data"];
$postdate = $row["postdate"];
$title = $row["Title"];
$previewimg = $row["previewimg"];
$prev .= '
<div class="wrapPreviewArticle">
<div style="headerPreview"><h4>'.$title.'</h4></div>
<div class="wrapPreviewRow">
<div style="imagePreview"><img src="'.$previewimg.'" height="20%" width="20%" alt="'.$title.'" /></div>
<div clas="wordPreview">'.$data.'</div>
</div>
</div>
';
}
?>
Once I've got this I would spit out the variable
<body>
<div><?php echo $prev; ?></div> <!--with only the desired portion.-->
</body>
Any help is greatly appreciated.
You could use SUBSTRING_INDEX on your query:
"SELECT author, SUBSTRING_INDEX(data, ' ', 5) data, ... FROM articlepreview ..."
This will extract only the first 5 words from the field data.
You can grab for example the first 200 characters and display only this as a preview
$pos=strpos($data, ' ', 200);
$preview=substr($data,0,$pos );
This will also make sure you split it at the space not in the middle of the word
You could show the first X characters (X here is 20):
<div class="wordPreview">'.substr($data, 0, 20).'</div>