CakePHP系列(二)----Bookmarker案例(一)

本教程通过创建一个简单的书签应用,引导读者逐步掌握CakePHP框架的基本使用方法,包括安装配置、数据库交互、密码散列及路由设置等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Bookmarker案例


本教程将引导您完成一个简单的书签应用程序(Bookmarker)的创建。 首先,我们将安装CakePHP,创建我们的数据库,并使用CakePHP提供的工具快速完成我们的应用程序。


以下是您需要的:

1.数据库服务器。 


我们将在本教程中使用MySQL服务器, 您将需要足够了解SQL以创建数据库:CakePHP将从那里接管,因为我们使用MySQL,还要确保在PHP中启用了pdo_mysql 。


2.基本PHP知识。


在开始之前,你应该确保你有一个最新的PHP版本:


php -v

你至少应该有安装PHP 5.6.0(CLI)或更高。 你的网络服务器的PHP版本必须是5.6.0或更高,应该 相同版本您的命令行接口(CLI)是 PHP版本,如果你想看到完整的应用程序CakePHP /书签。让我们开始吧。


二、获取CakePHP


安装CakePHP的最简单的方法是使用Composer。 Composer是从终端或命令行提示符安装CakePHP的简单方法。 首先,您需要下载并安装Composer,如果您还没有这样做的话。 如果你安装了curl,它就像运行下面一样简单:


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


默认windows下是没有curl这个命令,所以你要下载curl.exe(可以从这下载),并把路径配置到path环境变量中,然后才能执行该命令。




或者,您可以从Composer网站下载composer.phar 。

然后只需在安装目录中在终端中键入以下行,即可在bookmarker目录中安装CakePHP应用程序框架:

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


报错:Could not open input file: composer.phar

把这三个文件(从这下载),放到目录下,就可以了


如果您下载并运行了Composer Windows Installer ,则从安装目录(即C:\ wamp \ www \ dev \ cakephp3)在终端中键入以下行:

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


使用Composer的优点是它将自动完成一些重要的设置任务,如设置正确的文件权限和为您创建config / app.php文件。

还有其他方法来安装CakePHP。 如果您不能或不想使用Composer,请查看安装部分。

无论下载和安装CakePHP的方式如何,一旦设置完成,您的目录设置应如下所示:

/bookmarker
    /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文件夹结构部分。

检查我们的安装

我们可以通过检查默认主页快速检查我们的安装是否正确。 在您可以这么做之前,您需要启动开发服务器:

bin/cake server


▲ 注意: 对于Windows,该命令需要是bin\cake server (注意反斜杠)。




这将在端口8765上启动PHP的内置Web服务器。在Web浏览器中打开http://localhost:8765以查看欢迎页面。




 所有的项目符号都应该是CakePHP之外的其他能够连接到你的数据库的复选标记。 如果没有,您可能需要安装其他PHP扩展,或设置目录权限。



三、创建数据库


接下来,让我们为我们的书签应用程序设置数据库。 如果您还没有这样做,请创建一个空数据库供您在本教程中使用,并使用您选择的名称,例如cake_bookmarks 。 您可以执行以下SQL来创建必要的表:


▲ 注意:  这里我用的是本地安装好的数据库,你也可以把项目复制到集成好的环境中去。所以这里不用启动Apache服务。


 您可以执行以下SQL来创建必要的表:

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 bookmarks (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    title VARCHAR(50),
    description TEXT,
    url TEXT,
    created DATETIME,
    modified DATETIME,
    FOREIGN KEY user_key (user_id) REFERENCES users(id)
);

CREATE TABLE tags (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255),
    created DATETIME,
    modified DATETIME,
    UNIQUE KEY (title)
);

CREATE TABLE bookmarks_tags (
    bookmark_id INT NOT NULL,
    tag_id INT NOT NULL,
    PRIMARY KEY (bookmark_id, tag_id),
    FOREIGN KEY tag_key(tag_id) REFERENCES tags(id),
    FOREIGN KEY bookmark_key(bookmark_id) REFERENCES bookmarks(id)
);


执行完后




您可能已经注意到bookmarks_tags表使用复合主键。 CakePHP几乎支持复合主键,使得更容易构建多租户应用程序。

我们使用的表和列名称不是任意的。 通过使用CakePHP的命名约定 ,我们可以更好地利用CakePHP,并避免配置框架。CakePHP是足够灵活的,以适应甚至不一致的遗留数据库模式,但遵守约定将节省您的时间。


四、数据库配置


接下来,让我们告诉CakePHP我们的数据库在哪里,以及如何连接到它。 对许多人来说,这将是第一次和最后一次你需要配置任何东西。

配置应该非常简单:只需将config/app.php文件中的Datasources.default数组中的值替换为适用于您的设置的值。 示例完成的配置数组可能如下所示:


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_bookmarks',
            'encoding' => 'utf8',
            'timezone' => 'UTC',
            'cacheMetadata' => true,
        ],
    ],
    // More configuration below.
];

一旦你保存了config / app.php文件,你应该看到'CakePHP能够连接到数据库'部分有一个复选标记。


▲ 注意: CakePHP的默认配置文件的副本可以在config/app.default.php中找到。


五、生成脚本代码


因为我们的数据库遵循CakePHP约定,我们可以使用控制台应用程序快速生成基本应用程序。 在命令行中运行以下命令:


// On Windows you'll need to use bin\cake instead.
bin/cake bake all users
bin/cake bake all bookmarks
bin/cake bake all tags


windows下执行:


bin\cake bake all users
bin\cake bake all bookmarks
bin\cake bake all tags




这将为我们的users,bookmarks和tags资源生成控制器,模型,视图,它们相应的测试用例和夹具。 如果您已停止服务器,请重新启动并转到http://localhost:8765/bookmarks




您应该看到一个基本但功能齐全的应用程序,它提供对应用程序数据库表的数据访问。 进入书签列表后,添加几个用户,书签和标签。


http://localhost:8765/users




http://localhost:8765/bookmarks




http://localhost:8765/tags



▲ 注意: 如果看到“未找到”(404)页面,请确认已加载Apache mod_rewrite模块。


六、添加密码散列


当您创建用户时(通过访问http://localhost:8765/users),您可能注意到密码以纯文本格式存储。 




从安全的角度来看,这是很糟糕的,所以让我们来解决这个问题。

这也是讨论CakePHP中的模型层的好时机。 在CakePHP中,我们将操作对象集合的方法和单个对象分成不同的类。 对实体集合进行操作的方法放在Table类中,而属于单个记录的要素放在Entity类上。

例如,对单个记录进行密码散列,因此我们将在实体对象上实现此行为。 因为,我们要在每次设置密码时哈希密码,我们将使用mutator/setter方法。 CakePHP将在任何时候在您的一个实体中设置属性时调用基于约定的setter方法。 让我们为密码添加一个setter。 在src / Model / Entity / User.php中添加以下内容:


namespace App\Model\Entity;

use Cake\Auth\DefaultPasswordHasher; //include this line
use Cake\ORM\Entity;

class User extends Entity
{

    // Code from bake.

    protected function _setPassword($value)
    {
        $hasher = new DefaultPasswordHasher();
        return $hasher->hash($value);
    }
}




现在更新您之前创建的其中一个用户,如果更改其密码,您应该会在列表或查看页面上看到一个散列的密码,而不是原始值。 CakePHP默认使用bcrypt密码。 




如果使用现有的数据库,也可以使用sha1或md5。


▲ 注意: 如果密码没有得到哈希,请确保您为该类的密码成员遵循相同的情况,同时命名setter函数



七、使用特定标记获取Bookmarks 


现在我们安全地存储密码,我们可以在我们的应用程序中建立一些更有趣的功能。 一旦您收集了一系列书签,就可以通过标签进行搜索。 接下来,我们将实现一个路由,控制器动作和finder方法来通过标签搜索书签。

理想情况下,我们会有一个URL为http://localhost:8765/bookmarks/tagged/funny/cat/gifs 。 这将让我们找到所有带有“funny”,“cat”或“gifs”标签的书签。 在我们实现之前,我们将添加一条新路线。 你的config/routes.php应该看起来像:


<?php
use Cake\Routing\Route\DashedRoute;
use Cake\Routing\Router;

Router::defaultRouteClass(DashedRoute::class);

// New route we're adding for our tagged action.
// The trailing `*` tells CakePHP that this action has
// passed parameters.
Router::scope(
    '/bookmarker',
    ['controller' => 'Bookmarks'],
    function ($routes) {
        $routes->connect('/tagged/*', ['action' => 'tags']);
    }
);

Router::scope('/', function ($routes) {
    // Connect the default home and /pages/* routes.
    $routes->connect('/', [
        'controller' => 'Pages',
        'action' => 'display', 'home'
    ]);
    $routes->connect('/pages/*', [
        'controller' => 'Pages',
        'action' => 'display'
    ]);

    // Connect the conventions based default routes.
    $routes->fallbacks();
});




上面定义了一个新的“路由”,它将/bookmarks/tagged/  连接到BookmarksController::tags() 。 通过定义路由,您可以区分网址的外观,以及它们的实现方式。 如果我们访问http://localhost:8765/bookmarker/tagged ,我们会看到一个来自CakePHP的有用的错误页面,通知您控制器操作不存在。 




让我们现在实现那个缺少的方法。 在src / Controller/BookmarksController.php中添加以下内容:


public function tags()
{
    // The 'pass' key is provided by CakePHP and contains all
    // the passed URL path segments in the request.
    $tags = $this->request->getParam('pass');

    // Use the BookmarksTable to find tagged bookmarks.
    $bookmarks = $this->Bookmarks->find('tagged', [
        'tags' => $tags
    ]);

    // Pass variables into the view template context.
    $this->set([
        'bookmarks' => $bookmarks,
        'tags' => $tags
    ]);
}




要访问请求数据的其他部分,请参阅请求部分。


八、创建Finder方法


在CakePHP中,我们喜欢保持我们的控制器行动苗条,并将我们应用程序的大部分逻辑放在模型中。 如果你现在访问/bookmarks/tagged URL,你会看到一个错误, findTagged()方法还没有实现,所以让我们这样做。 在src / Model/Table/BookmarksTable.php中添加以下内容:


// The $query argument is a query builder instance.
// The $options array will contain the 'tags' option we passed
// to find('tagged') in our controller action.
public function findTagged(Query $query, array $options)
{
    $bookmarks = $this->find()
        ->select(['id', 'url', 'title', 'description']);

    if (empty($options['tags'])) {
        $bookmarks->leftJoinWith('Tags', function ($q) {
            return $q->where(['Tags.title IS ' => null]);
        });
    } else {
        $bookmarks->innerJoinWith('Tags', function ($q) use ($options) {
            return $q->where(['Tags.title IN' => $options['tags']]);
        });
    }

    return $bookmarks->group(['Bookmarks.id']);
}




我们只是实现了一个自定义搜索方法。这是一个非常强大的概念 CakePHP允许你包起来再使用的查询。查找方法总是查询生成器对象和选择数组作为参数。使得人可以操纵的查询和添加任何要求的条件或标准。当完成时,查找方法必须返回 修改查询对象。在我们的查找中,我们利用了distinct()和matching()方法,它们允许我们找到具有“匹配”标签的不同书签。 matching()方法接受一个接收查询构建器作为其参数的匿名函数 。 在回调中,我们使用查询构建器来定义将过滤具有特定标记的书签的条件


九、创建视图


现在,如果您访问/bookmarker/tagged URL,CakePHP将显示一个错误,让您知道您没有创建视图文件。 接下来,让我们为tags()动作构建视图文件。 在src/Template/bookmarker/tags.ctp中放入以下内容:


<h1>
    Bookmarks tagged with
    <?= $this->Text->toList(h($tags)) ?>
</h1>

<section>
<?php foreach ($bookmarks as $bookmark): ?>
    <article>
        <!-- Use the HtmlHelper to create a link -->
        <h4><?= $this->Html->link($bookmark->title, $bookmark->url) ?></h4>
        <small><?= h($bookmark->url) ?></small>

        <!-- Use the TextHelper to format text -->
        <?= $this->Text->autoParagraph(h($bookmark->description)) ?>
    </article>
<?php endforeach; ?>
</section>



在上面的代码中,我们使用HtmlText帮助器来帮助生成我们的视图输出。 我们还使用h快捷函数来对输出进行HTML编码。你应该记住在输出用户数据时总是使用h()来防止HTML注入问题。

我们刚刚创建的tags.ctp文件遵循视图模板文件的CakePHP约定。 约定是使模板使用控制器操作名称的小写和下划线版本。

您可能会注意到,我们可以在我们的视图中使用$tags$bookmarks变量。 当我们在我们的控制器中使用set()方法时,我们设置要发送到视图的特定变量。 该视图将使所有传递的变量在模板中作为局部变量可用。

您现在应该可以访问http://localhost:8765/bookmarker/tagged/funny网址,并查看所有标有“funny”的书签。



到目前为止,我们已经创建了一个基本的应用程序来管理书签,标签和用户。 但是,每个人都可以看到其他人的标签。 在下一章中,我们将实现身份验证,并将可见书签限制为仅属于当前用户的书签。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值