Annotations used for service deffinitions and customizable property injection

6 years ago

mike227
Member | 5
+
0
-

Hi!

I would like to ask if something is wrong in this way how to define services (see examples).

For larger projects, it is clearer to me. And it gives more options about property injection.

Examples:

/**
 * @Service
 */
class UsersManager {
    /** @InjectDao("\App\Model\Entities\User")  */
    public $userDao;

    /** @InjectDao("\App\Model\Entities\Group") */
    public $groupDao;

    ....
}

or

/**
 * @EventSubscriber
 */
class TestEventSubscriber extends Nette\Object implements Kdyby\Events\Subscriber
{
    ...
}

Used annotations:

/**
 * @Annotation
 */
class Service implements IServiceAnnotation
{
    public function createServiceDefinition($class)
    {
        $definition = new ServiceDefinition();
        $definition->setClass($class);
        $definition->setInject(TRUE);
        return $definition;
    }
}

/**
 * @Annotation
 */
class EventSubscriber implements IServiceAnnotation
{
    public function createServiceDefinition($class)
    {
        $definition = new ServiceDefinition();
        $definition->setClass($class);
        $definition->setInject(TRUE);
        $definition->addTag('kdyby.subscriber');
        return $definition;
    }
}

/**
 * @Annotation
 */
class InjectDao implements IInjectAnnotation {

    const ENTITY_MANAGER_CLASS = 'Kdyby\Doctrine\EntityManager';

    private $entityName;

    public function __construct(array $parameters) {
        if (!isset($parameters['value'])) {
            throw new InvalidArgumentException("Expected entity name.");
        }
        $this->entityName = $parameters['value'];
    }

    public function createInjectStatement(Property $property) {
        return new Statement('$this->getByType(?)->getDao(?)', array(self::ENTITY_MANAGER_CLASS, $this->entityName));
    }
}

I tried to write an extension for the compiler: https://github.com/…-annotations

You think it's a good idea? Or are there some hidden risks that I did not realize?

6 years ago

Filip Procházka
Moderator | 4693
+
0
-

Interesting solution, I was thinking about the market annotations @service in the past, but haven't implemented it because it's hard to do it safely. The annotations reader has to crawl files, even you do it using require, which is dangerous, because it can trigger some executable php script by mistake (just like doctrine can if you misconfigure entity dir).

I like the way it's extensible and how easy is to create the @EventSubscriber marker.

What I don't like is the injection to properties. First of all, that doesn't look like presenter and therefore you're gonna have a hard time defending why are you not using constructor.

And second of all, injecting of DAO's isn't that great of an idea, you might wanna read this.