Giter VIP home page Giter VIP logo

aop's Introduction

Introduction

AOP is a PECL extension that enables you to use Aspect Oriented Programming in PHP, without the need to compile or proceed to any other intermediate step before publishing your code.

The AOP extension is designed to be the easiest way you can think of for integrating AOP to PHP.

AOP aims to allow separation of cross-cutting concerns (cache, log, security, transactions, ...)

Build Status

Installation

You can use pecl

    sudo pecl install aop-beta

or

Download the AOP from github, compile and add the extension to your php.ini

    #Clone the repository on your computer
    git clone https://github.com/AOP-PHP/AOP
    cd AOP
    #prepare the package, you will need to have development tools for php
    phpize
    #compile the package
    ./configure
    make
    #before the installation, check that it works properly
    make test
    #install
    make install

Now you can add the following line to your php.ini to enables AOP

    extension=AOP.so

What is AOP ? Basic tutorial

Let's assume the following class

<?php
    class MyServices
    {
       public function doAdminStuff1 ()
       {
          //some stuff only the admin should do
          echo "Calling doAdminStuff1";
       }

       public function doAdminStuff2 ()
       {
          //some stuff only the admin should do
          echo "Calling doAdminStuff2";
       }
    }

Now you want your code to be safe, you don't want non admin users to be able to call doAdminMethods.

What are your solutions ?

  • Add some code to check the credentials "IN" you MyServices class. The drawback is that it will pollute your code, and your core service will be less readable.
  • Let the clients have the responsibility to check the credentials when required. The drawbacks are that you will duplicate lots of code client side if you have to call the service from multiple places
  • Add some kind of credential proxy that will check the credentials before calling the actual service. The drawbacks are that you will have to write some extra code, adding another class on the top of your services.

Moreover, those solutions tends to increase in complexity while you are adding more cross-cutting concerns like caching or logging.

That's where AOP comes into action as you will be able to tell PHP to do some extra actions while calling your MyServices's admin methods.

So let's first write the rule needed to check if we can or cannot access the admin services.

<?php
    function adviceForDoAdmin ()
    {
       if ((! isset($_SESSION['user_type'])) || ($_SESSION['user_type'] !== 'admin')) {
          throw new Exception('Sorry, you should be an admin to do this');
       }
    }

Dead simple : we check the current PHP session to see if there is something telling us the current user is an admin (Of course we do realize that you may have more complex routines to do that, be we'll keep this for the example)

Now, let's use AOP to tell PHP to execute this method "before" any execution of admin methods.

<?php
    aop_add_before('MyServices->doAdmin*()', 'adviceForDoAdmin');

Now, each time you'll invoke a method of an object of the class MyServices, starting by doAdmin, AOP will launch the function basicAdminChecker before the called method.

That's it, simple ain't it ?

Now le's try the examples :

<?php
    //session is started and we added the above examples to configure MyServices & basicAdminChecker

    $services = new MyServices();
    try {
       $services->doAdminStuff1();//will raise an exception as nothing in the current session tells us we are an admin
    } catch (Exception $e) {
       echo "You cannot access the service, you're not an admin";
    }

    $_SESSION['user_type'] = 'admin';//again, this is ugly for the sake of the example

    try {
       $service->doAdminStuff1();
       $service->doAdminStuff2();
    } catch (Exception $e) {
       //nothing will be caught here, we are an admin
    }

Here you are, you know the basics of AOP.

AOP Vocabulary and PHP's AOP capabilities

Advice

An advice is a piece of code that can be executed. In our first example, the function adviceForAdmin is an advice, it could be executed.

In PHP's AOP extension, an advice can be a trait, a callback, an anonymous function, a static method of a class, a method of a given object or a closure.

Join points

Join points are places where we can attach advices.

In PHP's AOP extension, a join point can be:

  • before any method / function call
  • after any method / function call
  • around any method / function call
  • During the arousing of an exception of any method / function
  • after any method / function call, should the method terminate normally or not (triggers an exception or not)

In our first example, we used a "before" join point.

Pointcut

Pointcuts are a way to describe whether or not a given join point will trigger the execution of an advice.

In PHP's AOP extension, pointcuts can be configured with a quite simple and straightforward syntax.

In our first example the pointcut was "MyServices->doAdmin*()" and was configured to launch the advice "before" the execution of the matching methods join points.

Why or should I use AOP?

AOP is a whole different way of thinking for developing application. It is as different as object oriented programming can be opposed to procedural programming.

Event if you don't want to base your future development on this approach, you may find it very useful for debugging purposes. Imagine a world where you can debug or get informations on your code based on information only collected for a given user, a given context, a given procedure. A world where you can hunt weird and old code execution without even trying to update multiple and sparse PHP files, but just by adding advices on given conditions.

We are sure that this extension will soon be part of your future development workflow!

Latest version of the documentation

aop's People

Contributors

alecsammon avatar asm89 avatar evandotpro avatar geraldcroes avatar juliens avatar kdambekalns avatar ralphschindler avatar siad007 avatar stealth35 avatar tyx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aop's Issues

Does not work when remote-debugging using Zend Debugger

First, thanks for your implementation of AOP in PHP. Hope this will live and grow (more users, and as simple as it is to use now).

My little bug report however :

It does not work when using extension Zend Debugger.

My testing environment is :

  • Eclipse IDE (Zend Studio 9 too, tested with both of them, in case of)
  • Debian 6 server, tested with php 5.3 and php 5.4 (and their respective version of the ZendDebugger.so extension)
  • Tried with AOP-PHP 0.1.0 and 0.2.0

Once ou call an URL with the debugger's parameters, that activate it (automatic when from Eclipse), it debugs well, but aop_add_* calls don't crash, but don't do anything. Advices are then not called at all.

That's not a problem for me : I go to Xdebug, as your extension works very well with it.
Thanks again.

Bonne journée.

Throwing exceptions in an advice kill the PHP process

Example code:

class Form {
    function render(array $aParams = []) {
        return 'foo';
    }
}

class Csrf {
    function aroundFormRender() {
        #echo 'bar';
        throw new Exception('bar');
    }
}
$oForm = new Form();
$oCsrf = new Csrf();
aop_add_around('Form->render()', array($oCsrf, 'aroundFormRender'));
echo $oForm->render();

Object-oriented style for aop_add_xxx methods

It will be nice to have a class for Aop routines, because object oriented style is smarter, allows inheritance and logical composition.

For example:

$aspect = new Aspect(); // <-- Class defined in the extension
$aspect->addBefore('MyServices->doStuff()', $advice); // <-- aop_add_before()

Example of use:

class TestAspect extends Aspect 
{

    public function aroundStuff(AopJoinPoint $joinpoint)
    {
        $joinpoint->process();
        $returnValue = $joinpoint->getReturnedValue();
        $returnValue = str_replace('best', 'very best', $returnValue);
        $joinpoint->setReturnedValue($returnValue);
    }

    public function register()
    {
        // aop_add_around('MyServices->doStuff()', array($this, 'aroundStuff'));
        $this->addAround('MyServices->doStuff()', array($this, 'aroundStuff'));
    }
}

$testAspect = new TestAspect();
// Object-oriented style with inheritance and encapsulation:
$testAspect->register();
// Procedural style:
// aop_add_around('MyServices->doStuff()', array($testAspect, 'aroundStuff'));

Segmentation fault (core dumped)

Out of my depth to fix

Have written a test that fails for me

--TEST--
Try using finfo_open (may cause segmentation fault)
--FILE--
<?php
class mytest {
    public function test() {
        return finfo_open(FILEINFO_MIME_TYPE);
    }
}

$test = new mytest();
$test->test();
echo 'PASS';
?>
--EXPECT--
PASS

Hook for object construction

Would it be possible to have a hook for the construction of an object? I guess it would be possible if an object has a __construct method, but maybe it is possible to provide a more robust hook.

Consider adding an API for removing pointcuts

It would be nice to be able to remove pointcuts.

This could for example be interesting for unit tests, but also for example when you want to debug certain code temporarily and then remove the callbacks to avoid any performance loss.

Random crash running phpunit

Hi.
I installed the version 0.2.0 of aop extension.
I run some phpunit test suite and the process silently crashes at random tests.
If I run the tests one at time, the tests run fine.
No error is reported in php error log.

Wildcard Class and Wildcard Method

Hi all,

First off, I'm loving this extension!

I'm not sure if this is currently supported but shouldn't this work:

My\Namespace\Path\*->*() or My\Namespace\Path\*->set*()

It doesn't appear this is directly referenced in the docs but I assumed it was possible since this works My\Namespace\Path\MyClass->*().

What about methods that override parent methods ?

When declaring a pointcut on a method, the advice should not be called for the overriden method of a child class !

But it does.

class Markus
{

    function loves() { echo "Markus love cookies "; } 

}

class Miky extends Markus
{

    function loves() { echo "Miky loves cheesecakes "; }

}

aop_add_before("Markus->loves()", function() { echo "What does Markus love ? "; });

$miky = new Miky();
$miky->loves();

This tells :

What does Markus love ? Miky loves cheesecakes

This should tell, because I never call Markus->loves() :

Miky loves cheesecakes

Must be fixed. Thanks.

Segmentation fault when registering an AOP advice from another advice

This crashes with a segmentation fault (using AOP-PHP 0.2.0 / PHP 5.4) :

function function1() {
    echo "function1 ";
}

function function2() {
    echo "function2 ";
}

function advice1() {
    echo "advice 1 ";
        // the crash happens here, when advice1() is called by the AOP extension
    aop_add_before("function2()", "advice2");
    echo "done ";
}

function advice2() {
    echo "advice 2 ";
    echo "done ";
}

aop_add_before("function1()", "advice1");
function1();
function2();

property : How to change assigned value ?

I see this in your documentation :

$assigned = $aop_tjp->getAssignedValue();
if ($assigned !== 'PHP') {
$assigned .= ' and PHP';
}

$assigned gets a reference to the assigned value, so if we modify it, it alters the assigned value. Cool. (note : it bugs with my current 0.2.0 version of AOP-PHP ! your sample at 2.1.7 of your documentation don't work, $developper->preferences is still "Java". I'd prefer use aop_add_after() but it stills don't work but my turnaround bellow)

But how can I do that stuff : ?

$assigned = $aop_tjp->getAssignedValue();
$assigned = 'PHP';

If I do that assigned value is not changed : in fact $assigned becomes a new string containing "PHP" and is not the reference to the assigned value anymore.

Today's turnaround :

static $dont_recurse = false;
if (!$done_recurse) {
$assigned = $aop_tjp->getAssignedValue();
$object = $aop_tip->getObject();
$property = $aop_top->getPropertyName();
$dont_recurse = true;
$object->$property = 'PHP';
$dont_recurse = false;
}

Another way to do that ?

If not, suggested improvement on AOP-PHP :

$aop_tip->setAssignedValue('PHP');

Compile on Windows--some errors

I was able to compile version 0.2.0 on Windows 7, with MS Visual C++ 2008 without a hitch, however after trying to upgrade to the latest, I am now running into problems, that seem to have to do with C / C++ strict syntax.

The first line in question occurs here, where a function is called before the variables are declared. It looks like the MS Compiler, is expecting a strict 'C' syntax wherein all variable declarations are required at the beginning of the function or class definition.

Any plans on adapting the library to the MS Compilers?

https://github.com/AOP-PHP/AOP/blob/master/aop.c#L248-L249

Thank you

Here is a stack trace of the error I am encountering:

C:\php-sdk\php53dev\vc9\x86\php-5.3.18-src>nmake

Microsoft (R) Program Maintenance Utility Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.

Recreating build dirs
aop.c
ext\AOP\aop.c(249) : error C2143: syntax error : missing ';' before 'type'
ext\AOP\aop.c(250) : error C2275: 'zval' : illegal use of this type as an expression
c:\php-sdk\php53dev\vc9\x86\php-5.3.18-src\zend\zend.h(286) : see declaration of 'zval'
ext\AOP\aop.c(250) : error C2065: 'aop_object' : undeclared identifier
ext\AOP\aop.c(251) : error C2065: 'i' : undeclared identifier
ext\AOP\aop.c(251) : error C2065: 'i' : undeclared identifier
ext\AOP\aop.c(251) : error C2065: 'i' : undeclared identifier
ext\AOP\aop.c(252) : error C2065: 'i' : undeclared identifier
ext\AOP\aop.c(279) : error C2065: 'aop_object' : undeclared identifier
ext\AOP\aop.c(279) : warning C4047: '=' : 'int' differs in levels of indirection from 'zval '
ext\AOP\aop.c(279) : error C2065: 'aop_object' : undeclared identifier
ext\AOP\aop.c(279) : error C2065: 'aop_object' : undeclared identifier
ext\AOP\aop.c(279) : error C2223: left of '->refcount__gc' must point to struct/union
ext\AOP\aop.c(279) : error C2065: 'aop_object' : undeclared identifier
ext\AOP\aop.c(279) : error C2223: left of '->is_ref__gc' must point to struct/union
ext\AOP\aop.c(280) : error C2065: 'aop_object' : undeclared identifier
ext\AOP\aop.c(280) : error C2100: illegal indirection
ext\AOP\aop.c(280) : error C2224: left of '.type' must have struct/union type
ext\AOP\aop.c(281) : error C2065: 'aop_object' : undeclared identifier
ext\AOP\aop.c(281) : error C2223: left of '->value' must point to struct/union
ext\AOP\aop.c(282) : error C2065: 'aop_object' : undeclared identifier
ext\AOP\aop.c(282) : warning C4047: '=' : 'zval *' differs in levels of indirection from 'int'
ext\AOP\aop.c(283) : error C2065: 'aop_object' : undeclared identifier
ext\AOP\aop.c(283) : warning C4047: 'function' : 'zval *' differs in levels of indirection from 'int'
ext\AOP\aop.c(283) : warning C4024: 'zval_addref_p' : different types for formal and actual parameter 1
ext\AOP\aop.c(284) : error C2065: 'aop_object' : undeclared identifier
ext\AOP\aop.c(284) : warning C4047: 'return' : 'zval *' differs in levels of indirection from 'int'
ext\AOP\aop.c(314) : error C2143: syntax error : missing ';' before 'type'
ext\AOP\aop.c(315) : error C2275: 'pointcut' : illegal use of this type as an expression
c:\php-sdk\php53dev\vc9\x86\php-5.3.18-src\ext\aop\aop.h(96) : see declaration of 'pointcut'
ext\AOP\aop.c(315) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(316) : error C2275: 'pointcut' : illegal use of this type as an expression
c:\php-sdk\php53dev\vc9\x86\php-5.3.18-src\ext\aop\aop.h(96) : see declaration of 'pointcut'
ext\AOP\aop.c(316) : error C2065: 'temp' : undeclared identifier
ext\AOP\aop.c(316) : error C2100: illegal indirection
ext\AOP\aop.c(329) : error C2065: 'temp' : undeclared identifier
ext\AOP\aop.c(336) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(336) : error C2065: 'temp' : undeclared identifier
ext\AOP\aop.c(336) : error C2100: illegal indirection
ext\AOP\aop.c(339) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(339) : warning C4047: '=' : 'int' differs in levels of indirection from 'AopJoinpoint_object *'
ext\AOP\aop.c(340) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(340) : error C2223: left of '->current_pointcut' must point to struct/union
ext\AOP\aop.c(340) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(342) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(342) : error C2223: left of '->pos' must point to struct/union
ext\AOP\aop.c(343) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(343) : error C2223: left of '->advice' must point to struct/union
ext\AOP\aop.c(344) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(344) : error C2223: left of '->kind_of_advice' must point to struct/union
ext\AOP\aop.c(344) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(344) : error C2223: left of '->kind_of_advice' must point to struct/union
ext\AOP\aop.c(345) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(345) : error C2223: left of '->object' must point to struct/union
ext\AOP\aop.c(346) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(346) : error C2223: left of '->to_return_ptr_ptr' must point to struct/union
ext\AOP\aop.c(347) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(347) : error C2223: left of '->value' must point to struct/union
ext\AOP\aop.c(348) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(348) : error C2223: left of '->ex' must point to struct/union
ext\AOP\aop.c(349) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(349) : error C2223: left of '->object' must point to struct/union
ext\AOP\aop.c(350) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(350) : error C2223: left of '->scope' must point to struct/union
ext\AOP\aop.c(351) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(351) : error C2223: left of '->called_scope' must point to struct/union
ext\AOP\aop.c(354) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(354) : error C2223: left of '->args' must point to struct/union
ext\AOP\aop.c(356) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(356) : error C2223: left of '->args_overloaded' must point to struct/union
ext\AOP\aop.c(357) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(357) : error C2223: left of '->exception' must point to struct/union
ext\AOP\aop.c(358) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(358) : error C2223: left of '->kind_of_advice' must point to struct/union
ext\AOP\aop.c(360) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(360) : warning C4047: 'function' : 'pointcut *' differs in levels of indirection from 'int'
ext\AOP\aop.c(360) : warning C4024: 'execute_pointcut' : different types for formal and actual parameter 1
ext\AOP\aop.c(363) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(363) : error C2223: left of '->kind_of_advice' must point to struct/union
ext\AOP\aop.c(365) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(365) : warning C4047: 'function' : 'pointcut *' differs in levels of indirection from 'int'
ext\AOP\aop.c(365) : warning C4024: 'execute_pointcut' : different types for formal and actual parameter 1
ext\AOP\aop.c(366) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(366) : error C2223: left of '->value' must point to struct/union
ext\AOP\aop.c(367) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(367) : error C2223: left of '->value' must point to struct/union
ext\AOP\aop.c(367) : error C2198: 'zval_addref_p' : too few arguments for call
ext\AOP\aop.c(368) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(368) : error C2223: left of '->value' must point to struct/union
ext\AOP\aop.c(372) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(372) : error C2223: left of '->args_overloaded' must point to struct/union
ext\AOP\aop.c(372) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(372) : error C2223: left of '->args' must point to struct/union
ext\AOP\aop.c(372) : warning C4047: 'function' : 'int' differs in levels of indirection from 'zval *
'
ext\AOP\aop.c(372) : warning C4024: '_test_func_pointcut_and_execute' : different types for formal and actual parameter 7
ext\AOP\aop.c(372) : error C2198: '_test_func_pointcut_and_execute' : too few arguments for call
ext\AOP\aop.c(374) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(374) : error C2223: left of '->kind_of_advice' must point to struct/union
ext\AOP\aop.c(375) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(375) : error C2223: left of '->kind_of_advice' must point to struct/union
ext\AOP\aop.c(377) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(377) : error C2223: left of '->exception' must point to struct/union
ext\AOP\aop.c(379) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(379) : warning C4047: 'function' : 'pointcut *' differs in levels of indirection from 'int'
ext\AOP\aop.c(379) : warning C4024: 'execute_pointcut' : different types for formal and actual parameter 1
ext\AOP\aop.c(381) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(381) : error C2223: left of '->value' must point to struct/union
ext\AOP\aop.c(382) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(382) : error C2223: left of '->value' must point to struct/union
ext\AOP\aop.c(382) : error C2198: 'zval_addref_p' : too few arguments for call
ext\AOP\aop.c(383) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(383) : error C2223: left of '->value' must point to struct/union
ext\AOP\aop.c(385) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(385) : error C2223: left of '->kind_of_advice' must point to struct/union
ext\AOP\aop.c(386) : error C2065: 'current_pc' : undeclared identifier
ext\AOP\aop.c(386) : warning C4047: 'function' : 'pointcut *' differs in levels of indirection from 'int'
ext\AOP\aop.c(386) : warning C4024: 'execute_pointcut' : different types for formal and actual parameter 1
ext\AOP\aop.c(387) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(387) : error C2223: left of '->value' must point to struct/union
ext\AOP\aop.c(388) : error C2065: 'obj' : undeclared identifier
ext\AOP\aop.c(388) : fatal error C1003: error count exceeds 100; stopping compilation
NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 9.0\VC\Bin\cl.exe"' : return code '0x2'
Stop.

how to read property

Hi,
I want to read object property in AOP but have Fatal error

PHP Fatal error: Too many level of nested advices. Are there any recursive call ? in /var/www/test/test.php on line 12

How to properly read property in object using AOP ?
I need this to build inteligent ORM.

Enhancement of properties joinpoints accessors

This crashes with "Too many level of nested advices" :

class MyClass {
    public $property;
}

function defaultGetter(AopJoinpoint $joinpoint)
{
    $var = $joinpoint->getPropertyName();
    $object = $joinpoint->getObject();
    if (!isset($object->$var)) {
        $object->$var = "default value";
    }
    return $object->$var;
}

aop_add_around("read MyClass->property", "defaultGetter");

$myObject = new MyClass();
echo $myObject->property;
  • could we disable recursivity when accessing the same object / property ? I can do with some code addition, but I don't know if recursivity in this exact case has any use, so it could be natively managed.
  • another (better ?) solution would be to have $joinpoint->getPropertyValue() and $joinpoint->setPropertyValue() methods that would not call read / write advices on this property to avoid recursivity.

Thanks for thinking about this kind of enhancement.

No errors but not working

Hi,

I'm in a weird situation.

AOP installed successfully. I can see it in phpinfo().

When i'm trying the aop_add_before example on the wiki, i get do my best stuff ! instead of I was called before doing stuff...do my best stuff !

What the problem could be?

getTriggeringObject() gives fatal error

The error:
Fatal error: Call to undefined method AopJoinpoint::getTriggeringObject()...

PHP: 5.4.5
AOP 0.2.0

Update: I've discovered that AopJoinpoint has been refactored so the method is now getPointcut().

Using callback parameter

For all aop_add_around the callback parameter wait a zval (z) it's should be directly a calllback (f)

f - function or array containing php method call info (returned as
    zend_fcall_info and zend_fcall_info_cache)

But something wrong in zend_call_function the callack is transformed to an empty array

Example :

PHP_FUNCTION(aop_add_before)
{
    char *selector;
    int selector_len;
    zend_fcall_info fci;
    zend_fcall_info_cache fcic;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &selector, &selector_len, &fci, &fcic) == FAILURE) {
        return;
    }

    add_pointcut(fci, fcic, selector, selector_len, AOP_KIND_BEFORE TSRMLS_CC);
}

static void add_pointcut (zend_fcall_info fci, zend_fcall_info_cache fcic, char *selector, int selector_len, int type TSRMLS_DC) {
    pointcut *pc;
    int count;

    aop_g(count_pcs)++;
    count=aop_g(count_pcs)-1;

    if (aop_g(count_pcs)==1) {
        aop_g(pcs) = emalloc(sizeof(pointcut *));
    } else {
        aop_g(pcs) = erealloc(aop_g(pcs),aop_g(count_pcs)*sizeof(pointcut *));
    }

    pc = emalloc(sizeof(pointcut));
    pc->selector = selector;
    pc->fci = fci;
    pc->fcic = fcic; 
    pc->kind_of_advice = type;
    parse_pointcut(&pc);
    aop_g(pcs)[count] = pc;
}

1 RC1

Release Candidate for version 1

Memory Leaks?

Just installed aop-beta via pecl. While checking to make sure the module is loaded correctly I see the below errors. I'm unclear on how this error occurs but I figured I'd report it anyhow.

Potentially noteworthy: PHP was compiled from source with --enable-debug and --enable-maintainer-zts

php -i |grep -i aop

aop
[Wed Nov 21 16:13:09 2012] Script: '-'
/tmp/pear/temp/AOP/aop.c(140) : Freeing 0x7F5B74F8BBD8 (8192 bytes), script=-
/software/php-5.4.8/Zend/zend_alloc.c(2529) : Actual location (location was relayed)
[Wed Nov 21 16:13:09 2012] Script: '-'
/tmp/pear/temp/AOP/aop.c(145) : Freeing 0x7F5B74F91CF8 (72 bytes), script=-
=== Total 2 memory leaks detected ===

Add Support for PHP 5.5

Currently, master does not compile against php 5.5:

(master) ~/Projects/AOP$ make
/bin/sh /Users/ralphschindler/Projects/AOP/libtool --mode=compile cc  -I. -I/Users/ralphschindler/Projects/AOP -DPHP_ATOM_INC -I/Users/ralphschindler/Projects/AOP/include -I/Users/ralphschindler/Projects/AOP/main -I/Users/ralphschindler/Projects/AOP -I/Users/ralphschindler/.php/5.5.0/include/php -I/Users/ralphschindler/.php/5.5.0/include/php/main -I/Users/ralphschindler/.php/5.5.0/include/php/TSRM -I/Users/ralphschindler/.php/5.5.0/include/php/Zend -I/Users/ralphschindler/.php/5.5.0/include/php/ext -I/Users/ralphschindler/.php/5.5.0/include/php/ext/date/lib  -DHAVE_CONFIG_H  -g -O2   -c /Users/ralphschindler/Projects/AOP/aop.c -o aop.lo
mkdir .libs
 cc -I. -I/Users/ralphschindler/Projects/AOP -DPHP_ATOM_INC -I/Users/ralphschindler/Projects/AOP/include -I/Users/ralphschindler/Projects/AOP/main -I/Users/ralphschindler/Projects/AOP -I/Users/ralphschindler/.php/5.5.0/include/php -I/Users/ralphschindler/.php/5.5.0/include/php/main -I/Users/ralphschindler/.php/5.5.0/include/php/TSRM -I/Users/ralphschindler/.php/5.5.0/include/php/Zend -I/Users/ralphschindler/.php/5.5.0/include/php/ext -I/Users/ralphschindler/.php/5.5.0/include/php/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /Users/ralphschindler/Projects/AOP/aop.c  -fno-common -DPIC -o .libs/aop.o
/Users/ralphschindler/Projects/AOP/aop.c:645:35: warning: incompatible pointer types assigning to 'zval **(*)(zval *, zval *, const zend_literal *)' from
      'zend_object_get_property_ptr_ptr_t' (aka 'zval **(*)(zval *, zval *, int, const struct _zend_literal *)') [-Wincompatible-pointer-types]
    zend_std_get_property_ptr_ptr = std_object_handlers.get_property_ptr_ptr;
                                  ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/ralphschindler/Projects/AOP/aop.c:646:46: warning: incompatible pointer types assigning to 'zend_object_get_property_ptr_ptr_t' (aka 'zval **(*)(zval *, zval *, int, const struct
      _zend_literal *)') from 'zval **(zval *, zval *, const zend_literal *)' [-Wincompatible-pointer-types]
    std_object_handlers.get_property_ptr_ptr = zend_std_get_property_ptr_ptr_overload;
                                             ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/ralphschindler/Projects/AOP/aop.c:649:19: error: non-object type 'void (zend_op_array *)' is not assignable
    zend_execute  = aop_execute;
    ~~~~~~~~~~~~  ^
/Users/ralphschindler/Projects/AOP/aop.c:1020:81: error: no member named 'Ts' in 'struct _zend_execute_data'
        to_return_ptr_ptr = &(*(temp_variable *)((char *) current_execute_data->Ts + current_execute_data->opline->result.var)).var.ptr;
                                                          ~~~~~~~~~~~~~~~~~~~~  ^
/Users/ralphschindler/Projects/AOP/aop.c:1106:37: warning: implicit declaration of function 'zend_vm_stack_push_nocheck' is invalid in C99 [-Wimplicit-function-declaration]
                                    zend_vm_stack_push_nocheck((void *) (zend_uintptr_t)i TSRMLS_CC);
                                    ^
/Users/ralphschindler/Projects/AOP/aop.c:1107:74: error: too few arguments to function call, expected 1, have 0
                                    zend_vm_stack_clear_multiple(TSRMLS_C);
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~         ^
/Users/ralphschindler/.php/5.5.0/include/php/Zend/zend_execute.h:290:1: note: 'zend_vm_stack_clear_multiple' declared here
static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC)
^
/Users/ralphschindler/Projects/AOP/aop.c:1245:50: error: too few arguments to function call, expected 1, have 0
            zend_vm_stack_clear_multiple(TSRMLS_C);
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~         ^
/Users/ralphschindler/.php/5.5.0/include/php/Zend/zend_execute.h:290:1: note: 'zend_vm_stack_clear_multiple' declared here
static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC)
^
/Users/ralphschindler/Projects/AOP/aop.c:1403:23: error: non-object type 'void (zend_op_array *)' is not assignable
        zend_execute  = _zend_execute;
        ~~~~~~~~~~~~  ^
3 warnings and 5 errors generated.
make: *** [aop.lo] Error 1

Improve Introduction

In the introduction, it is not clear where the AOP code should be saved. Will it be in the class file? Thanks!

throw fatal error when give two advices like this.

    <?php
    class AdminDeniedException extends Exception {
    }

    function doAdminStuff(){
        echo "do admin stuff\n";
    }
    
    function adviceForDoAdmin(){
        global $role;
        if ( $role != 'admin' ) {
            throw new AdminDeniedException();
        }
    }

    function adviceForException($obj){
        $method = $obj->getFunctionName();
        try {
            $obj->process();
        }
        catch(AdminDeniedException $e){
            echo "no privilige to access $method\n";
        }
    }
    
    aop_add_before('doAdmin*()' , 'adviceForDoAdmin');
    aop_add_around('doAdmin*()', 'adviceForException');    
    
    try {
        doAdminStuff();
    } catch(Exception $e) {
        echo "unknown exception";    
    }
    ?>

In code above, I want to use aop to manage priviliges and deal with exceptions. but when i put admin advice before exception advice, it will throw a Fata error as follows.

"Fatal error: Problem in AOP Callback in /home/kufazhang/workcode/php-dev/c.php on line 26"

But shouldn't it output "unknow exception"?

AOP-PHP can't recurse, but in big projects we need AOP advices to call other advices

Please have a look to this example.
I want to force the day to begin before the man can wake up.
And I want to force the night to end before the day can begin.
All of this with AOP-PHP of course.

class Night {
    public static function end() { echo "the night ends "; }
}

class Day {
    public static function begin() { echo "the sun rises "; }
}

class Man {
    public function wakeup() { echo "the man wakes up "; }
}

aop_add_before("Day->begin()", array("Night", "end"));
aop_add_before("Man->wakeup()", array("Day", "begin"));

$me = new Man();
$me->wakeup();

But it won't work with current version 0.2.0 (my php is 5.4).
I am waiting for this result :

the night ends the sun rises the man wakes up

But I only have this :
the sun rises the man wakes up

Will AOP-PHP allow this ?

AOP.so should be aop.so

I think we should lowercase the aop.so. By (untold ?) convention, extensions libraries seems to be lowercase.

AOP roadmap and stable version

Dear Gerald and Julien,

I consider your extension very powerful, easy to use and would like to compose it into a real application to watch methods and their input parameters.

Unfortunately the last released version 0.2.2b1 is not stable enough and causes HTTP request abortion in special case.
I found out the bug causing the aborting is fixed in the master version.

The application I currently worked on is a large business web application with important customers (BMW for example), so I cannot afford to use any PHP extension in beta version.

Would you be so kind to share the AOP extension roadmap, please? I would appreciate if you would release a stable version of the extension within few months.

Do not hesitate to contact me directly on [email protected].

I am looking forward to your reply, with best regards,

Marek Sykora, web developer,
Intraworlds GmbH

Support multiple selectors or boolean expressions in pointcut expression

I would like to be able to declare more than one Pointcut expression for an advice.

I have seen the boolean operators && and || used in the comments on the following issue, but have not been able to use them within my own expressions. They are not shown in the documentation, and I have not been able to find an existing unit test for them.

Are they actually supported?

#19

Thank you.

Better Error Message

It took me some time until I figured out what could be passed to the aop_add_before method.

For example:

aop_add_before('*', function() { }) causes a segmentation fault
aop_add_before('*', 'test') causes a "Bad Params" error, but does not really give any indication of what is wrong

Maybe we can add something more specific for these cases.

Dissociate FUNCTION & METHOD

() all functions
*->
all properties of all objects in the root namespace
->() all methods of all objects in the root namespace

AOP_KIND_BEFORE_METHOD => only object's methods, not functions
AOP_KIND_BEFORE_FUNCTION => only functions

getTriggeringMethodName => only method name, error if in function or property
getTriggeringFunctionName => only method name, error if in function or property

var_dump on AopJoinPoint

not very important but it does not work :
var_dump($jp); // AopJoinPoint

In Chrome / Chromium : Erreur 324 (net::ERR_EMPTY_RESPONSE) : Le serveur a mis fin à la connexion sans envoyer de données.

New CONST

new CONST for Method and Function
AOP_KIND_METHOD
AOP_KIND_FUNCTION

Absolute namespace

Mon\Plugin\Config::get() // work
\Mon\Plugin\Config::get() // Doesn't work

Properties?

First, very useful extension! We can definately use this in Doctrine (optionally) to avoid proxy code generation.

I am not sure if this is in the scope of an AOP extension, but would it be possible to have hooks for property access (read/write) as well? We could use this in Doctrine to implement Change Tracking for objects.

Performance

I've been looking through the docs and issues, but I couldn't find information (apart from some property metrics) about the performance impact this extension has.

Have you done any benchmarks?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.