获取/设置当前实体的服务

时间:2017-06-05 15:20:50

标签: symfony

我有一个Project实体,它有一个控制器定义了许多路径:

projects/1 projects/1/foo projects/1/bar

我需要一项服务来提供当前项目。用例是我在我的基本树枝模板中有依赖关系,需要知道当前项目。即一个下拉项目选择器,它位于当前控制器正在服务的模板的上下文之外。

我尝试使用$container->get('router.request_context');创建获取路由信息的服务,但是,它只提供路径。如果我不需要,我不想解析路径字符串。

最合适的方法是什么?

2 个答案:

答案 0 :(得分:1)

如果我理解正确,问题的解决方案是渲染/嵌入控制器。当然,它是最简单的,但在某种程度上可接受的解决方案,用于使用除当前模板之外的一些自定义逻辑来呈现html的部分。

您可以阅读rendering/embedding controllers

一些片段......

定义controller:action显然我的例子中的逻辑很简单):

/**
 * Generate select input field.
 *
 * @Route("/widget", name="project_widget")
 * @Method("GET")
 */
public function widgetAction()
{
    $repo = $this->getDoctrine()
        ->getManager()
        ->getRepository('AppBundle:Project');

    // #NOTICE: Wee need master request info, because our widget
    //     is rendered and called as subrequest.
    $masterRequest = $this->get('request_stack')->getMasterRequest();

    // #NOTICE: You need second parameter as default value in case there is no id in masterRequest route.
    $currentProjectId = $masterRequest->get('id', 0);

    $currentProject = $repo->find($currentProjectId);
    $projects = $repo->findAll();

    return $this->render('project/widget.html.twig', [
        'currentProject' => $currentProject,
        'projects' => $projects,
    ]);
}

然后你需要为它创建模板project/widget.html.twig

<div class="widget_project_selection">
    {% if projects is not empty %}
        <select name="widget_project_selection" id="widget_project_selection">
            <option value="">None</option>
            {% for project in projects %}
                <option value="{{ project.id }}"
                    {# #NOTICE: If this is current project, select it #}
                    {{- currentProject and project.id == currentProject.id
                        ? 'selected="selected"'
                        : '' -}}
                >
                    {{- project.title -}}
                </option>
            {% endfor %}
        </select>
    {% else %}
        <span>{{ 'Sadly, no projects yet :('|trans }}</span>
    {% endif %}
</div>

最后(但并非最不重要)将其渲染到base.html.twig中的某处:

{{- render(controller('AppBundle:Project:widget')) -}}

我为你创建了Github repo as reference。这是一个具有类似设置的小型Symfony应用程序。如果您愿意,您甚至可以运行它,不要忘记依赖关系和数据库更新。入口点为/app_dev.php/project/

查看base.html.twig中的widgetActionwidget templateexample usage

编辑:但这不是一切。你说你需要一项服务。如果出于某种原因渲染/嵌入控制器不是您的选择,或者您真的想要使用Service(如在Dependency Container中),您可以extend Twig并使用full power of services

我还以Twig过滤器为例,向您展示了herehere (usage in templates)中Twig Extensions的真正威力。

有关Twig Extensions的更多信息,请查看Twig ExtensionExtending Twig

同时查看service.yml了解服务和扩展定义 - 如果您不使用Symfony3.3 +,还需要做一些额外的工作 - defining service and extension directly

答案 1 :(得分:-1)

在您的控制器中,您可以使用类型提示来加载&#34;当前&#34;实体通过路线。

例如:

#myrouter.yml
current_project:
  path: /projects/{project}

另外,你的控制器......

//mycontroller.php
public function myControllerAction(Request $request, Project $project)
{
    //$project is entity (assuming valid) loaded via the route above
    return $this->render('mytemplate.twig', ['project' => $project]);
}