2012-04-26 8 views
31

Im seraching qua và không thể tìm thấy câu trả lời. Tôi có mô hình vai trò cơ sở dữ liệu trong ứng dụng của mình. Người dùng có thể có vai trò nhưng vai trò này phải được lưu trữ vào cơ sở dữ liệu.Symfony 2.0 nhận dịch vụ bên trong thực thể

Nhưng sau đó người dùng cần phải thêm vai trò mặc định từ cơ sở dữ liệu. Vì vậy, tôi đã tạo ra một dịch vụ:

<?php 

namespace Alef\UserBundle\Service; 

use Alef\UserBundle\Entity\Role; 

/** 
* Description of RoleService 
* 
* @author oracle 
*/ 
class RoleService { 

    const ENTITY_NAME = 'AlefUserBundle:Role'; 

    private $em; 

    public function __construct(EntityManager $em) 
    { 
     $this->em = $em; 
    } 

    public function findAll() 
    { 
     return $this->em->getRepository(self::ENTITY_NAME)->findAll(); 
    } 

    public function create(User $user) 
    { 
     // possibly validation here 

     $this->em->persist($user); 
     $this->em->flush($user); 
    } 

    public function addRole($name, $role) { 
     if (($newrole = findRoleByRole($role)) != null) 
      return $newrole; 
     if (($newrole = findRoleByName($name)) != null) 
      return $newrole; 

     //there is no existing role 
     $newrole = new Role(); 
     $newrole->setName($name); 
     $newrole->setRole($role); 

     $em->persist($newrole); 
     $em->flush(); 

     return $newrole; 
    } 

    public function getRoleByName($name) { 
     return $this->em->getRepository(self::ENTITY_NAME)->findBy(array('name' => $name)); 
    } 

    public function getRoleByRole($role) { 
     return $this->em->getRepository(self::ENTITY_NAME)->findBy(array('role' => $role)); 
    } 

} 

tôi services.yml là:

alef.role_service: 
    class: Alef\UserBundle\Service\RoleService 
    arguments: [%doctrine.orm.entity_manager%] 

Và bây giờ tôi muốn sử dụng nó ở hai nơi: UserControllerUser thực thể. Làm thế nào tôi có thể nhận được chúng bên trong thực thể? Đối với bộ điều khiển tôi nghĩ rằng tôi chỉ cần:

$this->get('alef.role_service'); 

Nhưng làm cách nào để nhận dịch vụ bên trong thực thể?

Trả lời

41

Bạn không. Đây là một câu hỏi rất phổ biến. Các thực thể chỉ nên biết về các thực thể khác chứ không phải về người quản lý thực thể hoặc các dịch vụ cấp cao khác. Nó có thể là một chút thách thức để làm cho quá trình chuyển đổi theo cách này phát triển nhưng nó thường đáng giá.

Điều bạn muốn làm là tải vai trò khi bạn tải người dùng. Thông thường bạn sẽ kết thúc với một UserProvider mà loại điều này. Bạn đã đọc qua các phần về bảo mật chưa? Điều đó sẽ là điểm bắt đầu của bạn:

http://symfony.com/doc/current/book/security.html

13

Trong khi nó rất nản để có được dịch vụ vào các tổ chức, có một cách tốt đẹp để làm điều đó mà không liên quan đến rối tung với hạt nhân toàn cầu.

Thực thể học viên có sự kiện Vòng đời mà bạn có thể móc trình xử lý sự kiện vào, xem http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#lifecycle-events Vì ví dụ, tôi sẽ sử dụng postLoad, kích hoạt ngay sau khi thực thể được tạo.

Danh sách phát sự kiện có thể được thực hiện làm dịch vụ mà bạn đưa các dịch vụ khác vào.

Add để app/config/config.yml:

services: 
    example.listener: 
      class: Alef\UserBundle\EventListener\ExampleListener 
    arguments: 
      - '@alef.role_service' 
    tags: 
      - { name: doctrine.event_listener, event: postLoad } 

Thêm vào Entity của bạn:

use Alef\UserBundle\Service\RoleService; 

private $roleService; 

public function setRoleService(RoleService $roleService) { 
     $this->roleService = $roleService; 
} 

Và thêm EventListener mới:

namespace Alef\UserBundle\EventListener; 

use Doctrine\ORM\Event\LifecycleEventArgs; 
use Alef\UserBundle\Service\RoleService; 

class ExampleListener 
{ 
    private $roleService; 

    public function __construct(RoleService $roleService) { 
     $this->roleService = $roleService; 
    } 

    public function postLoad(LifecycleEventArgs $args) 
    { 
     $entity = $args->getEntity(); 
     if(method_exists($entity, 'setRoleService')) { 
      $entity->setRoleService($this->roleService); 
     } 
    } 
} 
+4

Đó là giải pháp tốt nhất và câu trả lời chính xác nhất cho câu hỏi. Tôi ghét những câu trả lời như "bạn không thể", "đó là mẫu thiết kế quá sai" hoặc "Nó sẽ làm hỏng mọi thứ, bạn khốn kiếp!" được viết bởi rất kinh nghiệm. "Tệ hơn là (đôi khi) tốt hơn";) Cảm ơn một lần nữa. –

+3

Đáng buồn thay, "mẫu thiết kế sai", "mô hình MCV", "Lớp kinh doanh riêng biệt", v.v. đi ra khỏi cửa sổ khi 'ông chủ' muốn thực hiện "ngay bây giờ". Cảm ơn câu trả lời @Kai, đó là những gì tôi đang tìm kiếm. –