这是一篇发布时间大于两年的文章,当时的一些内容或笔者曾经的思维可能已不再适用于现在,请谨慎判断文章内容的可靠性


0-开始使用 Slim

为何使用 Slim 而不去使用众多流行使用广泛的 PHP 框架例如 Laravel 等等?因为目的是学习,而不是快速开发完成一个产品,学习的目的是了解某个功能在 PHP 代码中具体是怎样实现的,若使用 Laravel,其功能繁多,封装程度极高,以及框架中许多方便开发者使用的语义化方法、类等,都不利于我们学习基础知识。而使用 Slim,其只实现了基本的 router,request,response,dependency container 等等一些最最基本的功能,我们可以使用这个简单的骨架为基础开发扩展实现自己所需要的应用。

上手 Slim Framework

首先使用composer创建

composer create-project slim/slim-skeleton php auth

进入目录会发现生成了如下文件结构

.
├── public
│   └── index.php
├── src
│   ├── dependencies.php
│   ├── middleware.php
│   ├── routes.php
│   ├── settings.php
└── templates
    └── index.phtml

public/index.php为入口文件,所有的请求都会从此进入;src目录为项目代码的核心部分,绝大部分工作代码编写在此完成;templates为模板目录编写视图。首先看看public/index.php的内容:

<?php
if (PHP_SAPI == 'cli-server') {
    // 在使用PHP内置的cli-server时检查请求是否为静态文件
    $url  = parse_url($_SERVER['REQUEST_URI']);
    $file = __DIR__ . $url['path'];
    if (is_file($file)) {
        return false;
    }
}
// 加载composer autoload
require __DIR__ . '/../vendor/autoload.php';
// 开始session(session是用户认证的关键)
session_start();
// 使用`src/settings.php`的配置文件实例化Slim app
$settings = require __DIR__ . '/../src/settings.php';
$app = new \Slim\App($settings);
// 加载dependencies
require __DIR__ . '/../src/dependencies.php';
// 注册中间件
require __DIR__ . '/../src/middleware.php';
// 注册路由
require __DIR__ . '/../src/routes.php';
// 运行
$app->run();

运行命令,指定从public目录启动服务器:

php -S localhost:8080 -t public

浏览器访问localhost:8080可以得到默认的模板文件index.phtml的内容。

使用路由 router

不同 URI 的请求是通过routes.php中定义的路由所控制的,默认生成如下:

$app->get('/[{name}]', function (Request $request, Response $response, array $args) {
    // 日志记录
    $this->logger->info("Slim-Skeleton '/' route");
    // 渲染视图
    return $this->renderer->render($response, 'index.phtml', $args);
});

这里定义了一个 GET 请求的路由,所匹配为动态路由,{name}为定义的参数,例如访问localhost:8080/hello那么这个hello会作为参数传入,并在index.phtml模板中使用$name访问这个值

使用控制器 controller

我们不可能将所有的匹配到路由后的处理逻辑都写在这个路由定义文件中,因此一般的做法是使用控制器 Controller,在src/目录下新建一个Controller目录,新建HomeController.php,并在新建的控制器类中新建一个方法以处理路由匹配到后要作如何处理。为了在每个控制器中都能够访问到 container,可以定义一个 BaseController,编写构造函数传入 container:

<?php
namespace App\Controller;

use Slim\Container;

class Controller
{
    protected $container;
    public function __construct(Container $c)
    {
        $this->container = $c;
    }
}

然后定义自己的 Controller 继承这个 BaseController

<?php
namespace App\Controller;

use Slim\Http\Request;
use Slim\Http\Response;

class HomeController extends Controller
{
    public function index(Request $request, Response $response)
    {
        return $this->container->renderer->render($response, 'home.phtml', $args);
    }
}

然后在routes.php中修改为:

$app->get('/home', '\App\Controller\HomeController:index');

此时并不能运行起来,因为新建的目录和类并没有被自动加载,若运行会提示找不到这个类。因此在composer.php中添加一项:

{
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
}

意味 composer 会自动注册src目录下符合 psr-4 标准的App\命名空间下的类,接着运行

composer dump-autoload

就可以正常运行了