I'm running the equivalent of this code in lots and lots of controller actions, basically it grabs the user's username, and if that username is attached to a blog entity it will allow the user to see the blog entity(s):
我在很多很多控制器动作中运行相当于这段代码,基本上它抓住用户的用户名,如果该用户名附加到博客实体,它将允许用户查看博客实体:
$em = $this->getDoctrine()->getManager();
$user = $this->get('security.context')->getToken()->getUser();
$entities = $em->getRepository('MySiteBundle:Blog')->findBy(array('user' => $user));
return $this->render('MySiteBundle:Blog:index.html.twig', array(
'entities' => $entities,
I want to move it into a service so I can cut down on code repetition. I want to avoid doing as much logic in my controllers as possible.
我想把它转移到服务中,这样我就可以减少代码重复。我想避免在控制器中尽可能多地使用逻辑。
That being said, I'm not sure how I can access the user session and doctrine in a service.
话虽这么说,我不确定如何在服务中访问用户会话和学说。
Here's my services.yml:
这是我的services.yml:
mysite.user.blog:
class: MySite\SiteBundle\Services\BlogUser
And here's how I was attempting to call it in the controller:
以下是我试图在控制器中调用它的方式:
public function testAction() {
$response = $this->get('mysite.user.blog');
return new Response($response);
}
I did try using an event subscriber/listener tag, but that doesn't seem to accomplish the task I want.
我确实尝试使用事件订阅者/侦听器标记,但这似乎没有完成我想要的任务。
Here is my completely horrible attempt at a service. I couldn't get any response from it without using a constructor.
这是我完全可怕的服务尝试。没有使用构造函数我无法得到任何响应。
namespace MySite\SiteBundle\Services;
use MySite\SiteBundle\Entity\Blog;
class BlogUser {
protected $entities;
public function __construct(){
$em = $this->getDoctrine()->getManager();
$user = $this->get('security.context')->getToken()->getUser();
$this->entities = $em->getRepository('MySiteBundle:Blog')->findBy(array('user' => $user));
}
}
Am I going about this the completely wrong way? Is there a better way that I'm missing?
我是以完全错误的方式来做这件事的吗?有没有更好的方法让我失踪?
EDIT/ANSWER:
modified my naming convention a little:
修改了我的命名约定:
//services.yml
mysite.user.blog.entities:
class: Mysite\SiteBundle\Services\BlogUser
arguments: ["@doctrine.orm.entity_manager", "@security.context"]
In the controller action:
在控制器动作中:
$userEntities = $this->get('mysite.user.blog.entities');
$entities = $userEntities->getEntities();
In the service itself:
在服务本身:
class BlogUser {
protected $entities;
public function __construct($em, $securityContext){
$user = $securityContext->getToken()->getUser();
$this->entities = $em->getRepository('MySiteBundle:Blog')->findBy(array('user' => $user));
}
public function getEntities(){
return $this->entities;
}
}
Still needs two lines to get the $entities variable in the controller, but this is way better than defining the same thing over and over.
仍然需要两行来获取控制器中的$ entities变量,但这比一遍又一遍地定义相同的东西要好。
3 个解决方案
#1
11
"Security.context" has been deprecated since Symfony 2.6
自Symfony 2.6以来,“Security.context”已被弃用
After some community discussions, it was decided that SecurityContext gives too many dependencies to retrieve a simple Token/User object. That's why, starting with Symfony 2.6, thesecurity.context service has been deprecated and split into two new services:security.authorization_checker and security.token_storage.
在一些社区讨论之后,确定SecurityContext提供了太多依赖项来检索简单的令牌/用户对象。这就是为什么,从Symfony 2.6开始,不推荐使用thiscurity.context服务并将其拆分为两个新服务:security.authorization_checker和security.token_storage。
资源
Thus, the new way to do it would be, first configure your service as:
因此,新的方法是,首先将您的服务配置为:
mysite.user.blog:
class: MySite\SiteBundle\Services\BlogUser
arguments: ["@doctrine.orm.entity_manager", "@security.token_storage"]
Then in the service class constructor:
然后在服务类构造函数中:
class BlogUser
{
protected $user;
protected $entities;
public function __construct(EntityManager $em, TokenStorage $tokenStorage)
{
$this->user = $tokenStorage->getToken()->getUser();
$this->entities = $em->getRepository('MySiteBundle:Blog')->findBy(array('user' => $user));
}
}
#2
5
Yes, you are doing it in wrong way. Let's look at your code:
是的,你是以错误的方式做到的。我们来看看你的代码:
# call to undefined object method getDoctrine()
$em = $this->getDoctrine()->getManager();
# call to undefined object method get()
$user = $this->get('security.context')->getToken()->getUser();
You cannot call getting entitymanager and security.context
in your service in the same way like in your controller. Instead, you have to inject entitymanager and security.context
services. Example:
您不能像控制器一样调用服务中的entitymanager和security.context。相反,您必须注入entitymanager和security.context服务。例:
# services.yml
mysite.user.blog:
class: MySite\SiteBundle\Services\BlogUser
calls:
- [ setUserFromSecurityContext, [ @security.context ]]
- [ setEntityManager, [ @doctrine.orm.entity_manager ]]
And improved service:
并改善服务:
namespace Catablog\SiteBundle\Services;
use MySite\SiteBundle\Entity\Blog;
class BlogUser {
private $entityManager;
private $user;
public function setEntityManager(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
public function setUserFromSecurityContext(SecurityContext $securityContext)
{
# notice, there are a cases when `getToken()` returns null, so improve this
$this->user = $securityContext->getToken()->getUser();
}
public function getEntities(){
# your code here
}
}
More info about Dependency injection
有关更多信息Dependency injection
#3
2
You are looking on how to 'inject' other services into your custom service. Take a look at Service Container documentation.
您正在研究如何将“其他服务”注入您的自定义服务。查看Service Container文档。
In your case, you can inject doctrine.orm.entity_manager
and security.context
services into your BlogUser
class via constructor injection. For example:
在您的情况下,您可以通过构造函数注入将doctrine.orm.entity_manager和security.context服务注入您的BlogUser类。例如:
class BlogUser {
public function __construct($em, $securityContext) {
$user = $securityContext->getToken()->getUser();
$this->entities = $em->getRepository('MySiteBundle:Blog')->findBy(array('user' => $user));
}
}
And configure your service as the following:
并按以下方式配置您的服务:
mysite.user.blog:
class: MySite\SiteBundle\Services\BlogUser
arguments: ["@doctrine.orm.entity_manager", "@security.context"]
#1
11
"Security.context" has been deprecated since Symfony 2.6
自Symfony 2.6以来,“Security.context”已被弃用
After some community discussions, it was decided that SecurityContext gives too many dependencies to retrieve a simple Token/User object. That's why, starting with Symfony 2.6, thesecurity.context service has been deprecated and split into two new services:security.authorization_checker and security.token_storage.
在一些社区讨论之后,确定SecurityContext提供了太多依赖项来检索简单的令牌/用户对象。这就是为什么,从Symfony 2.6开始,不推荐使用thiscurity.context服务并将其拆分为两个新服务:security.authorization_checker和security.token_storage。
资源
Thus, the new way to do it would be, first configure your service as:
因此,新的方法是,首先将您的服务配置为:
mysite.user.blog:
class: MySite\SiteBundle\Services\BlogUser
arguments: ["@doctrine.orm.entity_manager", "@security.token_storage"]
Then in the service class constructor:
然后在服务类构造函数中:
class BlogUser
{
protected $user;
protected $entities;
public function __construct(EntityManager $em, TokenStorage $tokenStorage)
{
$this->user = $tokenStorage->getToken()->getUser();
$this->entities = $em->getRepository('MySiteBundle:Blog')->findBy(array('user' => $user));
}
}
#2
5
Yes, you are doing it in wrong way. Let's look at your code:
是的,你是以错误的方式做到的。我们来看看你的代码:
# call to undefined object method getDoctrine()
$em = $this->getDoctrine()->getManager();
# call to undefined object method get()
$user = $this->get('security.context')->getToken()->getUser();
You cannot call getting entitymanager and security.context
in your service in the same way like in your controller. Instead, you have to inject entitymanager and security.context
services. Example:
您不能像控制器一样调用服务中的entitymanager和security.context。相反,您必须注入entitymanager和security.context服务。例:
# services.yml
mysite.user.blog:
class: MySite\SiteBundle\Services\BlogUser
calls:
- [ setUserFromSecurityContext, [ @security.context ]]
- [ setEntityManager, [ @doctrine.orm.entity_manager ]]
And improved service:
并改善服务:
namespace Catablog\SiteBundle\Services;
use MySite\SiteBundle\Entity\Blog;
class BlogUser {
private $entityManager;
private $user;
public function setEntityManager(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
public function setUserFromSecurityContext(SecurityContext $securityContext)
{
# notice, there are a cases when `getToken()` returns null, so improve this
$this->user = $securityContext->getToken()->getUser();
}
public function getEntities(){
# your code here
}
}
More info about Dependency injection
有关更多信息Dependency injection
#3
2
You are looking on how to 'inject' other services into your custom service. Take a look at Service Container documentation.
您正在研究如何将“其他服务”注入您的自定义服务。查看Service Container文档。
In your case, you can inject doctrine.orm.entity_manager
and security.context
services into your BlogUser
class via constructor injection. For example:
在您的情况下,您可以通过构造函数注入将doctrine.orm.entity_manager和security.context服务注入您的BlogUser类。例如:
class BlogUser {
public function __construct($em, $securityContext) {
$user = $securityContext->getToken()->getUser();
$this->entities = $em->getRepository('MySiteBundle:Blog')->findBy(array('user' => $user));
}
}
And configure your service as the following:
并按以下方式配置您的服务:
mysite.user.blog:
class: MySite\SiteBundle\Services\BlogUser
arguments: ["@doctrine.orm.entity_manager", "@security.context"]