overtrue/yaf-skeleton

该包已被废弃,不再维护。未建议替代包。

Yaf 框架的骨架。

资助包维护!
overtrue

1.1.1 2018-07-18 07:39 UTC

This package is auto-updated.

Last update: 2022-07-29 01:48:30 UTC


README

支持 Yaf 框架的测试性骨架和 composer。

Sponsor me

要求

  • PHP >= 7.0
  • Yaf >= 3.0

安装

  1. 更新 yaf.ini
[yaf]
yaf.use_namespace=1
yaf.use_spl_autoload=1
...
  1. 创建项目。
$ composer create-project overtrue/yaf-skeleton myapp -vvv
  1. Web 服务器重写规则

    Apache

    #.htaccess
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule .* index.php
    

    Nginx

    server {
      listen 80;
      server_name  myapp.com;
      root   /path/to/myapp;
      index  index.php index.html index.htm;
    
      if (!-e $request_filename) {
        rewrite ^/(.*)  /index.php/$1 last;
      }
    }
    

    Lighttpd

    $HTTP["host"] =~ "(www.)?myapp.com$" {
      url.rewrite = (
         "^/(.+)/?$"  => "/index.php/$1",
      )
    }
    

应用程序结构

├── .scripts
│   ├── .gitkeep
│   ├── common.sh
│   ├── job_phpcs.sh
│   ├── job_phpmd.sh
│   ├── job_phpunit.sh
│   ├── sami.phar
│   └── sami.php
├── app
│   ├── commands                # sora commands (namespace:\App\Commands)
│   ├── controllers             # Yaf Controllers (namespace:\)
│   ├── exceptions              # Exceptions (namespace:\App\Exceptions)
│   ├── facades                 # Service Facades (namespace:\)
│   ├── plugins                 # Yaf plugins (namespace:\)
│   ├── presenters              # Object presenters (namespace:\App\Presenters)
│   ├── services                # Services, the 3rd service bridges (namespace:\App\Services)
│   ├── traits                  # Traits (namespace:\App\Traits)
│   ├── views                   # Template files
│   ├── helpers.php             # Herlpers
│   ├── Bootstrap.php           # Yaf Bootstrap file
├── config
│   ├── application.ini     # Yaf config file
├── public                  # web extrence
│   └── index.php
├── sora                    # The command line tool
├── tests                   # Unit tests
└── vendor                  #
├── phpunit.xml.dist        # PHPUnit config file
├── .gitignore
├── .php_cs                 # PHP-CS-Fixer config file
├── composer.json
├── composer.lock
├── README.md

控制器

$ ./sora make:controller Foo_Bar # or:foo_bar/FooBar/FooBarController
#
# /www/myapp/app/controllers/Foo/Bar.php Created!
# /www/myapp/tests/controllers/Foo/BarTest.php Created!

所有控制器都创建在 app/controllers 目录中,测试文件也创建在 tests/controllers 目录中。

当然,您也可以独立创建测试:

$ ./sora make:test Foo_Bar # Also supports multiple type controller names
# /www/myapp/tests/controllers/Foo/BarTest.php Created!

handle() 方法

控制器入口方法 handle()

<?php


class ExampleController extends BaseController
{
    public function handle()
    {
        return 'Hello world!';
        // return json(['foo' => 'bar']);
        // return redirect('https://easywechat.com');
        // return view('welcome', ['name' => 'MyApp']); // template engine require.
    }
}

视图

没有内置的模板引擎。如果您需要使用 PHP 模板,我们推荐使用 Plates,Plates 是一个快速、易于使用且易于扩展的本地 PHP 模板系统。

$ composer require league/plates -vvv

您可以在控制器的 handle 方法中使用 view(string $template, array $data) 辅助函数作为结果。

例如

    public function handle()
    {
        $data = [
            'name' => 'overtrue',
            'age' => 28,
        ];

        return view('profile-page', $data);
    }
<!--app/views/profile-page.php:-->

<h1><?= $name ?></h1>
<p><?= $age ?></p>

更多用法请参阅Plates 文档

单元测试

编写单元测试的难度与代码质量成反比。代码质量越高,单元测试的难度越低,因此请设计好您的代码。

创建控制器的单元测试可以使用以下命令:

$ ./sora make:test Foo_BarController

编写测试用例

要创建控制器测试对象,使用 mock_controller 函数。

$controller = mock_controller(Foo_BarController::class);

// Indicates the method to mock, and the protected method is also mockable
$controller = mock_controller(Foo_BarController::class, ['getUsers', 'getApp']);

断言

我们有一个这样的控制器

    ...
    public function handle()
    {
        $params = Request::only('uids', 'screen_name', 'trim_status', 'has_extend', 'simplify', 'is_encoded');

        $users = $this->get('main.users.show_batch', $params);

        return $users;
    }
    ...

因此测试应该涵盖上述三种行为:

public function testHandle()
{
    $input = [
        'uids' => '2193182644',
        'screen_name' => '安正超',
        'trim_status' => 0,
        'has_extend' => 1,
        'simplify' => 0,
        'is_encoded' => 0,
        'foo' => 'bar',
    ];

    Request::shouldReceive('only')
            ->with('uids', 'screen_name', 'trim_status', 'has_extend', 'simplify', 'is_encoded')
            ->andReturn($input);

    $controller = mock_controller(Users_Show_BatchController::class, ['get']); // mock the `get` method

    $controller->shouldReceive('get')->with('main.users.show_batch', array_except($_GET, ['foo']))
                                    ->andReturn('foo')
                                    ->once();

    $response = $controller->handle();

    $this->assertSame('foo', $response);
}

外观断言

Request::shouldReceive('get')->with('mid')->andReturn('mock-mid')->once();
Log::shouldReceive('action')->with(48, 'oid', 'ext')->once();
..

内置辅助断言方法

$this->shouldAbort($message, $code);

它们用于对应控制器中 abort($message, $code); 抛出的异常

测试用例类中的某些辅助方法

模拟请求方法:

$this->method('post');

模拟请求 uri

$this->uri('/foo/bar?uid=12345');

模拟配置:

$this->config('foo', 'bar');

模拟请求 IP:

$this->ip('127.0.0.1');

模拟 $_SERVER 变量:

$this->server('REQUEST_URI', '/foo/bar');

文档

❤️ 赞助我

Sponsor me

如果你喜欢我的项目并想支持它,点击这里 ❤️

由 JetBrains 支持的项目

非常感谢 Jetbrains 慷慨提供许可证,让我能够为这个和其他开源项目工作。

PHP 扩展包开发

想知道如何从零开始构建 PHP 扩展包?

请关注我的实战课程,我会在此课程中分享一些扩展开发经验 —— 《PHP 扩展包实战教程 - 从入门到发布》

许可协议

MIT