CAKEPHP 快速入門

快速入門

實戰是學習以及體驗 CakePHP 的最好途徑。 讓我們以開發一個內容管理系統(CMS)爲例,來學習 CakePHP。

內容管理系統教程

此教程將講述如何建立一個簡單的 CMS。 首先我們需要安裝 CakePHP,然後創建數據庫,最後編寫一個簡單的文章管理系統。

基本要求:

  1. 一個數據庫服務器。此教程採用的是 MySQL 作爲數據庫。 你需要儲備基本的 SQL 知識。懂得如何使用 SQL 建立數據庫以及執行教程中的各種 SQL 片段。 CakePHP 可自動構造你的應用所需的各種查詢語句。 由於此教程使用的是 MySQL, 請確定 PHP 的 pdo_mysql 已經啓用。
  2. 基本的 PHP 知識。

在開始之前,請確保你的 PHP 已經更新。

php -v

你至少需要安裝 PHP (命令行界面)版本 5.6.0 以上。網路服務器的 PHP 需要和命令行界面版本一致,保證 5.6.0 以上。

安裝 CakePHP

使用 Composer 是安裝 CakePHP 最簡單的方法。Composer 是通過終端或者命令行提示符安裝 CakePHP 的一種簡易方式。 首先,你需要下載和安裝 Composer。你可以通過 cURL,然後執行以下語句來安裝:

curl -s https://getcomposer.org/installer | php

或者你也可以從 Composer 官網 直接下載 composer.phar

然後在同一個目錄中,運行以下語句來安裝 CakePHP 的應用骨架,此應用將會建立在一個 cms 的目錄中:

php composer.phar create-project --prefer-dist cakephp/app cms

如果你是下載使用的 Composer Windows Installer,在同一個目錄中(比如 C:\wamp\www\dev\cakephp3)終端運行以下語句:

composer self-update && composer create-project --prefer-dist cakephp/app cms

使用 Composer 的優勢是它會自動完成一些重要的設置任務,比如建立合適的文件權限以及建立配置文件

config/app.php

當然 CakePHP 也提供其他的安裝方式。如果你不能或者不想使用 Composer 的話,請查看 安裝 章節。

不管你是以何種方式下載和安裝,你的目錄應該都會是以下形式:

/cms
  /bin
  /config
  /logs
  /plugins
  /src
  /tests
  /tmp
  /vendor
  /webroot
  .editorconfig
  .gitignore
  .htaccess
  .travis.yml
  composer.json
  index.php
  phpunit.xml.dist
  README.md

事不宜遲,現在是學習 CakePHP 目錄結構的合適時機: 請查看 CakePHP 的文件夾結構 章節。

如果你沒有跟上此教程的速度,你可以參考下此教程的 成品代碼.

檢查安裝

你可以通過訪問默認的主頁的來檢查安裝是否成功。當然首先我們需要啓動開發服務器:

cd /path/to/our/app

bin/cake server

Windows 用戶,需使用 bin\cake server (使用反斜線)

PHP 自帶的網絡服務器將在 8765 端口啓動。在瀏覽器中訪問 http://localhost:8765, 你應該會看到歡迎頁面。除了 ”CakePHP being able to connect to your database“ 沒有綠色廚師帽以後, 其餘的要點都應有。如果不是這樣的話,你可能需要安裝一些缺失的 PHP 擴展,或者是建立正確的目錄權限。

接下來,我們將創立我們的 數據庫以及創建第一個模型.

CMS 教程 - 創建數據庫

CakePHP 已經安裝好,我們可以開始爲 CMS 應用建立數據庫了。首先建立一個 空的數據庫,你可以使用任意的名字,比如 cake_cms。執行以下 SQL 語句來建立需要的數據庫表:

USE cake_cms;

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL,
    password VARCHAR(255) NOT NULL,
    created DATETIME,
    modified DATETIME
);

CREATE TABLE articles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    title VARCHAR(255) NOT NULL,
    slug VARCHAR(191) NOT NULL,
    body TEXT,
    published BOOLEAN DEFAULT FALSE,
    created DATETIME,
    modified DATETIME,
    UNIQUE KEY (slug),
    FOREIGN KEY user_key (user_id) REFERENCES users(id)
) CHARSET=utf8mb4;

CREATE TABLE tags (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(191),
    created DATETIME,
    modified DATETIME,
    UNIQUE KEY (title)
) CHARSET=utf8mb4;

CREATE TABLE articles_tags (
    article_id INT NOT NULL,
    tag_id INT NOT NULL,
    PRIMARY KEY (article_id, tag_id),
    FOREIGN KEY tag_key(tag_id) REFERENCES tags(id),
    FOREIGN KEY article_key(article_id) REFERENCES articles(id)
);

INSERT INTO users (email, password, created, modified)
VALUES
('[email protected]', 'sekret', NOW(), NOW());

INSERT INTO articles (user_id, title, slug, body, published, created, modified)
VALUES
(1, 'First Post', 'first-post', 'This is the first post.', 1, now(), now());

你也許已經注意到 articles_tags 表使用了複合主鍵。CakePHP 幾乎支持所有的複合主鍵,這樣便於你 使用比較簡單的數據庫結構,不用添加額外的 id 列。

以上所使用的數據表名以及列名都不是隨意的。利用 CakePHP 的 命名約定, 我們可以更有效的使用並且避免了配置框架的需要。雖然 CakePHP 的靈活度可以容納幾乎所有的數據庫結構, 但是採取約定,利用 CakePHP 提供的默認的約定可以節省你很多的開發時間,

數據庫配置

接着我們需要告訴 CakePHP 我們之前創建的數據庫地址以及如何連接。在 config/app.php 文件中, 找到 Datasources.default 數組,更改爲相對應的值。以下的例子是一個完整的配置數組:

<?php
return [
    // More configuration above.
    'Datasources' => [
        'default' => [
            'className' => 'Cake\Database\Connection',
            'driver' => 'Cake\Database\Driver\Mysql',
            'persistent' => false,
            'host' => 'localhost',
            'username' => 'cakephp',
            'password' => 'AngelF00dC4k3~',
            'database' => 'cake_cms',
            'encoding' => 'utf8mb4',
            'timezone' => 'UTC',
            'cacheMetadata' => true,
        ],
    ],
    // More configuration below.
];

一旦配置好你的 config/app.php 文件以後,你應該看到 'CakePHP is able to connect to the database' 的部分也出現一個綠色廚師帽。

一份默認的 CakePHP 配置文件可在 config/app.default.php 找到。

創建第一個的模型

模型是一個 CakePHP 應用的核心。通過他們,我們能夠讀取以及修改數據。他們讓我們可以將數據關聯 起來,驗證數據以及運用各種業務邏輯。模型是建立控制器的動作 (action) 和 模塊(template)的基石。

CakePHP 的模型是由 Table and Entity 兩種對象組成。Table 爲是一個特定的數據庫表 的抽象。他們儲存在 src/Model/Table 目錄中。在本教程中,我們將建立文件 src/Model/Table/ArticlesTable.php。 完成的文件內容如下:

<?php
// src/Model/Table/ArticlesTable.php
namespace App\Model\Table;

use Cake\ORM\Table;

class ArticlesTable extends Table
{
    public function initialize(array $config)
    {
        $this->addBehavior('Timestamp');
    }
}

我們附屬了 Timestamp 行爲 (behavior)。此行爲將會幫助我們自動填充 被附屬的數據庫表的 created 列 和 modified列。利用 CakePHP 的命名約定,我們取其名爲 ArticlesTable, 這樣 CakePHP 便可自動找到 articles 數據庫表。同樣利用命名約定,CakePHP 默認 id 爲主鍵。

如果一個模型的定義文件在 src/Model/Table 目錄中缺失, CakePHP 會動態的建立一個模型對象。 這代表着,如果我們不小心寫錯文件名(比如錯寫成 articlestable.php 或者 ArticleTable.php), CakePHP 將無法讀取你的設置,而是使用動態生成的模型。

我們也需要爲 Articles 創建一個 Entity 的類。Entity 是數據庫表中單個記錄的抽象,它提供數據庫行層面的 行爲。在本教程中,我們將建立文件 src/Model/Entity/Article.php。 完成的文件內容如下:

<?php
// src/Model/Entity/Article.php
namespace App\Model\Entity;

use Cake\ORM\Entity;

class Article extends Entity
{
    protected $_accessible = [
        '*' => true,
        'id' => false,
        'slug' => false,
    ];
}

以上的 Entity 目前比較單一,我們僅僅建立了 _accessible 屬性。它規定了此類的各種屬性的控制規則 entities-mass-assignment。

目前爲止,我們的模型都很簡單,接下來我們將創建我們的第一個 控制器和模版

CMS 教案 - 創建 Articles 控制器

在上一節,我們爲 articles 數據表創建了模型,現在我們需要爲它創建控制器。CakePHP 中的控制器 是用來處理 HTTP 請求以及執行封裝在模型中的業務邏輯。讓我們建立一個叫 ArticlesController.php 的 控制器文件,然後把它置於 src/Controller 目錄中。一個基本的控制器代碼如下:

<?php
// src/Controller/ArticlesController.php

namespace App\Controller;

class ArticlesController extends AppController
{
}

然後讓我們爲控制器添加一個行爲(action)。行爲是控制器中的方法,並且他們都與路由相連。比如當用戶訪問www.example.com/articles/index (與 www.example.com/articles 是一樣的效果),CakePHP 會自動調用 ArticlesController 控制器中的 index 方法。我們需要建立的這個行爲應該查詢 模型層,接着用模版渲染一個視圖作爲響應。此行爲的代碼應該看起來如下:

<?php
// src/Controller/ArticlesController.php

namespace App\Controller;

class ArticlesController extends AppController
{
    public function index()
    {
        $this->loadComponent('Paginator');
        $articles = $this->Paginator->paginate($this->Articles->find());
        $this->set(compact('articles'));
    }
}

定義完 ArticlesController 控制器中的 index() 函數以後,用戶便可以使用 www.example.com/articles/index 訪問了。同理,如果我們定義一個 foobar() 的函數,用戶便可以訪問 www.example.com/articles/foobar。 不要爲了實現某些特定的 URLs 來爲你的控制器和行爲取名。遵循 CakePHP 約定 原則, 秉持易讀易懂的概念來取名。然後再使用 Routing連接行爲和你想要的 URLs。

至此,我們的控制器行爲是非常簡單的。它利用 Articles 模型從數據庫中讀取一組分頁後的 articles 數據, 然後使用 set()函數將數據傳入模版(將在下部分創建)。CakePHP 將會自動渲染模版。

創建 Article 列表模版

我們的控制器拉取到了數據,爲視圖做好了準備,讓我們爲 index 行爲創建一個視圖模版。

CakePHP 的視圖模版是插入應用佈局中的演示型 PHP 代碼。視圖不僅可以實現 HTML,也可以實現 JSON 和 CSV, 甚至是二進制文件,比如說 PDF。

佈局是用來包裝視圖的演示代碼。佈局文件包含常見的網站元素,比如 header, footer 以及其他導航元素。一個 應用可以擁有多個佈局,使用於不同場景。但是現在讓我創建一個默認的佈局而已。

模版文件都儲存在 src/Template 目錄中的一個文件夾中,此文件夾以其對應的控制器命名。所以我們需要創建 一個叫做 'Articles' 的文件夾。其代碼如下:

<!-- File: src/Template/Articles/index.ctp -->

<h1>Articles</h1>
<table>
    <tr>
        <th>Title</th>
        <th>Created</th>
    </tr>

    <!-- Here is where we iterate through our $articles query object, printing out article info -->

    <?php foreach ($articles as $article): ?>
    <tr>
        <td>
            <?= $this->Html->link($article->title, ['action' => 'view', $article->slug]) ?>
        </td>
        <td>
            <?= $article->created->format(DATE_RFC850) ?>
        </td>
    </tr>
    <?php endforeach; ?>
</table>

在上一個章節中,我們使用 set() 方法將 'articles' 注入到了視圖中。在以上的代碼中,我們可以看到,被注入 的變量轉化爲了視圖模版中的本地變量。

你也許注意到我們使用了一個叫做 $this->Html 的對象。它是 CakePHP 中 HtmlHelper 的一個實例。CakePHP 自帶一系列的視圖助手 (view helper),它們簡化了很多任務,比如創建銜接,表單以及分頁。 你可以在 助件 章節學到更多關於它們的內容,但是在這裏,我們需要注意到的是 link() 方法會使用第一個參數作爲文字和第二個參數作爲 URL 來生產一個 HTML 銜接。

When specifying URLs in CakePHP, it is recommended that you use arrays or named routes. These syntaxes allow you to leverage the reverse routing features CakePHP offers.

在 CakePHP 中生成 URLs 時候,建議使用數組或者 命名路由。使用這些語法,你將可以利用到 CakePHP 的反向路由功能。

至此,在你的瀏覽其中訪問 http://localhost:8765/articles/index,你應該可以看到一個列表視圖,主題使用着正確 的格式,使用着 table 來排列 articles。

創建 View 動作

如果你點擊其中的一個 'view' 銜接,你會看到一個報錯頁面,提示你 'action hasn't been implemented'. 讓我們修復它:

// Add to existing src/Controller/ArticlesController.php file

public function view($slug = null)
{
    $article = $this->Articles->findBySlug($slug)->firstOrFail();
    $this->set(compact('article'));
}

雖然以上是一個很簡單的 action,但是我們卻可以看到一些 CakePHP 強大的功能。首先我們使用了 findBySlug() 方法,它屬於 動態 Finder。這個方法容許我們創建一個簡單的使用 slug 查詢 artciles 的 query。然後我們使用 firstOrFail() 提取第一個記錄,或者拋出異常 NotFoundException

我們的 action 的第一個參數是 $slug,可這個參數的值是如何來的呢?如果一個用戶訪問 /articles/view/first-post,那麼 'first-post' 將會被 CakePHP 的路由以及調度層傳入爲 action 的參數。保存爲文件以後,如果我們重新加載頁面,我們將看到另一個新的 CakePHP 報錯頁面,提示我們 'missing a view template'。讓我們修復它。

創建視圖模版

讓我們爲 'view' 創建一個視圖文件 src/Template/Articles/view.ctp

<!-- File: src/Template/Articles/view.ctp -->

<h1><?= h($article->title) ?></h1>
<p><?= h($article->body) ?></p>
<p><small>Created: <?= $article->created->format(DATE_RFC850) ?></small></p>
<p><?= $this->Html->link('Edit', ['action' => 'edit', $article->slug]) ?></p>

你可以通過瀏覽 /articles/index 頁面或者直接訪問 /articles/view/first-post 查看一個 article 來檢測視圖是否成功。

添加 Artciles

我們已經創建好基本的閱讀視圖,下一步我們需要實現創建新 articles 的功能。首先讓我們在 ArticlesController 中創建一個 action() 的動作。 至此我們的控制器代碼應該看起來如下:

// src/Controller/ArticlesController.php

namespace App\Controller;

use App\Controller\AppController;

class ArticlesController extends AppController
{

    public function initialize()
    {
        parent::initialize();

        $this->loadComponent('Paginator');
        $this->loadComponent('Flash'); // Include the FlashComponent
    }

    public function index()
    {
        $articles = $this->Paginator->paginate($this->Articles->find());
        $this->set(compact('articles'));
    }

    public function view($slug)
    {
        $article = $this->Articles->findBySlug($slug)->firstOrFail();
        $this->set(compact('article'));
    }

    public function add()
    {
        $article = $this->Articles->newEntity();
        if ($this->request->is('post')) {
            $article = $this->Articles->patchEntity($article, $this->request->getData());

            // Hardcoding the user_id is temporary, and will be removed later
            // when we build authentication out.
            $article->user_id = 1;

            if ($this->Articles->save($article)) {
                $this->Flash->success(__('Your article has been saved.'));
                return $this->redirect(['action' => 'index']);
            }
            $this->Flash->error(__('Unable to add your article.'));
        }
        $this->set('article', $article);
    }
}

如果你需要在控制器中使用 Flash 的組件,你必須要先加載它。通常情況下 我們可以在 AppController 中加載它,由於它是一個比較常用的組件。

以下是 add() 行爲的功能:

  • 如果 HTTP 請求是 POST,嘗試使用 Articles 模型來保存數據。
  • 如果由於任何原因數據沒有被保存,直接渲染視圖。這樣子用戶有機會看到驗證錯誤或者其他的警告信息。

每一個 CakePHP 請求包含着一個 request 對象,我們可以通過 $this->request 獲取到。這個 request 對象包含着 當前的請求的所有信息。我們使用 Cake\Http\ServerRequest::is() 方法檢測此次請求是否是一個 HTTP POST請求。

POST 數據可以通過 $this->request->getData() 獲取。如果需要檢查它裏面的數據內容,我們可以通過方法 pr() 或者 debug()。在保存數據之前,我們首先 'marshal' 數據成一個 Article Entity。然後我們使用之前創建的 ArticlesTable 來存儲。

保存完以後,我們使用 FlashComponent 的 success() 方法來把提示信息傳入 session 中。success 方法是通過 PHP 的 魔術方法 實現的. 瞬間提示信息將會在頁面跳轉以後顯示出來。在我們的佈局中,我們使用了 <?= $this->Flash->render() ?>,它會將瞬間提示信息顯示出來, 然後刪除其對應的 session 變量。保存完成以後,我們使用 Cake\Controller\Controller::redirect 將用戶頁面帶回 artciles 列表。參數 ['action' => 'index'] 將被翻譯爲 /articles,也就是 ArticlesController 的 index 行爲。參照 API <https://api.cakephp.org> 中的 Cake\Routing\Router::url() 文檔來查看 CakePHP 中生成 URL 各種方法的格式。

創建 add 模版

以下是 add 動作對應的視圖模版:

<!-- File: src/Template/Articles/add.ctp -->

<h1>Add Article</h1>
<?php
    echo $this->Form->create($article);
    // Hard code the user for now.
    echo $this->Form->control('user_id', ['type' => 'hidden', 'value' => 1]);
    echo $this->Form->control('title');
    echo $this->Form->control('body', ['rows' => '3']);
    echo $this->Form->button(__('Save Article'));
    echo $this->Form->end();
?>

我們使用 FormHelper 來生成 HTML form 的開始標籤。以下是 $this->Form->create() 生成的 HTML 代碼:

<form method="post" action="/articles/add">

由於我們使用 create() 時沒有使用 URL 選項,FormHelper 假設我們需要提交此 form 回當前的動作。

當需要創建同名的表單元素時,我們可以使用 $this->Form->control() 方法。第一個參數告訴 CakePHP 其對應的領域, 第二個參數可以讓我們指定各式各樣的選項 - 在以上代碼中,textarea 元素的 rows 的行數。這裏有使用到一些內檢功能和約定。 control() 將會根據不同的模型領域生產不同的元素,以及使用 inflection 來生成標註文字。你也可以使用選項來定製標註,輸入元素以及 任何其他 form 的屬性。 最後 $this->Form->end() 方法關閉表單.

讓我們更新一下 src/Template/Articles/index.ctp 視圖,添加一個新的 "Add Article" 的銜接。在 <table> 之前,加入下行 代碼:

<?= $this->Html->link('Add Article', ['action' => 'add']) ?>

添加簡單 slug 生成功能

如果我們現在保存一個 Article, 它將會失敗,因爲 slug 列應該爲 NOT NULL。通常 slug 的值應該是 title 的 URL 安全版本。 我們可以使用 ORM 的 beforeSave() 回調 來生成 slug:

// in src/Model/Table/ArticlesTable.php
namespace App\Model\Table;

use Cake\ORM\Table;
// the Text class
use Cake\Utility\Text;

// Add the following method.

public function beforeSave($event, $entity, $options)
{
    if ($entity->isNew() && !$entity->slug) {
        $sluggedTitle = Text::slug($entity->title);
        // trim slug to maximum length defined in schema
        $entity->slug = substr($sluggedTitle, 0, 191);
    }
}

以上的代碼是很簡陋的,沒有考慮到 slug 的重複問題。往下我們會修復它。

添加 edit 動作

現在我們可以保存 articles,但是無法編輯他們。讓我們現在完善它。加入一下的動作至 ArticlesController 中:

// in src/Controller/ArticlesController.php

// Add the following method.

public function edit($slug)
{
    $article = $this->Articles->findBySlug($slug)->firstOrFail();
    if ($this->request->is(['post', 'put'])) {
        $this->Articles->patchEntity($article, $this->request->getData());
        if ($this->Articles->save($article)) {
            $this->Flash->success(__('Your article has been updated.'));
            return $this->redirect(['action' => 'index']);
        }
        $this->Flash->error(__('Unable to update your article.'));
    }

    $this->set('article', $article);
}

在這個動作中,我們首先保證用戶要求的 article 存在。如果 $slug 是空的,或者 article 並不存在,拋出 NotFoundException 異常,然後 CakePHP 的 ErrorHandler 會渲染相對應的錯誤頁面。

接着我們檢測此請求是否爲 POST 或者 PUT。如果是,我們將使用 patchEntity() 方法以及傳入的數據來更新我們的 artcile 模型。 最後,我們使用 save() 保存數據,成功將跳轉,失敗將顯示驗證錯誤信息。

創建 edit 模版

以下是 edit 模版代碼:

<!-- File: src/Template/Articles/edit.ctp -->

<h1>Edit Article</h1>
<?php
    echo $this->Form->create($article);
    echo $this->Form->control('user_id', ['type' => 'hidden']);
    echo $this->Form->control('title');
    echo $this->Form->control('body', ['rows' => '3']);
    echo $this->Form->button(__('Save Article'));
    echo $this->Form->end();
?>

這個模版將展示一個編輯表單(以及表單元素值),以及必要時的錯誤驗證信息。

現在我們可以更新 index 視圖,加入 edit 的銜接。

<!-- File: src/Template/Articles/index.ctp  (edit links added) -->

<h1>Articles</h1>
<p><?= $this->Html->link("Add Article", ['action' => 'add']) ?></p>
<table>
    <tr>
        <th>Title</th>
        <th>Created</th>
        <th>Action</th>
    </tr>

<!-- Here's where we iterate through our $articles query object, printing out article info -->

<?php foreach ($articles as $article): ?>
    <tr>
        <td>
            <?= $this->Html->link($article->title, ['action' => 'view', $article->slug]) ?>
        </td>
        <td>
            <?= $article->created->format(DATE_RFC850) ?>
        </td>
        <td>
            <?= $this->Html->link('Edit', ['action' => 'edit', $article->slug]) ?>
        </td>
    </tr>
<?php endforeach; ?>

</table>

更新驗證規則

到現在爲止,我們都沒有使用任何的輸入驗證。讓我們使用 驗證器 來完善:

// src/Model/Table/ArticlesTable.php

// add this use statement right below the namespace declaration to import
// the Validator class
use Cake\Validation\Validator;

// Add the following method.
public function validationDefault(Validator $validator)
{
    $validator
        ->notEmpty('title')
        ->minLength('title', 10)
        ->maxLength('title', 255)

        ->notEmpty('body')
        ->minLength('body', 10);

    return $validator;
}

當 CakePHP 調用 save() 時,validationDefault() 方法將指示如何驗證數據。在以上代碼中, 我們規定 title 和 body 不可以爲空,而且必須要達到一定的長度。

CakePHP 的驗證器很強大也很靈活。它提供了一些常用的規則,比如郵箱地址,IP 地址等等。此外,你也可以靈活 地加入自定的規則。參考 Validation 文檔可瞭解如何自定義驗證規則。

現在我們部署好了驗證規則,你可以嘗試着使用空 title 或者 body 來測試。由於我們使用了 FormHelper 的Cake\View\Helper\FormHelper::control() 來創建表單元素,你會發現驗證錯誤信息回自動的呈現出來。

添加 delete 行爲

接下來我們要實現一個功能可以讓用戶刪除 artciles。首先添加一個 delete() 行爲到 ArticlesController 中:

// src/Controller/ArticlesController.php

public function delete($slug)
{
    $this->request->allowMethod(['post', 'delete']);

    $article = $this->Articles->findBySlug($slug)->firstOrFail();
    if ($this->Articles->delete($article)) {
        $this->Flash->success(__('The {0} article has been deleted.', $article->title));
        return $this->redirect(['action' => 'index']);
    }
}

以上的代碼邏輯將會使用規定的 $slug 來刪除指定 article,跳轉頁面至 /articles,然後使用 $this->Flash->success() 呈現一條確認信息。如果用戶嘗試用 GET 請求,allowMethod() 將會拋出異常。未捕獲的異常將被 CakePHP 內核的異常處理器捕獲,自帶的 錯誤頁面將被展示出來。CakePHP 自帶很多 異常 ,我們可以使用它們來響應不同的 HTTP 錯誤。

允許 GET 請求刪除內容是  危險的,這種做法可能導致爬蟲不小心刪除所有的內容。這就是我們 在控制器中使用 allowMethod() 的原因。

由於我們只是運行了一段邏輯然後跳轉到另一個動作,此處不需要模版。讓我們更新下 index 模版,加入 delete 的銜接:

<!-- File: src/Template/Articles/index.ctp  (delete links added) -->

<h1>Articles</h1>
<p><?= $this->Html->link("Add Article", ['action' => 'add']) ?></p>
<table>
    <tr>
        <th>Title</th>
        <th>Created</th>
        <th>Action</th>
    </tr>

<!-- Here's where we iterate through our $articles query object, printing out article info -->

<?php foreach ($articles as $article): ?>
    <tr>
        <td>
            <?= $this->Html->link($article->title, ['action' => 'view', $article->slug]) ?>
        </td>
        <td>
            <?= $article->created->format(DATE_RFC850) ?>
        </td>
        <td>
            <?= $this->Html->link('Edit', ['action' => 'edit', $article->slug]) ?>
            <?= $this->Form->postLink(
                'Delete',
                ['action' => 'delete', $article->slug],
                ['confirm' => 'Are you sure?'])
            ?>
        </td>
    </tr>
<?php endforeach; ?>

</table>

此處我們使用了 View\Helper\FormHelper::postLink() 來創建一個銜接,此銜接將會用 JavaScript 來建立一個 POST 的請求。

This view code also uses the FormHelper to prompt the user with a JavaScript confirmation dialog before they attempt to delete an article.

With a basic articles management setup, we'll create the basic actions for our Tags and Users tables.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章