用于消除 Symfony2 中重复代码的特性、辅助服务或继承

Traits, helper service or inheritance for eliminating repetitive code in Symfony2

我正在尝试清理一个旧的 Symfony2 项目,其中大部分代码都在控制器中。控制器中长而重复的代码块不是最佳选择,它使调试和开发非常乏味且容易出错。

有很多东西我可以轻松清理并转移到服务中,因为这些代码块提供了某种可重用的功能。我知道任何明确定义的任务都应该存在于服务中,而控制器应该只是 "wiring".

但无论我将代码移到哪里,总会有重复的小块把一切搞得一团糟。例如 initialization/transformation/parsing/filtering 模式,在我们的应用程序中广泛使用。

以创建DataTable需要的数据"kneading"为例:

class DefaultController extends Controller {

    public function indexAction() {

        $data = array(/* some data */);

        $encoders = array(new JsonEncoder());
        $normalizers = array(new GetSetMethodNormalizer());
        $serializer = new Serializer($normalizers, $encoders);
        $datatable = $this->get('datatables.orders');
        $datatable->buildDatatableView();
        $datatable->setData($serializer->serialize($data, 'json'));

        return array('datatable'=>$datatable);
    }
}

这是一种非常常见但也非常冗长的模式。我们的开发人员倾向于将数十种此类小模式存储在他们自己计算机上的文本文件中,并且通常 copy/paste 将它们存储到控制器中。

如果我想出使代码更简洁(和 DRY)的解决方案,有多种选择。

考虑一下:

Bundle/Traits/TableTrait.php

Trait TableTrait {
    function serialize($data, $format){
        $encoders = array(new JsonEncoder());
        $normalizers = array(new GetSetMethodNormalizer());
        $serializer = new Serializer($normalizers, $encoders);
        return $serializer->serialize($data, $format);
    }

    function buildTable($table, $data){
        $datatable = $table;
        $datatable->buildDatatableView();
        $datatable->setData($this->serialize($data, 'json'));
    }
}

Bundle/Controller/SomeController.php

class DefaultController extends Controller {

    use \Bundle\Traits\TableTrait;

    public function indexAction() {

        $data = array(/* some data */);
        $datatable = $this->buildTable($this->get('datatables.orders'),$data);

        return array('datatable'=>$datatable);
    }
}

将 6 行样板文件减少到 1 行。

Traits 是一个不好的解决方案吗? 如果是这样,哪个选项会更好?

您可能会考虑将一些东西转移到服务中。例如:

$serializer = $this->get('json.getset.serializer');

并可能制作数据 table 工厂服务

$dataTable = $this->get('datatable.orders.factory')->create($data);

您甚至可以更进一步,将您的控制器定义为服务,然后注入所需的依赖项。所以你最终会得到:

$dataTable = $this->dataTableFactory->create($data);