从存储库加载可重用数据的最干净方法是什么?

时间:2019-04-07 17:31:43

标签: php symfony doctrine-orm

我在symfony中有一个菜单栏,该菜单栏已加载到项目中的每个站点。通常我会这样加载数据:

/**
 * @Route("", name="main")
 * 
 * 
 */
public function main()
{
    $category_rep = $_om->getRepository(Category::class);
    $this->categories = $category_rep->findAll();
    ....
}

很好,但是我正在寻找更好的解决方案以将数据加载到整个控制器或项目中。我找到了通过以下方式自动加载数据的解决方案:

@Entity("category", expr="repository.find($id)")
public function index(Category $category)

但是它只能给我一个类别实体的结果(在菜单栏中,我想显示存储库中的所有类别)。第二个想法是控制器中的make构造函数,它像这样加载数据:

private $categories;

public function __construct(ObjectManager $_om)
{
    $category_rep = $_om->getRepository(Category::class);
    $this->categories = $category_rep->findAll();

}

或制作将加载该数据并以每种方法运行该服务的服务。我想问一下哪个想法是最好的(“最干净的”)解决方案。也许这是另一个更好的选择?

感谢您的帮助, 克里斯

2 个答案:

答案 0 :(得分:0)

一个简单的解决方案可能是单独的控制器操作,以获取菜单的类别,例如:

class MenuController extends AbstractController
{    
    public function displayMainMenu()
    {
        $categories = $this->getDoctrine()->getRepository(Category::class)->findAll();

        return $this->render('menu/main.html.twig', [
            'categories' => $categories,
        ]);
    }
}

这将返回仅包含菜单HTML的部分模板,如下所示:

# menu/main.html.twig

{% for category in categories %}
    <div>
        <a href="{{ path('/url/to/view/category/with/id', { id: category.id }) }}">
            {{ category.name }}
        </a>
    </div>
{% endfor %}

现在您只需要在embedding the controller之前的base.html.twig中包含该渲染的模板:

<div class="menubar">
    {{ render(controller('App\\Controller\\MenuController\\displayMainMenu')) }}
</div>

对于更高级的菜单,您可以考虑使用专用的套装,例如KnpMenuBundle

答案 1 :(得分:0)

创建custom Twig Function也是另一种方法,也很简单,但更加优雅(imho),如下所示:

class MenuExtension extends AbstractExtension
{
    private $categories;

    public function __construct(CategoryRepository $categories)
    {
        $this->categories = $categories;
    }

    public function getFunctions()
    {
        return [
            new TwigFunction(
                'main_menu',
                [$this, 'mainMenu'],
                ['needs_environment' => true]
            ),
        ];
    }

    public function mainMenu(\Twig_Environment $environment)
    {
        $categories = $this->categories->findAll();

        return $environment->render('menu/main.html.twig', [
            'categories' => $categories,
        ]);
    }
}

当然,您还需要菜单本身的模板,就像上一个答案一样:

# menu/main.html.twig

{% for category in categories %}
    <div>
        <a href="{{ path('/url/to/view/category/with/id', { id: category.id }) }}">
            {{ category.name }}
        </a>
    </div>
{% endfor %}

现在您可以在base.html.twig中使用自定义功能了:

<div class="menubar">
    {{ main_menu() }}
</div>