goaop / framework

:gem: Go! AOP PHP - modern aspect-oriented framework for the new level of software development
go.aopphp.com
MIT License
1.66k stars 163 forks source link

Problem when I have a instance of object before AspectKernel->init() #430

Closed rafaelqueiroz closed 5 years ago

rafaelqueiroz commented 5 years ago

Hi guys,

I have problem when in the codebase have a instance of object called before init the AspectKernel. I wrote a test for check if aspect to GuzzleHttp\Client() works:

class ApplicationAspectKernelTest extends TestCase
{

    public function testGuzzleAspectIsIntercepted()
    {
        $this->init();

        $client = new GuzzleHttp\Client();
        $this->assertInstanceOf(Go\Aop\Proxy::class, $client);
    }

    private function init()
    {
        $applicationAspectKernel = ApplicationAspectKernel::getInstance();
        $applicationAspectKernel->init([
            'debug' => true,
            'cacheDir' => __DIR__ . '/../../storage/cache',
            'includePaths' => [
                "/var/www/html/vendor/guzzlehttp",
            ]
        ]);

        return $applicationAspectKernel;        
    }
}

On the happy way, the perfect scenery, works well:

$ ./vendor/bin/phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
OK (1 test, 1 assertion)

The problem happens if I added the line before init:

class ApplicationAspectKernelTest extends TestCase
{

    public function testGuzzleAspectIsIntercepted()
    {
        $this->init();

        $client = new GuzzleHttp\Client();
        $this->assertInstanceOf(Go\Aop\Proxy::class, $client);
    }

    private function init()
    {
        $client = new GuzzleHttp\Client();

        $applicationAspectKernel = ApplicationAspectKernel::getInstance();
        $applicationAspectKernel->init([
            'debug' => true,
            'cacheDir' => __DIR__ . '/../../storage/cache',
            'includePaths' => [
                "/var/www/html/vendor/guzzlehttp",
            ]
        ]);

        return $applicationAspectKernel;        
    }
}

Now, the test is broken:

$ ./vendor/bin/phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
1) ApplicationAspectKernelTest::testGuzzleAspectIsIntercepted
Failed asserting that GuzzleHttp\Client Object (...) is an instance of interface "Go\Aop\Proxy".

Tests: 1, Assertions: 1, Failures: 1.

The problem is: I wrote a package which can be included on CakePHP, Laravel (in this case is Laravel), whatever framework.

Each framework has a place for bootstrap the package (such as /config/boostrap.php or AppServiceProvider.php)

Also the framework load and run the core codebase before. Which can create a instance of object anytime.

It's possible the AspectKernel->init() works if have a instance of objects before ?

Thanks in advance.

lisachenko commented 5 years ago

Hi, @rafaelqueiroz! This is known limitation of framework. If class is loaded before AOP kernel, then aspects won't be applied to it in run-time. This is why you need to find a place where you can init AOP kernel first. For example, you can use composer include file feature to always include initialization logic for your packet.

lisachenko commented 5 years ago

This issue will be closed because of current framework implementation. If you have any questions, you can open a new issue then.