Vì có việc bận quá nên bài ra chậm quá, xin lỗi mọi người.

Ở bài trước chúng ta đã hiển thị menu và hiển thị các truyện ra ngoài trang chủ rồi. Ở bài này sẽ gắn các link để vào trang chi tiết của một truyện, vào trang liệt kê các truyện theo thể loại(menu) đương nhiên sẽ có phân trang (và mình sẽ sử dụng phân trang bằng ajax). Nếu bài dài quá có thể mình sẽ chia làm 2 bài

1. Link cho menu và phân trang trong CakePHP

Nói đến link thì phải làm sao cho chuẩn theo SEO thân thiện với  google, trong CakePHP chúng ta phải nhờ đến routes trong app/Config/routes.php.

Ví dụ một link vào menu của website như sau: http://doctruyen.local/the-loai/216ngon-tinh.html

Chúng ta sẽ dựa vào link trên để tạo ra một routes và sử dụng. Dưới là routes mà mình tạo ra được từ link trên.


Router::connect(
'/the-loai/:id-:slug.html/*',
array('controller' => 'pages', 'action' => 'view_genre'),
array(
'pass' => array('id', 'slug'),
"id"=>"[0-9]+", // chỉ là số,
)
);

Mình có tô màu cho các bạn dễ hình dung nhá. Dấu * cuối cùng trong link là dùng để phân trang nha.

Cái link này sẽ chạy vào /app/Controller/PagesController.php và action sẽ là view_genre() với 2 param là id và slug. Tạo action view_genre() trong PagesController.php nội dung như sau.


public function view_genre($id=null,$slug){
echo $id ; echo $slug;exit();
}

Chạy thử link http://doctruyen.local/the-loai/12-ngon-tinh.html, nó sẽ xuất hiện dòng chữ 12ngon-tinh nghĩa là các bạn làm đúng rồi.

Tiếp theo chúng ra gắn link như thế vào menu đã tạo nhá. Các bạn nhớ nó ở đâu chứ?

Vào /app/View/Elements/story/menu.ctp chúng ta sẽ sửa nội dung như sau:

Thay thế đoạn


<a href="#"><?php echo $value['Category']['name'];?></a>

thành


<?php
echo $this->Html->link($value['Category']['name'],
array(
'controller' => 'pages',
'action' => 'view_genre',
'id' => $value['Category']['id'],
'slug' => strtolower(Inflector::slug($value['Category']['name']))),
array('class'=> "")
);
?>

Việc sử dụng Inflector mình đã hướng dẫn ở bài trước các bạn xem lại nhá

Save lại và chạy lại website, rồi click vào các menu sẽ thấy xuất hiện id và tên của menu.

Bây giờ suy nghĩ xem khi click vào các menu thể loại chúng ta sẽ cho hiển thị ra những gì?

Đương nhiên là các truyện thuộc thể loại đó rùi.

Chúng ta sẽ sử dụng /app/webroot/template_story/products.html làm view cho trang này. Tạo file /app/View/Pages/view_genre.ctp với nội dung lấy từ dòng 76-255 trong file /app/webroot/template_story/products.html

Bỏ đoạn echo $id ;  echo $slug;exit(); trong /app/Controller/PagesController.php sau đó chạy lại link vào một menu http://doctruyen.local/the-loai/1-ecchi.html

Kết quả như sau là thành công:

Screen Shot 2017-06-30 at 11.43.46 AM

Việc tiếp theo sẽ là lấy dữ liệu rồi đưa ra ngoài view để hiển thị lên.


$dataGenre = $this->Category->find('first', array(
'fields' => array('id', 'name','parent_id','description'),
'conditions'=>array('id = '.$id),
'recursive' =>-1
));

$data["dataGenre"] = $dataGenre;

Trên chính là lấy dữ liệu của menu được lựa chọn. Có sử dụng đến model Category nên khai báo vào biến public $uses = array(“Story”,”Category”); Tiếp theo là các truyện thuộc thể loại được chọn.


$this->paginate = array(
'fields' => array('id', 'name','updated','view'),
'conditions' => array('status' => 1,'category_id' =>$id),
'limit'=>9,
'order' => array('id' => 'desc'),
'recursive'=>-1
);
$dataStory = $this->paginate("Story");

$data["dataStory"] = $dataStory;

Cả 2 mảng dữ liệu trên chúng ta sẽ đưa ra view:


$this->set('data', $data);

Việc hiển thị dữ liệu ngoài view các bạn xem trong source nhá.

Mình xin nói đến phần phân trang, ở đây mình xin giới thiệu các bạn phân trang bằng ajax.

Việc đầu tiên chúng ta hãy bao lại tất cả nội dung trong file /app/View/Pages/view_genre.ctp bằng một thẻ div có id là resultsDiv. Việc phân trang cần thêm các khai báo của helper public $helpers = array(‘Js’,’Paginator’,’Html’); và public $components = array(‘RequestHandler’, ‘Data’); trong PagesController.php

Ở view_genre.ctp có đoạn


<?php
// Paginator options
$this->Paginator->options(array(
"update" => "#resultsDiv",
"before" => $this->Js->get("#spinner")->effect("fadeIn", array("buffer" => false)),
"complete" => '$("html, body").animate({scrollTop: 0}, "slow");',
'evalScripts' => true,
));
?>

đây là đoạn dùng để phân trang ajax trong CakePHP, các options trong nó là mảng, với param update là id chúng ta thêm ở trên, param beforecomplete là dùng để thực hiện trước và sau khi nhấn phân trang, ở đây mình làm là load lên 1 tấm ảnh loading.gif sau khi xong thì ẩn đi là di chuyển màn hình lên top của trang.

Cuối cùng là đoạn hiển thị số page các trang.


<div class="pagination pagination-small pagination-centered">
<div id="spinner" style="display: none;">
<?php echo $this->Html->image("loading.gif", array("id" => "busy-indicator")); ?>
</div>
<?php if($this->Paginator->param('count') > 6):?>
<?php
$this->Paginator->options(array('url' => array('id'=>$data["dataGenre"]["Category"]["id"],'slug' => strtolower(Inflector::slug($data["dataGenre"]["Category"]["name"])))));
?>
<?php echo $this->Paginator->prev("Prev"); ?>
<?php echo $this->Paginator->numbers(array("separator"=>" ")); ?>
<?php echo $this->Paginator->next("Next"); ?>
<?php endif;?>
<?php echo $this->Js->writeBuffer();?>
</div>

Vị trí hiển thị tấm ảnh loading mình để ở đây luôn, các bạn có thể thay đổi tuỳ ý, mình kiểm tra nếu số record nó lớn hơn 6 mới hiển thị phân trang. Phần hiển thị này tuỳ các bạn muốn nó hiển thị những gì, của mình chỉ cần các nút Prev Next và các nút number. Đoạn cuối cùng <?php echo $this->Js->writeBuffer();?> rất quan trọng phải để vào mới được nhá, còn lý do thì CakePHP JsHelper nó bảo thế.(^^).

Việc phân trang mình hướng dẫn đến đây thui, việc chỉnh sau cho đẹp các bạn tự làm nha. Các bạn chạy lên và test sẽ thấy được kết quả, nếu có lỗi có thể comment bên dưới mình sẽ hỗ trợ.

2. Link vào trang chi tiết 1 truyện

Quay lại trang chủ, việc làm tiếp theo là click vào một truyện trên trang sẽ chạy vào page chi tiết.

Cũng tương tự như trên đầu tiên ta tạo một routes.


Router::connect(
'chi-tiet/:slug-:id.html',
array('controller' => 'pages', 'action' => 'detail_story'),
array(
'pass' => array('slug', 'id'),
"id"=>"[0-9]+", // chỉ là số
)
);

Theo router trên, thì trong controller /app/Controler/PagesControler.php ta tạo thêm action detail_story() nội dung cũng đơn giản để test thử xem có đúng không.


echo $id.$slug; exit;

Tiếp theo chạy thử link. http://doctruyen.local/chi-tiet/one-piece-1.html các bạn thấy xuất hiện 1one-piece

OK, bây giờ chúng ta tạo file view /app/View/Pages/detail_story.ctp với nội dung là dòng 79-310 trong /app/webroot/template_story/product_detail.html

Sau đó ẩn đi dòng echo $id.$slug; exit; trong action detail_story() và chạy lại link http://doctruyen.local/chi-tiet/one-piece-1.html, sẽ được như hình bên dưới

Screen Shot 2017-06-30 at 4.58.06 PM

Bài này mình xin đến đây thui, phần tiếp theo sẽ là hiển thị các thông tin cũng như những thứ cần thiết còn sót lại trong trang chi tiết truyện.

Hy vọng các bạn cùng theo dõi với nongdanit

Kết luận

  1. Nếu có thắc mắc gì các bạn để lại comment bên dưới mình sẽ trả lời sớm nhất có thể.
  2. Cảm ơn các bạn đã đọc.

Nongdanit.info
[Cakephp] Bài 31 – Toàn tập website truyện tranh phần 10.1
Tagged on: