Ngu ngơ học làm web (x26) - CakePHP2 - Xem, cập nhật giỏ hàng

Tiếp theo của: Ngu ngơ học làm web (x25) - CakePHP2 – Tính tiền giỏ hàng, component
-----

Phần x26. CakePHP2 – Xem, cập nhật giỏ hàng


Xem (clip số 27b – chickenrainshop):

- set->(compact()) - gửi nhiều biến lên view (2":56)

- sử dụng layout khác thay thế cho layout default (10":10) 

Đoạn mã cho nút “Xem/Cập nhật giỏ hàng”:

Element [cart.ctp]

<p class="pricetotal"><span class="label">Tổng: <?php echo $this->Number->currency($total,
                                                ' VND', ['places' => 0, 'wholePosition' => 'after']); ?></span></p>
<?php echo $this->Html->link('Xem/Cập nhật giỏ hàng', '/gio-hang', ['class' => 'update-cart btn btn-primary btn-block']); ?>
<?php else: ?>

Vì giao diện bị bể, nên sẽ css một chút.

[chickenrainshop.css]

.update-cart {
    width: 200px;
    text-align: center;
    margin: 0 auto;
    margin-top: 40px;
}

Cấu hình route cho link $this->Html->link('Xem/Cập nhật giỏ hàng', '/gio-hang'):

[routes.php]

Router::connect('/sach-moi', ['controller' => 'books', 'action' => 'latest_books']);
Router::connect('/gio-hang', ['controller' => 'books', 'action' => 'viewCart']);
Router::connect('/tac-gia', ['controller' => 'writers', 'action' => 'index']);

Viết action viewCart trong [BooksController.php]

/*
* xem chi tiết giỏ hàng
*/
            public function viewCart() {
                        $cart = $this->Session->read('cart');
                        $payment = $this->Session->read('payment');
                        $this->set(compact('cart', 'payment'));
                        $this->set('title_for_layout', 'Giỏ hàng');
            }
           
            public function addToCart($id = null) {

Để gửi nhiều hơn một biến lên view, sử dụng hàm compact, ví dụ:

$this->set(compact('cart', 'payment'));

Viết view view_cart: do view view_cart sử dụng layout khác so với layout default, vì vậy cần phải tạo layout trước (layout cart.ctp).

Tạo layout mới, có tên là cart.ctp.

[Layouts\cart.ctp]

<!DOCTYPE html>
<html>
<head>
            <?php echo $this->Html->charset(); ?>
            <title>
                        <?php echo $title_for_layout; ?>
            </title>
            <?php
                        echo $this->Html->meta('icon');
                        echo $this->Html->css('bootstrap.min');
                        echo $this->Html->css('chickenrainshop');
                        echo $this->fetch('meta');
                        echo $this->fetch('css');
                        echo $this->fetch('script');
            ?>
</head>
<body>
            <div id="container" class="container">
                        <div id="header">
                                    <nav class="navbar navbar-default">
                                                <div class="navbar-header">
                                                            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#mainmenu">
                                                <span class="sr-only">Toggle navigation</span>
                                                <span class="icon-bar"></span>
                                                <span class="icon-bar"></span>
                                                <span class="icon-bar"></span>
                                    </button>
                                    <a href="#" class="navbar-brand">Chickenrainshop</a>
                        </div>
                        <div class="navbar-collapse collapse" id="mainmenu">
                                    <ul class="nav navbar-nav">
                                    <li class="active"><?php echo $this->Html->link('Sách mới', '/sach-moi') ?></li>
                                    <li><a href="#ban-chay">Sách bán chạy</a></li>
                                    <li><a href="#lien-he">Liên hệ</a></li>
                                    </ul>
                                    <ul class="nav navbar-nav pull-right">
                                                <?php
                                                            echo $this->Form->create('Book', [
                                                                        'url' => ['action' => 'get_keyword'],
                                                                        'class' => 'navbar-form search'
                                                                        ]);
                                                            echo $this->Form->input('keyword',[
                                                                        'label' => '',
                                                                        'style' => 'width: 200px',
                                                                        'placeholder' => 'Tìm kiếm...'
                                                                        ]);
                                                            echo $this->Form->end();
                                                ?>

                                    </ul>
                        </div>
                                    </nav>
                        </div><!-- #header -->
                        <div id="content">
                                    <div class="row">
                                                <div class="content col col-lg-12">
                                                            <?php echo $this->fetch('content'); ?>
                                                </div><!-- content -->
                                    </div>
                        </div>
                        <div id="footer">
                                    <div class="container">
                                                <p class="text-muted pull-right">Học CakePHP2</p>
                                    </div>
                        </div>
            </div>
            <?php echo $this->Html->script('jquery'); ?>
            <?php echo $this->Html->script('bootstrap.min'); ?>
</body>
</html>

Để sử dụng layout cart vừa tạo ở trên, trong [BooksController.php action viewCart()] thêm dòng lệnh $this->layout= ‘cart’;

Ví dụ:

public function viewCart() {
                        $this->layout = 'cart';
                        $cart = $this->Session->read('cart');

[View\Books\view_cart.ctp]

<?php if ($this->Session->check('cart')): ?>
            <div class="panel">
                        <h4 class="panel-heading"><span class="glyphicon glyphicon-shopping-cart"></span>Giỏ hàng của bạn</h4>
                        <div class="row">
                                    <div class="chi-tiet-gio-hang">
                                                <table class="table table-striped">
                                                            <thead>
                                                                        <tr>
                                                                                    <th>STT</th>
                                                                                    <th>Tên sách</th>
                                                                                    <th>Số lượng</th>
                                                                                    <th>Giá</th>
                                                                                    <th>Xóa</th>
                                                                        </tr>
                                                            </thead>
                                                            <tbody>
                                                                        <?php $i = 1; ?>
                                                                        <?php foreach ($cart as $book): ?>
                                                                                    <tr>
                                                                                                <td><?php echo $i++; ?></td>
                                                                                                <td><?php echo $this->Html->link($book['title'], '/'.$book['slug']); ?></td>
                                                                                                <td class='row'>
                                                                                                <?php echo $this->Form->create('Book', ['class' => 'form-inline']) ?>
                                                                                                            <?php echo $this->Form->input('quantity', ['value' => $book['quantity'], 'class' => 'col col-lg-2', 'label' => false, 'div' => false]); ?>
                                                                                                            <?php echo $this->Form->button('Cập nhật', ['class' => 'btn btn-link', 'type' => 'submit']); ?>
                                                                                                <?php echo $this->Form->end(); ?>
                                                                                                </td>
                                                                                                <td><?php echo $this->Number->currency($book['sale_price'],' VND',['places' => 0,'wholePosition' => 'after']); ?>
                                                                                                </td>
                                                                                                <td><a href="#"><span class="glyphicon glyphicon-remove"></span></a></td>
                                                                                    </tr>
                                                                        <?php endforeach ?>
                                                                        <tr>
                                                                                    <td></td>
                                                                                    <td colspan="2"><strong>Tổng cộng</strong></td>
                                                                                    <td colspan="2"><strong><?php echo $this->Number->currency($payment['total'],' VND',['places' => 0,'wholePosition' => 'after']); ?></strong></td>
                                                                        </tr>
                                                                        <tr>
                                                                                    <td></td>
                                                                                    <td colspan="2"><strong>Đã giảm <small>(Coupon: CAKEPHP - giảm 10%)</small></strong></td>
                                                                                    <td colspan="2"><strong>0 VND</strong></td>
                                                                        </tr>
                                                                        <tr class="success">
                                                                                    <td></td>
                                                                                    <td colspan="2"><h4><strong>Giá phải trả</strong></h4></td>
                                                                                    <td colspan="2"><h4><span class="label label-danger"><?php echo $this->Number->currency($payment['total'],' VND',['places' => 0,'wholePosition' => 'after']); ?></span></h4></td>
                                                                        </tr>
                                                            </tbody>
                                                </table>
                                    </div>
                                    <button type="submit" class="col-lg-3 btn btn-default empty">Làm rỗng giỏ hàng</button>
                        </div>
            </div>

<?php else: ?>
            <div class="panel">
                        Giỏ hàng đang rỗng.
                        Quay về <?php echo $this->Html->link('trang chủ', '/'); ?> để thêm quyển sách vào giỏ hàng.
            </div>
<?php endif ?>

Thêm đoạn mã sau vào chickenrainshop.css:

.chi-tiet-gio-hang {
    width: 800px;
    margin: 0 auto;
}

.empty {
    margin-left: 30px;
    background: #C0C0C0;
    color: #FFF;

}
-----------
Cập nhật 31/5/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web

Ngu ngơ học làm web (x25) - CakePHP2 - Tính tiền giỏ hàng, component

Tiếp theo của: Ngu ngơ học làm web (x24) - CakePHP2 – Session, postLink, giỏ hàng
-----

Phần x25. CakePHP2 – Tính tiền giỏ hàng, component


Xem (clip số 27a – chickenrainshop):

- Number->currency() định dạng xuất tiền (4":49)

- Tính tổng tiền của giỏ hàng bằng biến session (10":52)

- Khai báo hàm trong AppController để có thể gọi trong mọi controller(13":04)

- Khai báo hàm trong component để có thể gọi trong mọi project (14":00)

- set->(compact()) - gửi nhiều biến lên view (2":56)

Để tính tiền trong giỏ hàng:

- Đọc giỏ hàng từ Session

- Duyệt từng cuốn sách trong giỏ hàng, cộng tiền của từng cuốn

- Lưu lại tổng tiền vào Session

- Bên view, đọc Session và hiển thị lên view

Đoạn mã ví dụ:

[trong controller]

$cart = $this->Session->read('cart');
            $total = $this->sum($cart);
            $this->Session->write('payment.total', $total);

public function sum($cart) {
                        $total = 0;
                                    foreach ($cart as $book) {
                                                $total += $book['sale_price'] * $book['quantity'];
                                    }
                        return $total;
            }

[trong view]

<?php $total = $this->Session->read('payment.total'); ?>
<p class="pricetotal"><span class="label">Tổng: <?php echo $this->Number->currency($total,
                                                ' VND', ['places' => 0, 'wholePosition' => 'after']); ?></span></p>

Một số tùy chọn về phạm vi của một hàm trong controller:

- Hàm kiểu private, đặt trong một controller: phạm vi sử dụng trong chính controller

- Hàm kiểu public, đặt trong AppController: phạm vi sử dụng trong mọi controller của một project

- Đặt hàm trong một component: phạm vi sử dụng trong nhiều project

Ví dụ, sử dụng component:

- Tạo một component trong thư mục Controller\Component, ví dụ, component có tên là Tool thì tên của tập tin (theo quy ước) sẽ là ToolComponent.php

- Trong ToolComponent, định nghĩa các hàm, ví dụ:

<?php
            class ToolComponent extends Component {
                        public function sum($cart) {
                                    $total = 0;
                                                foreach ($cart as $book) {
                                                            $total += $book['sale_price'] * $book['quantity'];
                                                }
                                    return $total;
                        }
            }
?>

- Muốn sử dụng component, cần khai báo trong controller, ví dụ:

class AppController extends Controller {
            public $components = ['Tool'];
}

- Cú pháp gọi một hàm trong component, ví dụ:

$total = $this->Tool->sum($cart);

Có thể viết lại hàm sum cho tối ưu hơn:

<?php
            class ToolComponent extends Component {
                        public function arraySum($cart, $quantity_col = 'quantity', $price_col = 'price') {
                                    $total = 0;
                                                foreach ($cart as $item) {
                                                            $total += $item[$price_col] * $item[$quantity_col];
                                                }
                                    return $total;
                        }
            }
?>

Khi gọi ra sử dụng sẽ là, ví dụ:

$total = $this->Tool->arraySum($cart, 'quantity', 'sale_price');

[Element cart.ctp để hiển thị thông tin giỏ hàng]

<?php echo $this->Flash->render('cart'); ?>
<?php if($this->Session->check('cart')): ?>
<?php $cart = $this->Session->read('cart'); ?>
            <ul>
            <?php foreach ($cart as $book): ?>
                        <li>
                                    <?php echo $this->Html->link($book['title'], '/'.$book['slug']); ?>
                                    (<?php echo $this->Number->currency($book['sale_price'],
                                                ' VND', ['places' => 0, 'wholePosition' => 'after']); ?>)
                        </li>
            <?php endforeach ?>
            </ul>
            <?php $total = $this->Session->read('payment.total'); ?>
            <p class="pricetotal"><span class="label">Tổng: <?php echo $this->Number->currency($total,
                                                ' VND', ['places' => 0, 'wholePosition' => 'after']); ?></span></p>
            <button type="button" class="btn btn-primary btn-block">Xem/Cập nhật giỏ hàng</button>
<?php else: ?>
            Giỏ hàng đang rỗng!

<?php endif ?>
-----------
Cập nhật 30/5/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web

Ngu ngơ học làm web (x24) - CakePHP2 - Session, postLink, giỏ hàng

Tiếp theo của: Ngu ngơ học làm web (x23) - CakePHP2 – Link hình ảnh, Flash, Load theo vị trí
-----

Phần x24. CakePHP2 – Session, postLink, giỏ hàng


Xem (clip số 25 – chickenrainshop):

Trong CakePHP, có thể thao tác với session ở controller và view.

Controlller
View
Session component
Session helper
- check(): kiểm tra sự tồn tại của một session
- read(): đọc nội dung của một session
- write(): tạo mới hoặc chỉnh sửa nội dung của một session
- setFlash(), hoặc Flash->set(): gửi thông báo lên view
- delete(): xóa một session cụ thể
- destroy(): xóa tất cả các session đã tạo ra
Kiểm tra và hiển thị dữ liệu session đã được xử lý ở controller.
- check(): kiểm tra sự tồn tại của một session
- read(): đọc nội dung của một session
- flash() hoặc Flash->render(): hiển thị thông tin session đã được thiết lập trong hàm setFlash(), hoặc Flash->set()


Có hai loại session:

- Session thông thường: được lưu dưới dạng một cái tên, ví dụ A, có thể lưu vào A dữ liệu có kiểu bất kì như: kiểu số, chuỗi hoặc mảng.

- Session dạng mảng: một session sẽ có cấu trúc là một mảng, ví dụ B, để lấy giá trị: sử dụng B.key-1, B.key-2,…

Xem (clip số 26 – chickenrainshop):

- postLink - tạo một link giống một button (2":09)

- session->setFlash() - lưu thông báo xuống session(12":30)

postLink để tạo một link, khi người dùng bấm vào link, trình duyệt sẽ gửi một request dạng post về server. Ví dụ,

<?php echo $this->Form->postLink(
// nội dung hiển thị
            '<span class="glyphicon glyphicon-shopping-cart"></span> Thêm vào giỏ hàng',
            // URL và các tham số
            ['action' => 'addToCart', $book['Book']['id']],
            // thông tin tùy chọn
            ['class' => 'btn btn-primary', 'escape' => false]);
?>

Mục đích của tham số escape=>false là để trình duyệt xuất nội dung của phần '<span class="glyphicon glyphicon-shopping-cart"></span> Thêm vào giỏ hàng', ra màn hình chứ không xuất nguyên mã HTML.

Tạo giỏ hàng là tạo một mảng để lưu các sản phẩm, ví dụ:

- Tạo một sản phẩm với các thông tin đi kèm:

$item = [
                                                'id' => $book['Book']['id'],
                                                'title' => $book['Book']['title'],
                                                'slug' => $book['Book']['slug'],
                                                'sale_price' => $book['Book']['sale_price'],
                                                'quantity' => 1
                                    ];

- Lưu sản phẩm vào session kiểu mảng có tên là cart, tại vị trí cart.id:

$this->Session->write('cart.'.$id, $item);

- Thiết lập nội dung thông báo để hiển thị lên view:

$this->Flash->success('Đã thêm quyển sách vào trong giỏ hàng!', [
                                                'params' => [
                                                            'class' => 'alert alert-info'
                                                ]]);

- Lưu ý là sau khi CakePHP thực hiện xong action, nó luôn gửi kết quả tới view tương ứng, vì vậy nếu không có view, nó sẽ báo lỗi. Ở đây không tạo view addToCart, nên sẽ gửi kết quả lên view view.ctp.

$this->redirect($this->referer()); // chuyển hướng về chính cái trang đã gọi action

Khi thiết lập nội dung thông báo để hiển thị lên view, nên đặt tên cho mỗi thông báo để hiển thị chính xác thông báo đó, ví dụ:

[trong controller]

$this->Flash->success('Đã thêm quyển sách vào trong giỏ hàng!', [
                                                'key' => 'cart',
                                                'params' => [
                                                            'class' => 'alert alert-info'
                                                ]]);

[trong view]

<?php echo $this->Flash->render('cart'); ?>

[Controller\BooksController.php action addToCart()]

public function addToCart($id = null) {
                        if ($this->request->is('post')) {
                                    // tìm thông tin về sản phẩm
                                    $book = $this->Book->find('first', [
                                                'recursive' => -1,
                                                'conditions' => ['Book.id' => $id]
                                                ]);
                                    if ($this->Session->check('cart.'.$id)) {
                                                $item = $this->Session->read('cart.'.$id);
                                                $item['quantity'] += 1;
                                    } else {
                                                $item = [
                                                'id' => $book['Book']['id'],
                                                'title' => $book['Book']['title'],
                                                'slug' => $book['Book']['slug'],
                                                'sale_price' => $book['Book']['sale_price'],
                                                'quantity' => 1
                                                ];
                                    }
                                    // tạo giỏ hàng và thêm sản phẩm vào giỏ hàng
                                    $this->Session->write('cart.'.$id, $item);
                                    $this->Flash->success('Đã thêm quyển sách vào trong giỏ hàng!', [
                                                'key' => 'cart',
                                                'params' => [
                                                            'class' => 'alert alert-info'
                                                ]]);
                                    $this->redirect($this->referer());
                        }

            }
-----------
Cập nhật 30/5/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web

Ngu ngơ học làm web (x23) - CakePHP2 - Link hình ảnh, Flash, Load theo vị trí

Tiếp theo của: Ngu ngơ học làm web (x22) - CakePHP2 – Chức năng tìm kiếm
-----

Phần 23. CakePHP2 – Link hình ảnh, Flash, Load theo vị trí


Xem (clip số 24e – chickenrainshop):

- Tạo link hình ảnh bằng helper (2":35)

- Gửi thông báo: thành công, thất bại (20":00)

- Cho trang web load lại đúng vị trí mình đã gửi comment (21":29)

Tạo một link bằng hình ảnh, sử dụng Html helper, ví dụ:

<?php echo $this->Html->link($this->Html->image($book['Book']['image']), '/'.$book['Book']['slug']); ?>

Tuy nhiên, dòng mã trên sẽ không xuất ra hình ảnh mà xuất ra mã html. Để sửa lỗi này, thêm thuộc tính escape = false cho hàm link, ví dụ:

<?php echo $this->Html->link($this->Html->image($book['Book']['image']), '/'.$book['Book']['slug'], ['escape' => false]); ?>


Sửa lại trang hiển thị thông tin chi tiết một quyển sách. Vì bảng books trong cơ sở dữ liệu lúc thiết kế chưa có trường pages, nên sẽ thêm vào.

Phần thông báo lỗi được sử dụng lại nhiều lần, nên sẽ tạo một element cho nó, ví dụ:

[View\Elements\errors.ctp]

<?php if (isset($errors)): ?>
            <div class="alert alert-danger">
                        <?php foreach ($errors as $error): ?>
                                    <?php echo $error[0]; ?>
                        <?php endforeach ?>
            </div>
<?php endif ?>

Vì đang sử dụng CakePHP 2.9.6, nên để hiển thị thông báo khi thêm comment vào cơ sở dữ liệu thành công hoặc thất bại ở trong view, sử dụng hàm sau:

<?php echo $this->Flash->render(); ?>

Ví dụ,

[View\Books\view.ctp]
<h4>Gửi nhận xét</h4>
<?php echo $this->element('errors'); ?>
<?php echo $this->Flash->render(); ?>
<?php echo $this->Form->create('Comment', ['url' => ['action' => 'add'], 'novalidate' => true, 'class' => 'comments form']); ?>

Để ý hàm $this->Flash->render(); sẽ hiển thị thông tin được thiết lập trước đó (trong controller) bằng hàm:

$this->Flash->success('Đã gửi nhận xét thành công!',
                                                                        ['params' =>
                                                                                    ['class' => 'alert alert-info']
                                                                        ]);

Hoặc:

$this->Flash->error(('Chưa gửi được. Vui lòng thử lại.'),
                                                                        ['params' =>
                                                                                    ['class' => 'alert alert-danger']
                                                                        ]);

Ví dụ,

[Controller\CommentsController.php action Add()]

public function add() {
                        if ($this->request->is('post')) {
                                    // pr($this->request->data); exit;
                                    $this->Comment->set($this->request->data);
                                    if ($this->Comment->validates()) {
                                                $this->Comment->create();
                                                if ($this->Comment->save($this->request->data)) {
                                                            $this->Flash->success('Đã gửi nhận xét thành công!',
                                                                        ['params' =>
                                                                                    ['class' => 'alert alert-info']
                                                                        ]);
                                                } else {
                                                            $this->Flash->error(('Chưa gửi được. Vui lòng thử lại.'),
                                                                        ['params' =>
                                                                                    ['class' => 'alert alert-danger']
                                                                        ]);
                                                }
                                    } else {
                                                $comment_errors = $this->Comment->validationErrors;
                                                $this->Session->write('comment_errors', $comment_errors);

                                    }
                                    $this->redirect($this->referer());
                        }
            }

Trong Elements\Flash, thêm hai element có tên là success.ctp và error.ctp với nội dung như sau:

<div class="<?= h($params['class']) ?>">
    <?= h($message) ?>
</div>

Khi tải lại một trang, muốn nó hiển thị đúng ở một ví trí nào đó, trong hàm redirect, thêm tham số chỉ ra vị trí cần hiển thị, ví dụ, [Controller\CommentsController.php action Add()] sửa lại một chút như sau:

$this->redirect($this->referer().'#nhan-xet');

[View\Books\view.ctp]

<div class="panel">
            <h4 class="panel-heading"><span class="glyphicon glyphicon-bookmark"> Chi tiết</span></h4>
            <div class="row">
                        <div class="col col-lg-3">
                                    <div class="book-thumbnail">
                                                <?php echo $this->Html->image($book['Book']['image']); ?>
                                    </div>
                        </div>
                        <div class="col col-lg-9">
                                    <div class="book-info chi-tiet">
                                                <h4><?php echo h($book['Book']['title']); ?></h4>
                                                <p>Tác giả:
                                                            <?php if (!empty($book['Writer'])): ?>
                                                                        <?php foreach ($book['Writer'] as $writer): ?>
                                                                                    <?php echo $this->Html->link($writer['name'], '/tac-gia/'.$writer['slug']); ?>
                                                                        <?php endforeach; ?>
                                                            <?php else: ?>
                                                                        Đang cập nhật!
                                                            <?php endif; ?>
                                                </p>
                                                <p>Nhận xét:
                                                            <?php echo $this->Html->link($book['Book']['comment_count'].' nhận xét', '#nhan-xet'); ?>
                                                </p>
                                                <p>Giá bìa:
                                                            <?php echo $this->Number->currency($book['Book']['price'],' VND',['places' => 0,'wholePosition' => 'after']); ?>
                                                </p>
                                                <p>Giá bán:
                                                            <span class="label label-danger">
                                                                        <?php echo $this->Number->currency($book['Book']['sale_price'],' VND',['places' => 0,'wholePosition' => 'after']); ?>
                                                            </span>
                                                </p>
                                                <button type="button" class="btn btn-primary"><span class="glyphicon glyphicon-shopping-cart"></span> Thêm vào giỏ hàng</button>
                                    </div>
                        </div>
                        <div class="col col-lg-12 book-content">
                                    <h4>Giới thiệu:</h4>
                                    <p>
                                                <?php echo h($book['Book']['info']); ?>
                                    </p>
                                    <div class="col-lg-7">
                                                <table class="table table-striped table-bordered">
                                                            <thead>
                                                                        <tr>
                                                                                    <th colspan="2">Thông tin chi tiết</th>
                                                                        </tr>
                                                            </thead>
                                                            <tbody>
                                                                        <tr>
                                                                                    <td>Nhà xuất bản:</td>
                                                                                    <td><?php echo h($book['Book']['publisher']); ?></td>
                                                                        </tr>
                                                                        <tr>
                                                                                    <td>Ngày xuất bản:</td>
                                                                                    <td><?php echo h($book['Book']['publish_date']); ?></td>
                                                                        </tr>
                                                                        <tr>
                                                                                    <td>Số trang:</td>
                                                                                    <td><?php echo h($book['Book']['pages']); ?></td>
                                                                        </tr>
                                                            </tbody>
                                                </table>
                                    </div>
                        </div>
            </div>
</div>
<!-- sách liên quan -->
<div class="panel panel-success">
            <h4 class="panel-heading"><span class="glyphicon glyphicon-list-alt"></span> Sách liên quan</h4>
            <?php echo $this->element('book', ['books' => $relatedBooks]); ?>
</div>
<!-- Bình luận - nhận xét -->
<div id="nhan-xet" class="panel">
            <h4 class="panel-heading"><span class="glyphicon glyphicon-comment"></span> Nhận xét</h4>
            <div class="row">
                        <div class="col col-lg-10">
                                    <?php if (!empty($comments)): ?>
                                                <?php foreach ($comments as $comment): ?>
                                                            <p class="comment">
                                                                        <strong><?php echo $comment['User']['username']; ?>:</strong>
                                                                        <?php echo $comment['Comment']['content']; ?>
                                                            </p>
                                                <?php endforeach; ?>
                                    <?php else: ?>
                                                <p class="comment">Chưa có nhận xét!</p>
                                    <?php endif; ?>
                        </div>
            </div>
</div>
<!-- gửi nhận xét -->
<h4>Gửi nhận xét</h4>
<?php echo $this->element('errors'); ?>
<?php echo $this->Flash->render(); ?>
<?php echo $this->Form->create('Comment', ['url' => ['action' => 'add'], 'novalidate' => true, 'class' => 'comments form']); ?>
            <?php
                        echo $this->Form->input('user_id',
                                    [
                                                'type' => 'text',
                                                'value' => 1,
                                                'hidden' => true,
                                                'label' => '',
                                                'required' => false
                                    ]);
                        echo $this->Form->input('book_id',
                                    [
                                                'type' => 'text',
                                                'hidden' => true,
                                                'label' => '',
                                                'required' => false,
                                                'value' => $book['Book']['id']
                                    ]);
                        echo $this->Form->input('content', ['label' => '', 'rows' => 5, 'class' => 'col-lg-12']);
            ?>
            <?php echo $this->Form->button('Gửi', ['type' => 'submit', 'class' => 'pull-right btn btn-primary col-lg-3 send-button']); ?>

<?php echo $this->Form->end(); ?>
-----------
Cập nhật 28/5/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web