Indeed, the trait used in this way is a bad idea. If someone decides to use this trait in your code, they must ensure that the container attribute exists. the "container" must be correct (including the methods used), otherwise it will get an error. In fact, this code cannot be reused, and this is potentially a mistake. In addition, it violates the DIP rule (dependency inversion principle) of SOLID rules.
You can get around this:
interface ExampleContainerInterface{ } trait CheckPermissionTrait { protected $container; public function __construct(ExampleContainerInterface $container) { $this->container = $container; } protected function checkPermission($object_id) { $judge = $this->container->get('acme_judge'); $user = $this->container->get('security.context')->getToken()->getUser(); if( !$judge->isPermitted($user, $object_id) ) { throw $this->createAccessDeniedException("Brabbel"); } } } class ExampleClassA { use CheckPermissionTrait; } class ExampleClassB { use CheckPermissionTrait; }
or like this (php7):
interface ExampleContainerInterface{ } trait CheckPermissionTrait { abstract public function getContainer():ExampleContainerInterface; protected function checkPermission($object_id) { $container = $this->getContainer(); $judge = $container->get('acme_judge'); $user = $container->get('security.context')->getToken()->getUser(); if( !$judge->isPermitted($user, $object_id) ) { throw $this->createAccessDeniedException("Brabbel"); } } } class ExampleClassA { use CheckPermissionTrait; protected $container; public function getContainer():ExampleContainerInterface { return $this->container; } } class ExampleClassB { use CheckPermissionTrait; protected $container; public function getContainer():ExampleContainerInterface { return $this->container; } }
source share