I am trying to implement a commenting system on my website that is only two levels deep for example you will have the main comment and replies to that comment but it does not go any further:
main comment 1
(sub_comment1)
(sub_comment2)
main comment 2
(sub_comment1)
(sub_comment2)
(sub_comment2)
etc...
Make sense?
I am creating the site in codeigniter but i think a basic php solution will do.
each row in my database table has an id and a parent_id, if the parent id is 0 then its a main comment and if its a sub-comment it will have the id of its parent comment in parent_id.
how to I feed a two dimensional array with the parent and child comments in the right order.
My current code is like so: The controller:
function status_comments($id){
$this->load->model('status_model');//load the status model
$this->load->model('comment_model');//load the comment model
$status = $this->status_model->get_entry_and_category($id);
$comments = $this->comment_model->get_comments($id);
if($status !== false) {
if($comments !== false) {
foreach($comments as $comment){
if($comment->reply_id == 0){
$comment =
}
}
$content_data['comments'] = $comments;
}
$content_data['status'] = $status;
$data['content'] = $this->load->view('status_view', $content_data, TRUE);
$data['title'] = $status->title.' - High Value Status';
$data['page_title'] = $status->title;//The page H1 tag
$this->load->view('home', $data);
}
else
{
$this->session->set_flashdata('invalid', '<p class="rejectionalert"><span>The status you tried to view does not exist.</span></p>');
redirect('home');
}
}
The model function:
//Gets comments associated with an individual status
function get_comments($status_id, $offset=null, $limit=null)
{
$this->db->select('id, comment, nickname, created, reply_id');
$this->db->from('comments');
$this->db->where('active', 1);
$this->db->where('status_id', $status_id);
$query = $this->db->get();
if ($query->num_rows() > 0) {
return $query->result();
}
return false;
}
This works but its using more than one query, the model:
function get_comments($status_id, $limit=NULL, $offset=NULL)
{
$this->db->where(array('status_id' => $status_id, 'reply_id' => 0));
$query = $this->db->get('comments', $limit, $offset);
$parents = $query->result_array();
$comments = array();
foreach($parents as $key => $comment)
{
array_push($comments, $comment);
$this->db->order_by('created', 'ASC');
$this->db->where(array('status_id' => $status_id, 'reply_id' => $comment['id']));
$comments = array_merge($comments, $this->db->get('comments')->result_array());
}
return $comments;
}
I thought it would be more efficent to make one query of all comments, index them into an array by their id, and iterate over them again to find their children. I still dont know how to implement that?
Related
I am working on a MLM System, i want to get all childs & subchilds of any parent user. i tried use of recursion but failed. please help me to solve this.
public function searchAllDownline(Request $req){
$ids = array();
$req->validate(['search_keyword'=>'required']);
$search_keyword = $req->search_keyword;
$position = $req->position;
$user = User::where('username',$search_keyword)->first();
if(empty($user)){
return back()->with('error','Invalid username');
}
$query = User::where('parent_id',$user->id)->where('position',$position)->get();
foreach($query as $data){
$ids[] = $data->id;
}
$depth = User::where('name','!=','')->max('depth') - $user->depth - 2;
$this->recursion($ids,$position,$depth);
return view('admin.all-downline',compact('search_result','search_keyword','position'));
}
public function recursion($ids,$position,$depth){
$subquery = User::whereIn('parent_id',$ids)->where('position',$position)->get();
foreach($subquery as $subdata){
array_push($ids,$subdata->id);
}
while($depth-- != 0){
$this->recursion($ids,$position,$depth);
}
print_r(array_unique($ids));
}
Table structure:
There is a quite useful answer you can try below (can’t comment without enough rep…):
https://stackoverflow.com/a/26654139/19766732
It’s old but gold ;)
I am working on an online newspaper/blogging application with CodeIgniter 3.1.8 and Bootstrap 4.
At the bottom of the single post view, I want to add a link to the next post (as well as one to the previous post). For this, I need to get the data (slug, title, etc), of the next post (row in the posts table).
For this purpose, I have added this method to my Posts_model model:
/* Next post */
public function get_next_post($slug) {
$query = $this->db->get_where('posts', array('slug' => $slug));
if ($query->num_rows() > 0) {
$data = $query->next_row();
return $data;
}
}
In the controller I have:
public function post($slug) {
//more code
$data['post'] = $this->Posts_model->get_post($slug);
$data['next_post'] = $this->Posts_model->get_next_post($slug);
print_r($data['next_post']);
//more code
}
EDIT: In the Posts_model, I now have:
/* Next post */
public function get_next_post($slug) {
$query = $this->db->get('posts');
$row_index = 6;
$data = $query->row_array($row_index);
if ($query->num_rows() > 0) {
$data = $query->next_row();
return $data;
}
}
/* Prev post */
public function get_prev_post($slug) {
$query = $this->db->get('posts');
$row_index = 6;
$data = $query->row_array($row_index);
if ($query->num_rows() > 0) {
$data = $query->previous_row();
return $data;
}
}
That means that if I could get the current post's index by slug, I could replace this hardcoded index of the 7th post - $row_index = 6 - and the problem would be solved.
How do I do that?
// Your_model.php
...
public function getPost($slug) {
$this->db->where('slug', $slug);
return $this->db->get('posts_table')->row_array();
}
public function getPrevPost($currentPostId) {
$this->db->where('id <', $currentPostId);
$this->db->order_by('id', 'desc');
$this->db->limit(1);
return $this->db->get('posts_table')->row_array();
}
public function getNextPost($currentPostId) {
$this->db->where('id >', $currentPostId);
$this->db->limit(1);
return $this->db->get('posts_table')->row_array();
}
// Yourcontroller.php
...
public function getPost($slug) {
$post = $this->your_model->getPost($slug);
$data = [
'thePost' => $post,
...
'prevPost' => $this->your_model->getPrevPost($post['id']),
'nextPost' => $this->your_model->getNextPost($post['id']),
...
];
...
}
EDIT: this post answers the original question. In the meantime below code was used in an edit by OP.
you need to return a result of your query: $data = $query->row_array();
And get_where() is limiting the record-set to one record, hence there is no next record. You need to return the complete record-set with $this->db->get('posts'). In case you know the row_number (e.g.: 5) of the row containing $slug, you can point to it. The next_row shown, is row number 6.
public function get_next_post($slug) {
$query = $this->db->get('posts'); // querying the whole data-set
$data = $query->row_array(5); // the missing line
if ($query->num_rows() > 0) {
$data = $query->next_row();
return $data;
}
}
now you should get your next row (if exists), see Result Rows
I am trying to make a bootstrap slider with CodeIgniter, the slider images should be pulled from the database.
each post has a unique slider, so I have 2 database tables, one for the posts and the other for the slides.
the issue is I can't loop through the slides table to pull out the slides that assigned to the post.
I did a join tables between the posts and the slides table so I can get the associated slides, but the result is only loading one slide.
Model:
public function get_yachts($slug = FALSE){
if ($slug === FALSE) {
$query = $this->db->get('yachts');
return $query->result_array();
}
$this->db->join('yacht_slider', 'yacht_slider.yacht_slide_id = yachts.id');
$query = $this->db->get_where('yachts', array('slug' => $slug));
return $query->row_array();
}
Controller:
public function view($slug = NULL){
$data['yacht'] = $this->yacht_model->get_yachts($slug);
$data['title'] = 'Yachts';
$this->load->view('templates/header', $data);
$this->load->view('yachts/view', $data);
$this->load->view('templates/footer');
}
}
In my HTML code, when I try to load the slides like this <?php echo $yacht['slide'];?> I only get one row from slides table, so how can I loop to get the rest of the slides. I tried foreach loop and other methods, but none worked.
Hope this will help you :
Your model get_yachts should be like this :
public function get_yachts($slug = FALSE)
{
if ($slug === FALSE)
{
$query = $this->db->get('yachts');
return $query->result_array();
}
else
{
/*$this->db->select('yachts.title as ytitle');*/
$this->db->join('yacht_slider', 'yacht_slider.yacht_slide_id = yachts.id');
$query = $this->db->get_where('yachts', array('slug' => $slug));
return $query->result_array();
}
}
Controller will remain the same.
In view access $yacht like this:
this will work when slug is either empty or not empty
<?php
if (! empty($yacht))
{
foreach ($yacht as $key => $item) {
echo $item['slide'];
}
}
?>
I have to table article and table comment. In the home page I want to see how many comment for earch article.
Model
function show_latest_article($start,$display,$cate)
{
$query= $this->db->get_where('news_news', array('News_Cate_ID'=>$cate),$start,$display);
if($cate==0)
{
$query= $this->db->get_where('news_news',$start,$display);
}
return $query->result();
}
function count_comment($id)
{
$query = $this->db->get_where('comment',array('comment_article_id'=>$id) );
return $query->num_rows();
}
Controller
function index() {
$this->load->model('article');
$data=array('article'=>$this->article->show_latest_article(0,8,1),
'sidebar'=>$this->article->side_bar(9),
'count_comment'=> $this->article->count_comment($id),
);
$this->load->view('page/index',$data);
}
In the view I have this
foreach($article as $art)
{
echo $art->title."<br>";
$id= $art->id;
// I want to echo number of comment here.
// Or I want to call function count_comment($id)
}
$this->load->model('article');
$data['article'] = $this->article->show_latest_article(0, 8, 1);
$data['sidebar'] => $this->article->side_bar(9);
$data['count_comment'] => $this->article->count_comment($id);
$this->load->view('page/index', $data);
And it should work.
It's not so clear, where the $id variable come from, but I suggest to join the comments table to your article. It's not a best practice to make queries within loops.
In your model:
public function show_latest_article($ids = array())
{
return $this->db
->select('articles.*, COUNT(comments.id) as comment_count')
->where_in('articles.id', $ids) // You can skip this
->join('comments', 'comments.article_id = articles.id', 'left')
->group_by('articles.id')
->get('articles')
->result();
}
In your controller:
public function index()
{
$data['articles'] = $this->article->show_latest_article(array(0, 8, 1));
$this->load->view('page/index', $data);
}
Just change the field name according to database columns. Also you can skip the where_in condition. (I'm not sure what the three number stands for).
Then in your view, you can simply access the field:
$art->comment_count
EDIT: According to your comment:
$this->db
->select('a.*, (SELECT COUNT(*) FROM comment c WHERE c.comment_article_id = a.News_News_ID ) as counta')
->get('news_news')
->result();
I am writing this answer as you provided code. It could be more simpler if you give more database details. Try below code
function index() {
$this->load->model('article');
$articles = $this->article->show_latest_article(0,8,1);
foreach($articles as $article)
{
$article->comment_count = $this->article->count_comment($article->id);
$all_article[] = $article;
}
$data=array('article'=>$all_article,
'sidebar'=>$this->article->side_bar(9)
);
$this->load->view('page/index',$data);
}
On view
foreach($article as $art)
{
echo $art->title."<br>";
$id= $art->id;
echo $art->comment_count;
}
Controller :
function index() {
$this->load->model('article');
$articles = $this->article->show_latest_article(0,8,1);
$count_comments = Array();
for($i=0;$i<count($articles);$i++){
$count_comments[$i] = $this->article->count_comment($articles->$id);
}
$count_comments =
$data=array('article'=>$articles,
'sidebar'=>$this->article->side_bar(9),
'count_comment'=> $count_comments);
$this->load->view('page/index',$data);
}
In the View :
$i=0;
foreach($article as $art)
{
echo $art->title."<br>";
$id= $art->id;
echo $count_comment[$i];
$i++;
}
Data is passed from the controller to the view by way of an array or an object in the second parameter of the view loading function. Here is an example using an array:
$data = array(
'title' => 'My Title',
'heading' => 'My Heading',
'message' => 'My Message'
);
$this->load->view('blogview', $data);
Also below is the example for object
$data = new Someclass();
$this->load->view('blogview', $data);
PLEASE NOTE: Note: If you use an object, the class variables will be turned into array elements.
You can find out more from below ref URL
Ref: https://ellislab.com/codeigniter/user-guide/general/views.html
First of all in your controller you get count_comment only for specific article ID and not for all articles so you cant do foreach to display comment count of each article.
You need to setup you model better and in model function show_latest_article to use JOIN comments table and do count comment in query.
I will help you with query if you provide me more info about database table of article and comments.
SELECT
article.*,
COUNT(comment.id),0) AS numberOfCommments
FROM article
LEFT JOIN comment
ON comment.article_id = article.id
GROUP BY article.id
Hey guys !
Well I was trying out codeigniter but it seems to me that I have made some kind of mess while trying to retrieve and display the data from the tables
here is the code snippet.
I want to retrieve all the articles stored in my article table along with that I need to pull out all the tags associated with each article from the relationship table and the tag table called articleTagRelation and tags respectively
Table structure :
Article table : articleID, articleContent, date
Tags table : tagID, tagName
articleTagRelation : aricleID,tagID {Combination of both is my primary key}
CI model :
article_model.php
public function getAllTags($postId){
$this->db->select('articleTagRelation.tagId as tagId, articleTagRelation.postId as postId, article.tagName as tagName,');
$this->db->from('articleTagRelation');
$this->db->join('Tags','Tags.tagId = articleTagRelation.tagId');
$this->db->where('ArticleTagRelation.articleId',$postId);
$qTag = $this->db->get();
if($qTag->num_rows() > 0){
foreach ($qTag->result() as $tag) {
return $tag;
}
}
}
public function getAllArticles(){
$this->db->select('*');
$this->db->from('Article');
$this->db->order_by('date','desc');
$query=$this->db->get();
if($query->num_rows()>0){
foreach ($query->result() as $row) {
$data['row'] = $row;
$data['articletags'] = $this->getAllTags($row->articleId); // I'm trying to get get a array of all the associate tags.
$post=array($data['row'],$data['articletags']);
}
}else{
echo 'nothing found !';
}
return $post;
}
my controller file
article.php
I'm calling this function in the index function
$data['rows'] = $this->blog_model->getAllArticles();
and then loading the view by passing the data array
now the part where things get messy
in my view
echo $r->articleId // works fine
echo $r->articletags->tagId //gives me a error message
Can any one help me out in printing those tagIds
First you don't need the foreach at all to get the tag information, it comes back from a query_result.
like this...
if($qTag->num_rows() > 0){
return $qTag->result();
}
else {
return array(); //return empty array if no tags
}
Then to build your article, do this with getAllArticles()
public function getAllArticles(){
// removed uneccessary select and from
// the below accomplishes the same thing
$this->db->order_by('date','desc');
$query = $this->db->get('Article');
if ( $query->num_rows() > 0 ) {
// store the result in a variable you will end up returning
$articles = $query->result();
// make sure you foreach by reference so that changes you make
// to the interated $article will be made to the actual article
// result
foreach ($articles as &$article) {
// create a new property of your article "tags" and save an
// array of tags in it
$article->tags = $this->getAllTags( $article->articleId );
}
} else {
echo 'nothing found !';
}
return $articles;
}
The last thing to note is that when you now reference $r->tags that is an array, so you can foreach it to process all tags, OR reference an index like $r->tags[3]->tagId
if($qTag->num_rows() > 0){
foreach ($qTag->result() as $tag) {
$tags[] = $tag; //this create the array with the result
}
return $tags;
}
"$r->articletags->tagId" only works if you return results as an object, use "$r->articletags['tagId']" instead.