culturegr/presenter 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

culturegr/presenter

Composer 安装命令:

composer require culturegr/presenter

包简介

Eloquent Model Presenter for Laravel applications

README 文档

README

Latest Version on Packagist Total Downloads Github Actions

This package provides an easy way to create Presenters that can be used to decorate an Eloquent Model. It is heavily inspired by Hemp Presenter and Laravel API Resources, however it comes with some key differences:

  • It provides an easy way to handle paginated models
  • It does not focus solely in JSON API responses but it serves as a general purpose decorator that can be used anywhere in the project

TL;DR

A Decorator is an object that wraps another object in order to add functionality to the wrapped object. It also delegates calls to methods not available on the decorator to the class being decorated. Decorators can be useful when you need to modify the functionality of a class without relying on inheritance. You can use it to add optional features to your objects like logging, access-control, and things of that sort. A Presenter is a type of decorator used to present an object to the view of an application, such as a Blade view, or an API response.

Installation

Via Composer:

$ composer require culturegr/presenter

In Laravel 5.5+, the package's service provider should be auto-discovered, so you won't need to register it. If for some reason you need to register it manually you can do so by adding it to the providers array in config/app.php:

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

Usage

Creating Presenter Classes

A Presenter class can be generated by running the make:presenter Artisan command:

php artisan make:presenter UserPresenter

This will generate an empty Presenter class inside of app/Presenters

Customizing Presenter Classes

Presenters are simple classes designed to encapsulate complex or repetitive view logic. For example, here is a simple UserPresenter class:

<?php

namespace App\Presenters;

use CultureGr\Presenter\Presenter;

class UserPresenter extends Presenter
{

    public function fullname()
    {
        return $this->firstname.' '.$this->lastname;
    }
}

Note that the original model's properties (firstname, lastname) can be directly accessed using the $this variable. This is because the Presenter class automatically proxies property and method access down to the underlying model.

This class has a custom method fullname that can be called wherever an instance of this Presenter is used.

$presentedUser->firstname; //=> 'John'
$presentedUser->lastname; //=> 'Doe'
$presentedUser->fullname() //=> 'John Doe'

The Presenter class requires you to implement an abstract toArray method which returns the array of attributes that should be used when the presenter is converted to an array or JSON. This ensures consistent behavior across all presenter classes.

<?php

namespace App\Presenters;

use CultureGr\Presenter\Presenter;

class UserPresenter extends Presenter
{
    public function fullname()
    {
        return $this->firstname.' '.$this->lastname;
    }

    public function toArray()
    {
        return [
            'id' => $this->id,
            'fullname' => $this->fullname()
             // ...
        ];
    }
}

Presenting Single Models

Once the presenter is defined, it may be used to create a presented model using the make factory method:

$user = User::first();
$presentedUser = UserPresenter::make($user);

The presented model may be used anywhere in the project and can be passed to views, returned from controllers, or returned from API routes. Presenters implement Arrayable, Jsonable, JsonSerializable, and ArrayAccess interfaces, which means they can be:

  • Automatically converted to arrays when needed (no need to call toArray() explicitly)
  • Automatically converted to JSON when returned from routes (no need to call toJson() explicitly)
  • Accessed like arrays using square bracket notation (e.g., $presenter['key'])
<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Presenters\UserPresenter;

class UserController extends Controller
{
    public function show($id)
    {
        // No need to call toArray() - automatic conversion happens when needed
        return view('users.show', [
            'user' => UserPresenter::make(User::find($id))
        ]);
    }
}

Presenting Collections

To present a collection of models, the static collection method on the Presenter class can be used:

$users = User::all();
$presentedUsers = UserPresenter::collection($users);

The collection of presented models may be used anywhere in the project. Thanks to the automatic conversion features, the collection can be directly returned from a route or controller without explicitly calling toArray():

<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Presenters\UserPresenter;

class UserController extends Controller
{
    public function index()
    {
        $users = User::all();

        return UserPresenter::collection($users);
    }
}

The output will be something like this:

[
    {"id": "1", "fullname": "John Doe"},
    {"id": "2", "fullname": "Jane Doe"}
]

Presenting Paginated Collections

To present a paginated collection of models with pagination metadata, the static pagination method on the Presenter class can be used:

$users = User::paginate();
$presentedUsers = UserPresenter::pagination($users);

The paginated collection of presented models may be used anywhere in the project and can be directly returned from a route or controller:

<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Presenters\UserPresenter;

class UserController extends Controller
{
    public function index()
    {
        $users = User::paginate();

        return UserPresenter::pagination($users);
    }
}

The output will contain the presented models wrapped in a data key, along with links and meta keys containing pagination information:

{
    "data": [
        {"id": "1", "fullname": "John Doe"},
        {"id": "2", "fullname": "Jane Doe"}
    ],
    "links":{
        "first": "http://example.com/pagination?page=1",
        "last": "http://example.com/pagination?page=1",
        "prev": null,
        "next": null
    },
    "meta":{
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://example.com/pagination",
        "per_page": 15,
        "to": 10,
        "total": 10
    }
}

Using the Presentable Trait

The package provides a Presentable trait that can be used to present models directly from the model instance. This allows for a more elegant syntax when presenting models, collections, and paginators.

To use the trait, first add it to your model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use CultureGr\Presenter\Presentable;

class User extends Model
{
    use Presentable;

    // ...
}

Then you can present the model directly using the present method:

$user = User::first();
$presentedUser = $user->present(UserPresenter::class);

This allows for a more fluent syntax when presenting models:

$presentedUser = User::first()->present(UserPresenter::class);

For collections, you can use the presentCollection method directly on the collection:

$users = User::all();
$presentedUsers = $users->presentCollection(UserPresenter::class);

This is equivalent to using the static collection method on the Presenter class, but provides a more fluent API.

You can also use the presentCollection method directly on a paginator instance:

$users = User::paginate();
$presentedUsers = $users->presentCollection(UserPresenter::class);

When used on a paginator, the presentCollection method automatically detects that it's being called on a paginator and returns a structured result with the presented models wrapped in a data key, along with links and meta keys containing pagination information.

Automatic Array and JSON Conversion

Presenters now implement the necessary interfaces to be automatically converted to arrays or JSON when needed:

  • Arrayable: Allows automatic conversion to arrays
  • Jsonable: Allows automatic conversion to JSON strings
  • JsonSerializable: Ensures proper JSON serialization
  • ArrayAccess: Allows accessing presenters like arrays using square bracket notation

This means you no longer need to explicitly call toArray() or toJson() in most contexts:

// Before
$array = $presenter->toArray();
$json = $presenter->toJson();

// Now - automatic conversion happens when needed
$array = $presenter; // Automatic conversion to array
$json = json_encode($presenter); // Automatic conversion to JSON
return $presenter; // Automatic conversion when returned from routes

Array Access Support

Presenters can now be accessed like arrays:

$presenter = UserPresenter::make($user);
$id = $presenter['id']; // Same as $presenter->id

Abstract toArray Method

The toArray() method is now abstract, which means all presenter classes must implement it. This ensures consistent behavior across all presenters.

Note for Existing Users

If you're currently calling toArray() explicitly when using Presenters (e.g., UserPresenter::make($user)->toArray()), please note that these calls will continue to work as before. However, they are no longer necessary in most contexts due to the new automatic conversion feature. You can safely remove these explicit calls if desired, which will make your code cleaner and more concise.

Testing

$ composer test

License

Please see the license file for more information.

Credits

culturegr/presenter 适用场景与选型建议

culturegr/presenter 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.37k 次下载、GitHub Stars 达 14, 最近一次更新时间为 2019 年 11 月 12 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「laravel」 「presenter」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 culturegr/presenter 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 culturegr/presenter 我们能提供哪些服务?
定制开发 / 二次开发

基于 culturegr/presenter 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 1.37k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 14
  • 点击次数: 8
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 14
  • Watchers: 4
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2019-11-12