goaop / goaop-symfony-bundle

[Outdated!] Integration bridge for Go! AOP framework and Symfony
55 stars 16 forks source link
aop aspect-oriented-programming symfony-bundle symfony2

GoAopBundle

Scrutinizer Code Quality Travis branch GitHub release Minimum PHP Version License

The GoAopBundle adds support for Aspect-Oriented Programming via Go! AOP Framework for Symfony2 applications. Symfony 3.4 and upper versions are not supported! Global rewrite of bundle is required to make it working for newer versions of Symfony.

Overview

Aspect-Oriented Paradigm allows to extend the standard Object-Oriented Paradigm with special instruments for effective solving of cross-cutting concerns in your application. This code is typically present everywhere in your application (for example, logging, caching, monitoring, etc) and there is no easy way to fix this without AOP.

AOP defines new instruments for developers, they are:

Installation

GoAopBundle can be easily installed with composer. Just ask a composer to download the bundle with dependencies by running the command:

$ composer require goaop/goaop-symfony-bundle

Versions 1.x are for Symfony >=2.0,<2.7 Versions 2.x(master) are for Symfony >= 2.7 and 3.x

Then enable the bundle in the kernel:

// app/AppKernel.php

public function registerBundles()
{
    $bundles = array(
        new Go\Symfony\GoAopBundle\GoAopBundle(),
        // ...
    );
}

Make sure that bundle is the first item in this list. This is required for the AOP engine to work correctly.

Configuration

Configuration for bundle is required for additional tuning of AOP kernel and source code whitelistsing/blacklisting.

# app/config/config.yml
go_aop:
    # This setting enables or disables an automatic AOP cache warming in the application.
    # By default, cache_warmer is enabled (true), disable it only if you have serious issues with 
    # cache warming process.
    cache_warmer: true

    # This setting enables or disables workaround for weaving of Doctrine ORM entities. By default,
    # it is disabled. If you are using Doctrine ORM and you are using AOP to weave Doctrine entities,
    # enable this feature. For details about this known issue, see https://github.com/goaop/framework/issues/327
    doctrine_support: false

    # Additional settings for the Go! AOP kernel initialization
    options:
        # Debug mode for the AOP, enable it for debugging and switch off for production mode to have a
        # better runtime performance for your application
        debug: %kernel.debug%

        # Application root directory, AOP will be applied ONLY to the files in this directory, by default it's
        # src/ directory of your application.
        app_dir: "%kernel.root_dir%/../src"

        # AOP cache directory where all transformed files will be stored.
        cache_dir: %kernel.cache_dir%/aspect

        # Whitelist is array of directories where AOP should be enabled, leave it empty to process all files
        include_paths: []

        # Exclude list is array of directories where AOP should NOT be enabled, leave it empty to process all files
        exclude_paths: []

        # AOP container class name can be used for extending AOP engine or services adjustment
        container_class: ~

        # List of enabled features for AOP kernel, this allows to enable function interception, support for
        # read-only file systems, etc. Each item should be a name of constant from the `Go\Aop\Features` class.
        features: []

XML format is supported for configuration of this bundle as well, for XML format please use provided XML schema file.

Defining new aspects

Aspects are services in the Symfony2 apllications and loaded into the AOP container with the help of compiler pass that collects all services tagged with goaop.aspect tag. Here is an example how to implement a logging aspect that will log information about public method invocations in the src/ directory.

Definition of aspect class with pointuct and logging advice

<?php

namespace App\Aspect;

use Go\Aop\Aspect;
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\Before;
use Psr\Log\LoggerInterface;

/**
 * Application logging aspect
 */
class LoggingAspect implements Aspect
{
    /**
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    /**
     * Writes a log info before method execution
     *
     * @param MethodInvocation $invocation
     * @Before("execution(public **->*(*))")
     */
    public function beforeMethod(MethodInvocation $invocation)
    {
        $this->logger->info($invocation, $invocation->getArguments());
    }
}

Registration of aspect in the container:

services:
    logging.aspect:
        class: App\Aspect\LoggingAspect
        arguments: ["@logger"]
        tags:
            - { name: goaop.aspect }

If you're using Symfony 3.3+ with autowired and autoconfigured services, your aspects will be registered automatically.

Known issues and workarounds

License

This bundle is under the MIT license. See the complete license in the bundle:

Resources/meta/LICENSE