CodeIgniter Forums

Full Version: Forum topics pagination and posts anchors
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi, I am a new user of codeigniter (2 weeks) and this is my first post Smile

With CI3, i build a forum app.
A single topic shows posts that have posts.topic_id = topics.id
I want each posts on a single topic to have a permalink : I go to post #3 on topic-slug with this url: http://example.com/forum/forum-slug/topic-slug/#3
I have a problem with pagination and posts permalink.

My pagination looks like this (20 posts per page) :
http://example.com/forum/forum-slug/topic-slug/   --> first page
http://example.com/forum/forum-slug/topic-slug/20 --> second page
http://example.com/forum/forum-slug/topic-slug/40 --> third page

Posts permalinks are given to topic view with the $posts object.

How would I give each post a permalink depending on where it is in the pagination page number :
Post #5 would have permalink http://example.com/forum/forum-slug/topic-slug/#5
Post #25 (on the page 2 of pagination) would have permalink http://example.com/forum/forum-slug/topic-slug/20/#25
Post #45 (on page 3 of pagination) would have permalink http://example.com/forum/forum-slug/topic-slug/40/#45

I want it to be a dynamic attribution of posts permalinks, because if I want to change pagination $config['per_page'], I want all posts permalinks to change accordingly.
I am thinking of it, but I cannot find a good solution.


On my forum Controller, i have :

PHP Code:
public function topic($slug) {
    
    
// set basic variables
    
$slug       $this->uri->segment(30);
    
$forum_slug $this->uri->segment(20);
    
$topic_id   $this->forum_model->get_topic_id_from_topic_slug($slug);
    
    
// get topic object
    
$data['topic'] = $this->forum_model->get_topic($topic_id);
    
    
// pagination
    
$limit 15;
    
$this->load->library('pagination');
    
$config['base_url'       base_url() . 'forum/' $forum_slug '/' $slug '/';
    
$config['total_rows'     $this->forum_model->count_posts($topic_id);
    
$config['per_page'       $limit;
    
$config['uri_segment'    4;
    
$config['num_links'      2;
    
    
$this->pagination->initialize($config);
    
$page = ($this->uri->segment(4)) ? $this->uri->segment(4) : 0;
    
$data['pagination'] = $this->pagination->create_links();
    
    
// get all posts from this topic, limited by pagination
    
$posts $this->forum_model->get_post($topic_id$limit$page);
    
    
// loop through posts and create post objects
    
foreach ($posts as $post) {
        
        
$author_id $post->author_id;
        
$author    $this->user_model->get_user($author_id);
        
        
$data['posts'][] = (object)[
            
'id'          => $post->id,
            
'date'        => date("m-d-Y"strtotime($post->date)) . ' at ' date("H:i:s"strtotime($post->date)),
            
'content'     => $post->content,
            
'permalink'   => base_url() . 'forum/' $forum_slug '/' $slug '/#' $post->id// this is the post permalink with it anchor
            
'edit_link'   => base_url() . 'forum/' $forum_slug '/' $slug '/edit/#' $post->id,
            
'report_link' => base_url() . 'forum/' $forum_slug '/' $slug '/report/#' $post->id,
            
'author'      => (object)[
                
'id'        => $post->author_id,
                
'name'      => $this->user_model->get_username_from_user_id($post->author_id),
                
'avatar'    =>  base_url() . 'uploads/avatars/' $author->avatar,
                
'permalink' => base_url(). 'user/' $this->user_model->get_username_from_user_id($post->author_id),
                
'count_posts' => $this->forum_model->count_user_posts($post->author_id),
                
'count_topics' => $this->forum_model->count_user_topics($post->author_id)
            ]
        ];
        
    }
    
    
// load view and give it datas
    
$this->load->view('header'$data);
    
$this->load->view('forum/topic/topic_single'$data);
    
$this->load->view('footer');
        



on my single topic view :

PHP Code:
<?php foreach ($posts as $post) : ?>    
    <article class="col-md-12 post">
        <div class="row">
            <div class="col-xs-2 col-md-1 text-center">
                <p>
                    <img src="<?= $post->author->avatar ?>" alt="<?= $post->author->name ?>" class="img-circle" style="max-width: 100%; width: 100%;">
                    <small><a href="<?= $post->author->permalink ?>"><?= $post->author->name ?></a><br><?= $post->author->count_topics ?> topics<br><?= $post->author->count_posts ?> posts</small>
                </p>
            </div>
            <div class="col-xs-10 col-md-11">
                <div class="panel panel-default">
                    <div class="panel-body">
                        <header class="post-header">
                            <small><?= $post->date ?></small>
                            <!-- POST PERMALINK BELOW : -->
                            <small><a href="<?= $post->permalink ?>" id="<?= $post->id ?>" style="float: right">#<?= $post->id ?></a></small>
                        </header>
                        <div class="post-content">
                            <?= $post->content ?>
                        </div><!-- .post-content -->
                        <footer class="post-footer">
                            <a href=""><small>Report</small></a>
                            &middot;
                            <a href=""><small>Edit</small></a>
                        </footer>
                    </div><!-- .panel-body -->
                </div><!-- .panel -->
            </div>
        </div><!-- .row -->
    </article><!-- .post -->
<?php endforeach; ?>

<div class="bottom-pagination col-md-12">
    <?= $pagination ?>
</div> 
While I can see how you might end up trying to do something like this, I have to say that you probably shouldn't.


A perma-link implies that you're linking to a particular item permanently, regardless of what gets added afterwards and what might change on the server's configuration. If you're providing a perma-link to a post, the pagination shouldn't matter, and the topic probably shouldn't, either. At best, this implies something like: http://example.com/forum/forum-slug/post-slug or http://example.com/forum/form-slug/topic-slug/post-slug

The first post in a given topic is usually going to change over time (unless first is in terms of chronological order). You would usually use a perma-link to return to the same post, not to the newest (or 45th newest) post in a given topic.


Additionally, you should avoid using # in your URLs, especially at the end of the URL. The use of # implies that http://example.com/forum/forum-slug/topic-slug/#45 and http://example.com/forum/forum-slug/topic-slug/#5 point to different positions on the same page, rather than different pages. See URI Generic Syntax Components and URI Generic Syntax: Same-Document Reference. Of course, that may be your intent, in which case I may be confused (probably because I would expect something between the / and the #).
hi mwhitney and thank you for your answer,

I used the word permalink, maybe i used the wrong word, but i do want to give each post an identifier to be able to go to this specific post from a user profile page for example, or to be able to share a given post on social networks, etc...

It is a common to give a post on a forum an identifier, for example your post on this topic has the url http://forum.codeigniter.com/thread-1466...ml#pid6575
Even if your post was placed on second pagination page, it still would be accessible via this url (see threads on codeigniter forum that have many pages).
Also, note the "#" at the end of the url. this is what i want to do.

My question is how can i do that even if i am using codeigniter pagination.

I forgot my routes.php file when i posted this thread:
PHP Code:
// Forum controller
$route['forum/(:any)'] = 'forum/index/$1';
$route['forum/(:any)/new'] = 'forum/new_topic'// new topic
$route['forum/(:any)/(:any)'] = 'forum/topic/$2';
$route['forum/(:any)/(:any)/(:num)'] = 'forum/topic/$3'// topic pagination 
The word permalink was correct if you're looking to do the same thing done on this forum. Take a look at the URL you gave for my post:
http://forum.codeigniter.com/thread-1466...ml#pid6575

Now, this forum uses MyBB, but I'll break down the existing URL and give an example of how this might be done in CI:
MyBB: http://base_url/thread-{threadID}-post-{postID}.html#pid{postID}
CI:   http://base_url/thread/{threadID}/post/{postID}#pid{postID}

The paging of the forum is not mentioned in the URL for the post because it is not relevant. The page numbers are only referenced when you are viewing a list of threads or a paged list of responses to a post. For example, the following URL does not mention a page, even though the post it references is on the second page of a discussion:

http://forum.codeigniter.com/thread-1380...ml#pid6437

However, the following link may appear to take you to the same place:
http://forum.codeigniter.com/thread-1380-page-2.html

It references the page because the link is to the second page of the thread, not to the specific post.

[EDIT: If you change your options on the forum to display 20 posts per page (instead of the default 10), the first link will take you to the 11th post on the first page instead of the first post on the second page, while the second link will just take you to the first page, unless the thread gets up to 21 posts]

If you look at the code for the page you are currently viewing, you will find that there is a div with an id which matches the portion after the # in the URL (the easiest way to see this is to right-click on the header with the post author's information and select "Inspect Element", the div will be one of the divs surrounding the one which is selected in the inspector). This is what causes the page to focus on the post once the page is loaded. If I were to go to http://forum.codeigniter.com/thread-1380-post-6437.html (instead of http://forum.codeigniter.com/thread-1380...ml#pid6437 ) the page still loads properly, but the browser's focus is not moved to the top of the post.
I cannot imagine a way to make your example work : http://base_url/thread/{threadID}/post/{postID}#pid{postID}

This url is a topic url showing posts (and #xxx a specific post). But if there is a pagination on that page, and it sure will be a pagination because we don't want 100 posts per topic's page, the problem is still the same.

Sorry if i don't understand you but:

http://base_url/thread/{threadID}/post/{postID}#pid{postID}  (your example)

or

http://example.com/forum/forum-slug/topic-slug/#5  (my example)

they are quite equals, and the pagination will break the post targeting in both cases, no?
maybe i miss something...
(03-13-2015, 12:27 PM)hedi Wrote: [ -> ]I cannot imagine a way to make your example work : http://base_url/thread/{threadID}/post/{postID}#pid{postID}

This url is a topic url showing posts (and #xxx a specific post). But if there is a pagination on that page, and it sure will be a pagination because we don't want 100 posts per topic's page, the problem is still the same.

The controller should determine which page needs to be displayed to display the requested post based on the current settings for the pager. The page shouldn't need to be passed in the URL, because the only thing that matters is that the post is displayed. For example, if the post is the 21st post in that particular thread and the pager is setup for 20 posts per page, you would display the second page. However, if the pager is changed to display 25 posts per page, you would display the first page. Since you're linking to a post, you don't reference the paging in the URL, otherwise your "perma-links" are no longer valid when the paging changes.

Quote:Sorry if i don't understand you but:

http://base_url/thread/{threadID}/post/{postID}#pid{postID}  (your example)

or

http://example.com/forum/forum-slug/topic-slug/#5  (my example)

they are quite equals, and the pagination will break the post targeting in both cases, no?
maybe i miss something...

In my example, if postID is 5, the end of the URL is /post/5#pid5. The difference is that there is something between the last / and the #.

The post targeting might still work in your example, but it's dependent on the browser. The browser (or other tools used by the end-user) may not interpret the URL in your example properly, and it is possible that a link to http://example.com/forum/forum-slug/topic-slug/#35 would not work from the page displayed by going to http://example.com/forum/forum-slug/topic-slug/#5 (assuming the paging is setup for fewer than 30 posts per page), because the URL indicates that both posts are on the same page.