人人都能看懂的全栈开发教程——框架

人人都能看懂的全栈开发教程——框架

Chris Yue No Comment
Posts

回顾一下我们项目的开发历程,我们为了追求安全性,可维护性,稳定性,代码复用,分工等各种目的,做了很多事情,而这些事情似乎都是每个项目都必须要做的。难道每开始一个新的项目时都需要把这些要点再重新实现一遍吗?更可气的是,这些事情虽然不得不做,但实际上跟业务一点关系也没有,所以程序员往往会有这样的尴尬,你已经为了项目忙活儿了半天,但就因为还没涉及到业务,在老板眼里你好像还啥都没干似的……有没有办法可以让我们能更快的把注意力集中到业务本上,而将我们对一切纯技术的美好追求都总结成某种能复用的代码呢?

既然编程这个职业都工程化这么多年了,这点问题当然不是问题,不仅可以做,而且很多人已经帮你做好了。

『开发框架』就是基于这样考虑的一种产物,它不仅仅是一些可复用的代码,而且它还带来了解决某种开发问题的解决方案,或者说开发模式。

但因为每个人有每个人不同的考虑,导致目前的框架五花八门,我们即使做了筛选,把问题限定为开发 HTTP Web 应用(网站就是),并且限定语言只有 PHP,你能选择的框架也很多。我稍稍回忆了一下,正儿八经用来做过项目的就有 LaravelYii2SymfonyZendFramework(现在改叫 Laminas 了)。除了这些标准框架,我对一些面向具体业务的产品也做过不少二次开发,比如电商相关的有商派,Magento,内容管理系统有 Joomla,WordPress。二次开发的那些产品虽然不算框架,但各自也都有自成一体的开发解决方案,所以我也把他们算到里面。

出于让读者学习和了解框架的原则,我这里会选择 Symfony。我曾经见网上有人说 Symfony 入门难,我持有不同的意见:第一我没有觉得 Symfony 难,从经验上来说,Symfony 只是跟传统的框架用法有一点不同而已,接受了这些不同实际没什么难的;第二我觉得很多人对其他很多框架的作出『简单』的评价,是基于『作出网页』这个目的来说的,这些框架可能提供了某些技巧,让『作出网页』这个目标更容易实现,但就如我经常说的,学习的时候,最好不要用一些看上去『魔法』太多的工具,它们隐藏了太多细节,让你『知其然而不知其所以然』,我希望我的读者都不用死记硬背,而是能多了解原理并且融会贯通。

其实所有的框架,近了看各有各的不同,但远了看也能看出相似。如果你掌握了一个框架,实际上再换别的框架的时候也会很容易,而且现在框架也都在相互借鉴,以后估计会越来越相似。

接下来我们尝试安装 Symfony。因为使用框架之后,项目文件目录结构变化会很大,为了方便我打算直接创建另外一个新项目,就叫 minetodo 吧,但我们这次不需要自己创建目录,利用之前用的 Composer,我们执行下面的命令

composer create-project symfony/website-skeleton minetodo

注:依然可以用 -vvv 参数关注命令执行进度。

不同于我们之前通过 Composer 的 require 命令安装 PHPUnit,通过 create-project 来创建项目不但包含项目所默认依赖的所有库文件,还包括了项目的目录结构,以及默认的文件。

在执行完命令之后进入 minetodo 目录,可以发现里面已经有很多文件(夹),先不管它们分别是做什么的,我们先执行命令:

bin/console --version

bin/console 是 Symfony 框架自带的命令行工具,后面可以看到此工具的很多用法,提高我们的开发效率。如果一切正常,上面的命令会返回版本号,到我写这篇文章的时候,是 5.0.4。版本号不一样可能会有一些功能的命令不一样,这里告诉大家一个规则,对于这种三段式版本号来说,只要第一位不变,理论上用法就应该不变,所以大家安装项目时也尽量用 5.* 的版本,可以通过下面的命令来指定创建项目时你打算用的版本号:

composer create-project symfony/website-skeleton minetodo "5.*"

框架搭建好之后,我们一点点把代码移过来。

首先最容易移的,理论上是 Domain 里面的代码。按照我们之前的计划,Domain 里面的代码只关心业务逻辑本身,所以跟用什么框架也没什么关系。另外,我们的 tests 里的测试也只是测试了 Domain 里的代码的逻辑,所以怎么挪也是同样的做法。实际上这里应该能想得到,既然业务代码哪儿都能用,是不是可以把它也变成一个库,通过 Composer 来安装,不仅在 Symfony 里能用,Laravel 里也能用?这个想法是没有问题的,我们的确可以这么做,只不过在本例子里,就先不考虑完全独立出去这种做法了,就直接先在新项目里创建一个 domain 目录,表示里面都是业务相关代码,然后把文件挪过去即可,挪完之后,文件目录结构应该是这样的

minetodo/
  ..
  domain/
    tests/
      Domain/
        UserManagerTest.php
    BadCredentialException.php
    PasswordEncoderInterface.php
    UserManager.php
    UsernameExistsException.php
    UserNotFoundException.php
    UserRepositoryInterface.php
  ..

别忘了在 composer.json 文件里,添加载入规则:

{
    ...
    "autoload": {
        "psr-4": {
            "App\\": "src/", // <-- 也别忘了这个逗号
            "Domain\\": "domain/"
        }
    }
    ...
}

同样,执行 composer dump-autoload 命令生成自动加载文件。

我们可以尝试测试一下我们的业务类还好不好用,因为 Symfony 5 封装了 PHPUnit,用来增加一些针对 Symfony 项目相关的检查,所以读者很有可能在 vendor/bin/ 目录下找不到 phpunit 但能看到一个 simple-phpunit ,实际上都是一样的用法。我们先运行一下

vendor/bin/simple-phpunit

第一次直接运行的目的是为了让 simple-phpunit 去安装 PHPUnit,应该是从 Symfony 5 开始 PHPUnit 没有被默认安装,但执行一次 simple-phpunit 就会被安装上。这个时候我们再执行

vendor/bin/simple-phpunit domain/tests/

正常情况还是可以用的。simple-phpunit 只增加了功能,并没有删除功能,都一样的用。

注意上面的命令我们并没有指定文件名,如果只指定目录,意思就是挨个执行指定目录下所有的测试文件。这并不是 simple-phpunit 独有的,本身 PHPUnit 就有这个功能。

接下来我们应该把剩下的没挪的都挪过来,不过先不着急,遇到一个新的工具时,我们应该先『把玩』一下,了解一下工具怎么使用。

先来了解一下 Symfony 框架里如何添加控制器。我们在 src/Controller 目录里创建一个文件 TaskController.php,然后在这个文件里加入下面的内容,注意注释:

<?php

namespace App\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;

class TaskController
{
    /**
     * 虽然看上去这是 PHP 的注释,不过 Symfony 里是可以识别 @ 开头的注释,转换成类似配置文件的东西
     * 下面这句的意思是,将此方法与路径 / 绑定,即访问首页时,就执行此方法
     * 并且,此方法所接受的 HTTP 方法只有 GET
     * @Route("/", methods={"GET"})
     */
    public function indexAction()
    {
        // Response 类表示返回给用户的内容,我们现在只返回 Hello world 给用户
        return new Response('Hello world');
    }
}

此时,我们先确认在旧项目里已经停止了 Web 服务,然后我们再去新项目的 public 目录,开启 Web 服务,命令依然一样:

php -S localhost:8000

此时我们再访问首页,不出意外应当看到 Hello world 出现。

虽然我们现在还没有完全把网站移到新的项目,但好消息是我们已经能正常用上 Symfony 框架了。接下来我们再通过进一步的项目迁移,来了解 Symfony,或者说框架,到底能为我们做什么。

本章代码完整源代码见这里

人人都能看懂的全栈开发教程——框架 by Chris Yue is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

微信赞赏码

写作累,服务器还越来越贵
求分担,祝愿好人一生平安
天使打赏人

发表评论

73 − 69 =