mohamedhamidi's avatar

Split a page into multiple pages using pagination

I am making a blog , in the blog.show.blade view sometimes the body is too long and want to divide it into parts and add 'previous' , 'next' buttons , but the problem is that the body is stored all in one column in database so how can i paginate it ?

show.blade.php (the article show view) :

    @if($post->image_url)
    <div class="post-image">
      <img class="mb-5" src="{{ $post->image_url }}" alt="{{ $post->slug }}">
    </div>
    @endif

    <div class="post-title">
      <h1 class="mb-4" >{{ $post->title }}</h1>
    </div>


  <div class="post-body mb-5">
    {!! $post->body_html !!}
  </div>
  </div>
</div>
0 likes
14 replies
mohamedhamidi's avatar

Of course i read the documentation 4 times before asking here , you didn't get my question, usual pagination is used when retrieving data from multiple rows in database , but what i want to paginate is the body which is only one instance but sometimes it is too long to display in one page

mohamedhamidi's avatar

What i want to paginate is the body_html , sometimes it's too long to show in single page , also it's better SEO practice to split articles into 3 pages. The problem is that the body is only one entity retrieved to the view , not multiples bodies

MichalOravec's avatar

Use strip_tags and then strlen to get length of text, then split it if it's necessary, but it will be maybe problem because you have there a html. And if you have splitted create link to another page of that content and shot it there.

1 like
Snapey's avatar
Snapey
Best Answer
Level 122

Easier if you are ok to put something indicating page break in your post

Then you know where to split it.

Otherwise, you have to read so many characters and then find the next parent element (eg a <div>). Take the first part and count how many characters where in the first part. If you don't split it on a parent element then the html will be broken on page 2

Output the first part to the view

Have a link to part 2, when you get the part 2 route, read the contents again and discard everything up to the previous character count. then repeat incase you need page 3...

Not simple at all.

1 like
Tray2's avatar

In your case I would use markdown for the blogposts then you can use something like this to find your page breaks.

<div style="page-break-after: always"></div>
Snapey's avatar

Frankly, sometimes I wonder why I bother...

mohamedhamidi's avatar

Following your instructions i finally got the final solution , thanks man and sorry :D

post show function in Controller :

public function show(Post $post)
{
	
  $items = array();

  // split whole body into 2000 characters each parts

  $bodyParts = str_split($post->body, 2000);

  // iterate through the parts and fill the array

  foreach($bodyParts as $bodyPart)
  {
    array_push($items, $bodyPart);
  }

 // get current page for Paginator
  $currentPage = LengthAwarePaginator::resolveCurrentPage();
 // indicate number of parts to show per page
  $perPage = 1;

  $currentItems = array_slice($items, $perPage * ($currentPage - 1), $perPage);

  $paginator = new LengthAwarePaginator($currentItems, count($items), $perPage, $currentPage);

  $results = $paginator->appends('filter', request('filter'));

  $results->withPath($post->slug);


return view('blog.show', compact('post','results'));

}

And then in the show view :

  <div class="post-body mb-5">
    @foreach($results as $part)
      <p>{!! nl2br($part) !!}</p>
    @endforeach
{!! $results->links() !!}
  </div>
Snapey's avatar

a) You don't care about valid html? Your post is only plain text?

b) You don't care about XSS attacks, your post could contain script tags and you just output them RAW to the view?

mohamedhamidi's avatar

a) The body output in browser is html in paragraph tag and could style it with css

b) I post articles from admin panel , it's the owner of the website who's authorized to post articles and apparently wouldn't inject script tags

Snapey's avatar

a) The body output in browser is html in paragraph tag and could style it with css

so, your split at 2000 characters could be mid paragraph?

<p>This is my super long article which has <strong>even</strong> some html tags mid paragraph</p>

split might be;

Page 1

<p>This is my super long article which has <strong>ev

Page 2

en</strong> some html tags mid paragraph</p>

so your formatting breaks on both pages. This could be worse if your post contains tables, links etc

mohamedhamidi's avatar

That's what i am actually working on right now , if you got some ideas about the logic behind to fix that, your help would be appreciated

MichalOravec's avatar

Create a new table where you will store body or bodies of your post, it will be one to many relationship. Then you can easily paginate it. And in your admin just make logic to add new "page" of your post.

1 like
Snapey's avatar

Easier if you are ok to put something indicating page break in your post

so if in your post you entered something that represented a page break then you could find it, remove it, and split the post at that point.

eg ==break here==

You just need to look if your editor would wrap this in <div> or <p> and then include that in your search/replace.

1 like
mohamedhamidi's avatar

That worked like charm , i edited the code like that and it worked , thank you so much @snapey

Old code :

// Code

$bodyParts = str_split($post->body, 2000);

//Code

Better solution :

// Code

$bodyParts = explode("==break here==", $post->body);

//Code
1 like

Please or to participate in this conversation.