sands/laravel-presenter

为 Laravel 5+ 以各种格式展示您的响应

1.0.1 2016-09-11 16:35 UTC

This package is not auto-updated.

Last update: 2024-09-14 19:53:02 UTC


README

Laravel 5+ 的自动响应展示器。自动将您的响应发送为 Blade 视图或 JSON。

需要其他类型的响应?请查看下面的插件部分。您也可以创建自己的展示器

安装

$ composer require sands/laravel-presenter

config/app.php 中,将 Sands\Presenter\PresenterServiceProvider 添加到 providers 数组中

'providers' => [
     ...
     Sands\Presenter\PresenterServiceProvider::class,
     ...
]

app/Http/Controllers/Controller.php 中添加 Sands\Presenter\PresentsResponses 特性,以便它可以在所有控制器中使用

// app/Http/Controllers/Controller.php
...
use Sands\Presenter\PresentsResponses;
...
class Controller extends BaseController
{
    use PresentsResponses;
}

用法

假设您有一个由网页和移动端同时使用的控制器 UsersController。对于网页,您希望返回由 Blade 视图生成的 HTML 文档,而对于移动端,您希望返回 JSON 格式的数据。

在控制器的 index 方法中,您可以如此展示数据

public function index()
{
    return $this->present(['users' => User::paginate()])
        ->using('blade', 'json');
}

Laravel 会自动以首选格式返回响应。格式检测通过 Accept 头、通过 format 查询字符串或通过 presentUsing 请求参数完成。

带有 application/json 值的 Accept 请求头将返回 json 格式,而 text/html 将返回渲染的 Blade 视图。

您还可以通过在 URL 中附加 ?format={presenter} 来定义响应类型。这对于下载链接特别有帮助。

或者也可以通过 presentUsing 路由参数定义响应类型

// in your routes file
Route::get('/users/export.{presentUsing}', 'UsersController@index');

因此,当用户访问 users/export.json 路由时,Laravel 会以 JSON 格式返回响应。

自定义数据

有时您可能希望针对不同的展示返回不同的数据。例如,当渲染 Blade 视图时,您可能希望返回分页集合,而当通过 JSON 访问时,您可能希望所有数据都可用。为此,您可以使用以下方法 setOption

public function index()
{
    return $this->present()
        ->setOption('data.blade', 'data')    // call this method to get data for blade
        ->setOption('data.json', 'jsonData') // call this method to get data for JSON
        ->setOption('data', 'data')          // default data method
        ->using('json', 'blade');
}

public function data()
{
    return ['users' => User::paginate()];
}

public function jsonData()
{
    return ['users' => User::all()];
}

默认情况下,展示器会查找 data.{presenterName} 选项,并在控制器上调用该方法以获取数据。如果该选项不存在,则查找 data 选项,并在控制器上调用该方法。如果该选项未设置,则返回在调用 present 时传递的数据。

为了避免对所有数据方法调用昂贵的 DB 操作,该方法仅在展示器 render 方法调用之前调用。这是在控制器上下文之外完成的。由于数据方法是在控制器之外调用的,因此方法的可见性应该是 public

您应该考虑到 Laravel 5.0 - 5.2 控制器方法的命名约定,以便通过 Route::controller 注册的控制器不会意外地将这些数据方法暴露为路由。

您还可以将这些方法放入单独的特性文件中,以便控制器不会因数据方法而变得杂乱。

内置展示器

默认情况下,Sands\Presenter 随附三个默认展示器

  • blade (html)
  • json

您可以安装额外的插件。或者根据需要创建自己的展示器。

Blade 视图响应

Blade视图路径自动从完全限定的控制器类名称计算得出,移除了App\Http\Controllers\前缀和Controller后缀,以及控制器当前调用的方法。例如,调用App\Http\Controllers\Auth\FacebookAuthController@show方法时,将加载Blade视图auth.facebook-auth.show

在调用present时可以通过调用setOption方法来覆盖控制器前缀。

namespace App\Controllers;
...
public function index()
{
    return $this->present(['users' => User::paginate()])
        ->setOption('controllerPrefix', 'App\\Controllers')
        ->using('blade', 'json');
}

在调用present时可以通过调用setOption方法来覆盖控制器后缀。

class UsersControllers {
...
public function index()
{
    return $this->present(['users' => User::paginate()])
        ->setOption('controllerSuffix', 'Controllers')
        ->using('blade', 'json');
}

在调用present时可以通过调用setOption方法来覆盖视图路径。

public function index()
{
    return $this->present(['users' => User::paginate()])
        ->setOption('view', 'some.blade.path')
        ->using('blade', 'json');
}

JSON响应

JSON响应将返回传递给它的数据作为JSON。这对移动应用来说特别有用。

格式化JSON

可选地,您可以使用spatie/laravel-fractal包(本包不包括此包)来转换JSON,方法是告诉展示器使用自定义的JSON数据方法。

public function index()
{
    return $this->present()
        ->setOption('data', 'data')
        ->setOption('data.json', 'jsonData') // call this method to get data for JSON
        ->using('json', 'blade');
}

public function jsonData()
{
    return [
        'users' => fractal()
            ->collection(User::all()
            ->transformWith(new UserTransformer())
            ->toArray();
    ];
}

创建您的展示器

创建自己的展示器非常简单。您的自定义展示器类需要实现Sands\Presenter\PresenterContract接口。展示器合同将期望您的实现有一个__constructrender方法。必须返回一个Illuminate\Http\Response实例或可以被它消费的数据的实例。

__construct方法将presenter实例作为唯一参数。通常您会将presenter附加为类属性。

use Sands\Presenter\Presenter;
use Sands\Presenter\PresenterContract;
...
class PdfPresenter implements PresenterContract {
    public function __construct(Presenter $presenter)
    {
        $this->presenter = $presenter;
    }
...

所有响应都是延迟实例化的。这意味着只有在展示器的render方法需要被调用时,展示器才会被加载和实例化。

render方法将有一个传递为第一个参数的$data变量。必须返回一个Illuminate\Http\Response实例或可以被该类消费的值。

public function render($data = [])
{
    $viewPath = $this->presenter->getOption('view.pdf');
    return PDF::loadView($viewPath, $data)->stream();
}

可用选项

通常,用户通过使用setOption方法设置选项。这些选项可以通过调用$this->presenter->getOption('key')方法在您的自定义展示器中使用,其中key是您正在查找的选项。如果未设置选项,则返回null

要获取所有选项,使用$this->presenter->getOptions()方法。

默认情况下,这些选项可用

  1. controllerPrefix: App\Http\Controllers
  2. controllersSuffix: Controllers
  3. controller: 当前调用的控制器,例如:App\Http\Controllers\UsersController
  4. method: 当前调用的控制器方法,例如:index
  5. routeParams: 当前路由参数。

注册您的展示器

要注册您的展示器,只需调用register方法

app('sands.presenter')->register('pdf', [
    'presenter' => \App\Presenters\Pdf::class,
    'mimes' => [ // optionally bind to these mimes
        'application/pdf',
    ],
    'extensions' => [ // optionally bind to these extensions
        'pdf'
    ],
    'options' => [] // options to be included in the $presenter instance
]);

通常您应该在Sands\Presenter\PresenterServiceProvider之后加载的服务提供者中注册您的展示器。

可用插件

MIT许可证

版权所有(c)2016 Sands Consulting Sdn Bhd

特此授予任何获得本软件及其相关文档文件(以下简称“软件”)副本的人免费使用软件的权利,不受限制,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本,以及允许获得软件的人进行此类操作,前提是遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

本软件按“原样”提供,不提供任何形式的保证,无论是明示的还是暗示的,包括但不限于适用性、特定用途的适用性和非侵权性保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任承担责任,无论是基于合同行为、侵权行为或其他方式,无论该索赔、损害或其他责任源于、产生于或与该软件或对该软件的使用或其他使用方式有关。