PHP __invoke 使用

2023-08-23 18:49:23 浏览数 (2)

why they are magic? Because they are magically called by PHP when specific actions happen.

The __invoke() method is called when a script tries to call an object as a function.

代码语言:javascript复制
<?php
class CallableClass
{
    public function __invoke($x)
    {
        var_dump($x);
    }
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
代码语言:javascript复制
int(5)
bool(true)

使用明显的操作方法初始化

例如,当我们有一个提供者时,就会发生这种情况。

aws-sdk-php/src/Endpoint/PatternEndpointProvider.php

代码语言:javascript复制
public function __invoke(array $args = [])
{
    $service = isset($args['service']) ? $args['service'] : '';
    $region = isset($args['region']) ? $args['region'] : '';
    $keys = ["{$region}/{$service}", "{$region}/*", "*/{$service}", "*/*"];

    foreach ($keys as $key) {
        if (isset($this->patterns[$key])) {
            return $this->expand(
                $this->patterns[$key],
                isset($args['scheme']) ? $args['scheme'] : 'https',
                $service,
                $region
            );
        }
    }

    return null;
}

它使用 invoke 使用一些参数提供端点。我们如何使用这个类?

代码语言:javascript复制
public function testReturnsNullWhenUnresolved()
{
    $e = new PatternEndpointProvider(['foo' => ['rules' => []]]);
    $this->assertNull($e(['service' => 'foo', 'region' => 'bar']));
}

尝试使用单动作控制器?

控制器应该大而广泛?他们不应该。我们应该有瘦控制器和胖服务。

在这里,invoke 可以帮助我们,因为我们可以定义一个只处理单个动作的控制器,并在其上放置单个 invoke 方法。

这也有助于我们实现单一职责原则,即 SOLID 中的 S,这是前五个面向对象设计 (OOD) 原则的首字母缩写词。

A class should have one and only one reason to change, meaning that a class should have only one job.

在 Laravel 中的例子:Single Action Controllers | laravel:

代码语言:javascript复制
<?php

namespace AppHttpControllers;

use AppUser;
use AppHttpControllersController;

class ShowProfile extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return View
     */
    public function __invoke($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

然后,在注册路由时,我们不需要指定方法名称。只有类名。

代码语言:javascript复制
<?php
Route::get('user/{id}', 'ShowProfile');

This way we can have Single Action Controllers.

References

  • PHP invoke: is anybody using it? | medium
  • __invoke() | php

– EOF –

  • # php

0 人点赞