2013-08-14 54 views
8

Tôi đang chạy mã tương đương với rất nhiều hành động điều khiển, về cơ bản nó lấy tên người dùng của người dùng và nếu tên người dùng đó được gắn với thực thể blog, nó sẽ cho phép người dùng để xem (các) thực thể blog:Người dùng truy cập và học thuyết của Symfony2 trong một dịch vụ

$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, 

Tôi muốn chuyển nó thành dịch vụ để tôi có thể cắt giảm mã lặp lại. Tôi muốn tránh làm nhiều logic trong bộ điều khiển của mình càng tốt.

Điều đó đang được nói, tôi không chắc chắn cách tôi có thể truy cập vào phiên người dùng và học thuyết trong một dịch vụ.

Dưới đây là services.yml tôi:

mysite.user.blog: 
    class: MySite\SiteBundle\Services\BlogUser 

Và dưới đây là cách tôi đã cố gắng gọi nó trong bộ điều khiển:

public function testAction() { 
    $response = $this->get('mysite.user.blog'); 
    return new Response($response); 
} 

Tôi đã thử sử dụng một sự kiện subscriber/listener thẻ, nhưng điều đó không' t dường như hoàn thành nhiệm vụ tôi muốn.

Đây là nỗ lực hoàn toàn khủng khiếp của tôi đối với dịch vụ. Tôi không thể nhận được bất kỳ phản hồi từ nó mà không sử dụng một nhà xây dựng.

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)); 
    } 
} 

Tôi sẽ làm điều này theo cách hoàn toàn sai? Có cách nào tốt hơn tôi đang thiếu?

EDIT/ĐÁP:

sửa đổi của tôi quy ước đặt tên một chút:

//services.yml 
mysite.user.blog.entities: 
    class: Mysite\SiteBundle\Services\BlogUser 
    arguments: ["@doctrine.orm.entity_manager", "@security.context"] 

Trong controller action:

$userEntities = $this->get('mysite.user.blog.entities'); 
$entities = $userEntities->getEntities(); 

Trong dịch vụ riêng của mình:

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; 
    } 
} 

Vẫn cần hai dòng để lấy biến $ entity trong controller, nhưng đây là cách tốt hơn so với việc định nghĩa cùng một thứ lặp đi lặp lại.

Trả lời

11

"Security.context" đã bị phản đối từ Symfony 2,6

Sau khi một số cộng đồng các cuộc thảo luận, nó đã được quyết định rằng SecurityContext cho quá nhiều phụ thuộc để truy xuất đối tượng Token/User đơn giản. Đó là lý do tại sao, bắt đầu với Symfony 2.6, dịch vụ thesecurity.context đã không được chấp nhận và được chia thành hai dịch vụ mới: security.authorization_checker và security.token_storage.

Source

Như vậy, phương pháp mới để làm điều đó sẽ là, lần đầu tiên cấu hình dịch vụ của bạn như:

mysite.user.blog: 
    class: MySite\SiteBundle\Services\BlogUser 
    arguments: ["@doctrine.orm.entity_manager", "@security.token_storage"] 

Sau đó, trong constructor lớp dịch vụ:

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

Bạn đang tìm cách 'tiêm' các dịch vụ khác vào dịch vụ tùy chỉnh của mình. Hãy xem tài liệu Service Container.

Trong trường hợp của bạn, bạn có thể tiêm các dịch vụ doctrine.orm.entity_managersecurity.context vào lớp BlogUser của bạn thông qua quá trình tạo hàm tạo. Ví dụ:

class BlogUser { 

    public function __construct($em, $securityContext) { 
     $user = $securityContext->getToken()->getUser(); 
     $this->entities = $em->getRepository('MySiteBundle:Blog')->findBy(array('user' => $user)); 
    } 

} 

Và cấu hình dịch vụ của bạn như sau:

mysite.user.blog: 
    class: MySite\SiteBundle\Services\BlogUser 
    arguments: ["@doctrine.orm.entity_manager", "@security.context"] 
+2

Như từ symfony v. 2.6 ngữ cảnh bảo mật không được dùng nữa: http://symfony.com/doc/current/book/security.html – 11mb

5

Vâng, bạn đang làm nó theo cách sai. Hãy xem mã của bạn:

# call to undefined object method getDoctrine() 
    $em = $this->getDoctrine()->getManager(); 
    # call to undefined object method get() 
    $user = $this->get('security.context')->getToken()->getUser(); 

Bạn không thể gọi nhận thực thể và security.context trong dịch vụ giống như trong bộ điều khiển của bạn. Thay vào đó, bạn phải tiêm các thực thể và các dịch vụ security.context.Ví dụ:

# services.yml 
mysite.user.blog: 
    class: MySite\SiteBundle\Services\BlogUser 
    calls: 
     - [ setUserFromSecurityContext, [ @security.context ]] 
     - [ setEntityManager, [ @doctrine.orm.entity_manager ]] 

Và cải thiện dịch vụ:

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 
    } 
} 

Thông tin thêm về Dependency injection

+0

không có dấu gạch dưới trong propertie S! –

+1

@Pazi nó vẫn là tên thuộc tính hợp lệ. – NHG

+0

có phần "" cuộc gọi: "' của dịch vụ chạy bất kỳ chức năng nào bạn chỉ định không? Có một lợi thế để sử dụng mà thay vì các nhà xây dựng ngoài sự linh hoạt (hoặc tái sử dụng cùng một lớp được gọi là bởi các dịch vụ khác nhau?) – gan