Phần tiếp theo của phần hướng dẫn website truyện tranh bằng CakePHP sẽ là các phần thay đổi footer, nav trong chi tiết truyện, các slider hiển thị.

Nav trang chi tiết truyện.

Truy cập thử vào 1 truyện demo ví dụ: http://doctruyen.local/chi-tiet/one_pice-1.html các bạn sẽ thấy giống như hình sau:

Screen Shot 2017-08-04 at 9.25.25 AMChúng ta sẽ tiến hành thay đổi phần hiển thị trong đây theo ý của chính mình. Đầu tiên mở file /app/View/Pages/detail_story.ctp và tìm đến thẻ div có 2 class là span3 col chúng ta sẽ tiến hành cắt bỏ phần này qua một file mới rồi dùng element để gọi lại nó, và khi muốn sử dụng nó ở đâu thì dùng element là được.

Tạo file /app/View/Elements/story/nav.ctp nội dung là thẻ div ở trên nếu các bạn làm giống mình thì nó là dòng 190-270 trong  /app/View/Pages/detail_story.ctp và thay thế nó bằng


<?php echo $this->element('story/nav');?>

Các bạn test bằng cách load lại page.

Bây giờ nội dung chúng ta cần là thực hiện nằm trong /app/View/Elements/story/nav.ctp, ở đây hiện tại  có 3 phần:  1 hiển thị menu truyện(cái này tương tự như cái menu nên mình không làm nữa), 2 hiển thị các truyện random, và 3 hiển thị các truyện được đọc nhiều nhất.

Random truyện:

Lấy dữ liệu random trong /app/Controller/StoriesController.php


public function randomstory(){
$dataStoryRandom = $this->Story->find('all', array(
'conditions'=>array('status=1'),
'order' => 'rand()',
'limit'=>8,
'recursive'=>-1
));
return $dataStoryRandom;
}

Và ở /app/View/Elements/story/nav.ctp chúng ta lấy dữ liệu của nó bằng


<?php $randomStorys = $this->requestAction('/stories/randomstory/');
?>

Tiến hành foreach dữ liệu:


<?php if(!empty($randomStorys)):?>
<?php foreach ($randomStorys as $key => $value):
if($key == 0){
$class_acvite = "active";
}else $class_acvite = "";
?>
<div class="<?php echo $class_acvite;?> item">
<ul class="thumbnails listing-products">
<li class="span3">
<div class="product-box">
<?php $image_name = $DataComponent->get_image(IMG_DIR . DS . STORIES_DIR . DS, $value['Story']['id'].'.jpg');?>
<?php
$img = $this->Html->image($image_name, array('alt'=>$value['Story']['name']));
echo $this->Html->link($img,
array(
'controller' => 'pages',
'action' => 'detail_story',
'id' => $value['Story']['id'],
'slug' => strtolower(Inflector::slug($value['Story']['name']))),
array('escape'=>false)
);
?>
<br/>
<?php
echo $this->Html->link($value['Story']['name'],
array(
'controller' => 'pages',
'action' => 'detail_story',
'id' => $value['Story']['id'],
'slug' => strtolower(Inflector::slug($value['Story']['name']))),
array('class'=> "title")
);
?>
<br/>
</div>
</li>
</ul>
</div>
<?php endforeach;?>
<?php endif;?>

Chạy lại page để xem kết quả.

Truyện đọc nhiều nhất:

Trong /app/Controller/StoriesController.php


public function readbeststory(){
$dataStoryRandom = $this->Story->find('all', array(
'conditions'=>array('status=1'),
'order' => array("view" => "DESC"),
'limit'=>3,
'recursive'=>-1
));
return $dataStoryRandom;
}

Và trong /app/View/Elements/story/nav.ctp chúng ta lấy dữ liệu


$readBestStorys = $this->requestAction('/stories/readbeststory/');

Hiển thị dữ liệu như sau:


<?php if(!empty($readBestStorys)):?>
<?php foreach ($readBestStorys as $key => $value):
?>
<li>
<?php $image_name = $DataComponent->get_image(IMG_DIR . DS . STORIES_DIR . DS, $value['Story']['id'].'.jpg');?>
<?php
$img = $this->Html->image($image_name, array('alt'=>$value['Story']['name']));
echo $this->Html->link($img,
array(
'controller' => 'pages',
'action' => 'detail_story',
'id' => $value['Story']['id'],
'slug' => strtolower(Inflector::slug($value['Story']['name']))),
array('escape'=>false, "title"=> $value['Story']['name'])
);
?>
<?php
echo $this->Html->link($value['Story']['name'],
array(
'controller' => 'pages',
'action' => 'detail_story',
'id' => $value['Story']['id'],
'slug' => strtolower(Inflector::slug($value['Story']['name']))),
array('class'=> "")
);
?>
</li>
<?php endforeach;?>
<?php endif?>

Đến đây thì đã xong phần nav trong trang chi tiết truyện, load lại pages để xem kết quả:

Screen Shot 2017-08-04 at 2.03.36 PM

Nội dung footer

việc chúng ta cần làm nằm ở file /app/View/Elements/story/footer.ctp

Đây là các liên kết trong trang web của bạn hoặc các trang web khác mà bạn muốn, hoặc menu cũng dc, thậm chí là một liên kết đến 1 trang truyện mà bạn yêu thích muốn để dưới footer để làm một liên kết nhanh, hoặc phần giới thiệu về website, thông tin liên hệ của bạn…

Demo đơn giản như sau:


<section id="footer-bar">
<div class="row">
<div class="span7">
<h4>Liên kết</h4>
<ul class="nav">
<li><a href="/">Trang chủ</a></li>
<li><a href="http://nongdanit.info">Nongdanit</a></li>
<li><a href="http://doctruyen.local/chi-tiet/one_pice-1.html/">Oncepice</a></li>
<li><a href="#">Liên hệ</a></li>
</ul>
</div>
<div class="span5">
<p class="logo">
<?php
echo $this->Html->image("../template_story/themes/images/logo.png", array('class'=> "site_logo",'alt'=>""));
?>
</p>
<p>Truyện tranh mới nhất, cập nhật nhanh nhất, các truyện hay nhất</p>
<br/>
</div>
</div>
</section>
<section id="copyright">
<span>Copyright 2017 truyentranhonline.com.vn.</span>
</section>
<?php
echo $this->Html->script(array(
'../template_story/themes/js/common.js',
));
?>

Đương nhiên các dữ liệu này chúng ta cũng có thể quản lý trong cơ sở dữ liệu rồi lấy ra hiển thị, nhưng hiện tại nó đơn giản nên chỉ cần làm trực tiếp trong file luôn. Phần liên kết Liên hệ các bạn tự phát triển nhá.

Slideshow hình ảnh hiển thị ở trang chủ:

Thiết kế 1 bảng dữ liệu có tên là slides như sau:

Screen Shot 2017-08-04 at 2.59.12 PM

Chúng ta sẽ quản lý trong admin:

Tạo file model /app/Model/Slide.php có nội dung:


<?php
class Slide extends AppModel {
var $name='Slide';
}

File /app/Controller/SlidesController.php:


<?php
class SlidesController extends AppController
{
var $layout = 'admin';
var $uses = array('Slide');
var $helpers = array('Session', 'Paginator');
var $paginate = array();
public function beforeFilter(){
parent::beforeFilter();
}
function admin_index(){
$this->paginate=array(
'order' =>array('id'=>'desc'),
'recursive' =>-1
);
$data = $this->paginate("Slide");
$this->set('data', $data);
}
function admin_add(){
$error = array();
if($this->request->is('post')){
$arrParams = $this->data['Slide'];//dữ liệu sau khi submit
if($arrParams['link']==null){
$error['link'] = 'Link ảnh không được rỗng';
}
if(empty($this->data['Slide']['image']['name'])){
$error['image'] = 'Vui lòng chọn ảnh';
}
if(!empty($this->data['Slide']['image']['name'])){
$file = $this->data['Slide']['image'];
$ext = substr(strtolower(strrchr($file['name'], '.')), 1);
$arr_ext = array('jpg', 'jpeg', 'gif', 'png');
if(in_array($ext, $arr_ext)){
$fla = 1;
}else{
$error['image'] = 'Hình ảnh chỉ có thể có định dạng là jpg, jpeg, gif';
}
}
if(empty($error)){
$arrParams['active'] = 1;
if($this->Slide->save($arrParams)){
if(!empty($fla)){
$file_name = $this->Slide->id.'.jpg';
move_uploaded_file($file['tmp_name'], WWW_ROOT . IMG_DIR .DS . SLIDE_DIR . DS . $file_name);
}
}
$this->Session->setFlash('Thêm thành công','default',array('class'=>"alert alert-success"));
$this->redirect(array('action' => 'index'));
}
$this->set("error", $error);
}
}

public function admin_edit($id){
$error = array();
$detail = $this->Slide->find('first', array(
'conditions'=>array('id = '.$id),
'recursive' =>-1
));
$this->set('detail', $detail);
if($this->request->is('post')){

$arrParams = $this->data['Slide'];//dữ liệu sau khi submit
if($arrParams['link']==null){
$error['link'] = 'Link ảnh không được rỗng';
}
if(!empty($this->data['Slide']['image']['name'])){
$file = $this->data['Slide']['image'];
$ext = substr(strtolower(strrchr($file['name'], '.')), 1);
$arr_ext = array('jpg', 'jpeg', 'gif', 'png');
if(in_array($ext, $arr_ext)){
$fla = 1;
}else{
$error['image'] = 'Hình ảnh chỉ có thể có định dạng là jpg, jpeg, gif';
}
}
if(empty($error)){
$arrParams['id'] = $id;
if($this->Slide->save($arrParams)){
if(!empty($fla)){
$file_name = $this->Slide->id.'.jpg';
move_uploaded_file($file['tmp_name'], WWW_ROOT . IMG_DIR .DS . SLIDE_DIR . DS . $file_name);
}
}
$this->Session->setFlash('Cập nhật thành công','default',array('class'=>"alert alert-success"));
$this->redirect(array('action' => 'index'));
}
$this->set("error", $error);
}
}
public function admin_delete($id = null){
if($this->request->is('get')){
$data = $this->Slide->find('first', array(
'conditions'=>array('id = '.$id)
));
if(!empty($data)){
$this->Slide->delete($id);
$file_name = $id.'.jpg';
@unlink(WWW_ROOT . IMG_DIR .DS . SLIDE_DIR . DS .$file_name);
$this->Session->setFlash('Success','default',array('class'=>"alert alert-success"));
}else{
$this->Session->setFlash('Error','default',array('class'=>"alert alert-success"));
}
$this->redirect(array('action'=>'list'));
}
}

}

Một thư mục chứa hình ảnh của slide trong app/webroot/img/slides/

Define các biến cho thư mục Slides trong /app/webroot/index.php


define('SLIDE_DIR', 'slides');

Cuối cùng cần tạo ra 3 file view: danh sách các slide, thêm, và cập nhật slide, nội dung 3 file này các bạn tham khảo trong phần download về.

Chú ý: nếu thực hiện trên server thì nhớ phần quyền thư mục Slides, để user có quyền đọc ghi nhá.

Tiếp theo là lấy dữ liệu của slide hiển thị ngoài trang chủ nhá.

Mở lại file /app/View/Pages/index.ctp. Đoạn html trong thẻ <section></section> đầu tiên là phần hiển thị slide của chúng ta, các bạn có thể đưa nó qua Elemment để sử dụng được nhiều chổ, còn ở đây mình chỉ làm ở trang chủ nên không cần làm việc đó.

Nội dung phần slide sau khi đổi như sau:


<?php if(!empty($dataSlide)):?>
<section class="homepage-slider" id="home-slider">
<div class="flexslider">
<ul class="slides">
<?php foreach ($dataSlide as $key => $value):?>
<li>
<a href="<?php echo $value["Slide"]["link"]?>">
<?php echo $this->Html->image(SLIDE_DIR . DS. $value['Slide']['id'].'.jpg', array('alt'=>$value['Slide']['link']));?>
</a>
</li>
<?php endforeach;?>
</ul>
</div>
</section>
<?php endif;?>

Vào file /app/Controller/PagesController.php phần action index, sẽ thêm đoạn lấy dữ liệu của Slide rồi đưa nó ra View. Đương nhiên cần thêm slide vào biến để sử dụng,  public $uses = array(“Story”,”Category”, “Chapter”, “Slide”);

Phần lấy dữ liệu như:


$dataSlide = $this->Slide->find('all', array(
'conditions'=>array('active=1'),
'order' => array('id' => 'desc'),
'limit'=>8,
'recursive'=>-1
));
$this->set('dataSlide', $dataSlide);

Tiến hành load lại trang chủ:

Screen Shot 2017-08-11 at 2.00.10 PM

Nội dung cơ bản của website truyện tranh bằng CakePHP đã hoàn tất. Cảm ơn các bạn đã cùng nongdanit.info đi đến bài này. Mình sẽ suy nghĩ cần việc gì thêm để hoàn thiện hơn về website này, hoặc nếu các bạn có yêu cầu cứ comment làm được mình sẽ hướng dẫn.

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 34 – Toàn tập website truyện tranh phần 11
Tagged on: