Php 类、闭包和可调用项

Php 类、闭包和可调用项,php,Php,我编写了一个抽象类,用于处理应用程序模型的持久化。该代码是通用的,可用于应用程序的任何模型。然而,一些模型需要一些特定的处理,这超出了模型类的范围或抽象类的功能。具体的处理由扩展抽象类的类负责 因此,我需要抽象类能够调用扩展类中定义的函数,该函数将执行所需的特定处理。下面是一些有效的示例代码。但我不确定这是否是正确的方法(我尝试了许多不同的方法,但这是我唯一成功地开始工作的方法) 我的问题是: 对于persistModel()方法,在参数列表中使用Closure类型是否正确 Closure::f

我编写了一个抽象类,用于处理应用程序模型的持久化。该代码是通用的,可用于应用程序的任何模型。然而,一些模型需要一些特定的处理,这超出了模型类的范围或抽象类的功能。具体的处理由扩展抽象类的类负责

因此,我需要抽象类能够调用扩展类中定义的函数,该函数将执行所需的特定处理。下面是一些有效的示例代码。但我不确定这是否是正确的方法(我尝试了许多不同的方法,但这是我唯一成功地开始工作的方法)

我的问题是:

  • 对于
    persistModel()
    方法,在参数列表中使用
    Closure
    类型是否正确
  • Closure::fromCallable([$this,'getPostFilename'])
    是将
    getPostFilename()
    方法传递到
    persistModel()
    方法中的最佳(正确)方法吗
  • 我意识到这些问题是在征求一些意见,但我认为这些问题和答案可能会对其他像我这样的人有所帮助

    工作示例代码:

    class Post
    {
    }
    
    abstract class FacadeAbstract
    {
        protected function persistModel(string $className, array $data, Closure $callabel = null)
        {
            $model = new $className();
    
            if (is_callable($callabel)) {
                echo $callabel($model);
            }
        }
    }
    
    class PostFacade extends FacadeAbstract
    {
        public function createPost(array $data)
        {
            $this->persistModel(Post::class, $data, Closure::fromCallable([$this, 'getPostFilename']));
        }
    
        public function deletePost(array $data)
        {
            $this->persistModel(Post::class, $data);
        }
    
        private function getPostFilename(Post $model): string
        {
            return "the_file_name.json\n";
        }
    }
    
    class Controller
    {
        public function actionGET(array $data)
        {
            $facade = new PostFacade();
            $facade->createPost($data);
        }
    }
    
    $controller = new Controller();
    echo $controller->actionGET(['slug' => 'context/title']);
    

    请回答您的问题:

    在我看来,类型提示更灵活。当然,这需要使用
    call\u user\u func()
    ,而不仅仅是调用
    $callabel()

    function persistModel(callable $callabel = null)
    {
        if ($callabel !== null) {
            call_user_func($callabel, $model);
        }
    }
    
    使用
    callable
    时,您不再需要
    Closure::fromCallable()
    ,只需调用

    $this->persistModel([$this, 'getPostFilename']);
    
    注1:当调用
    $callabel
    确实是
    persistModel
    中的最后一个操作时,我只需返回
    $model
    变量并调用
    createPost
    中的
    getPostFilename
    。但最有可能的是,您给定的代码被极度简化,而且还有更多

    注2:看看策略设计模式(谷歌会给出很多例子),也许这会带来更简洁的解决方案。

    我尝试过你的建议(这是我以前尝试过的方法之一),但将数组传递给
    $this->persistModel(Post::class,$data,[$this,'getPostFilename'])时出错-传递给FacadeAbstract::persistModel()的参数3必须是可调用的或空的,如果您的建议有效,则必须将
    getPostFilename()
    方法的范围扩大到
    受保护的