Location: PHPKode > scripts > Transparent PHP AOP > transparent-php-aop/Manual.html
<html>
	<head>
		<title>Transparent PHP AOP</title>

		<style type="text/css">

BODY {
	font-family: Trebuchet MS, Helvetica, Sans Serif;
	font-size: 10pt;
	color: #000;
	background-color: #fff;
	padding: 10px;
	margin: 0px;
	border: 0px;
}


@media Print {
	A:unknown {
		content: " (" attr(href) ")";
	}
	
	PRE, .code {
		background-color: #fff;
		border-width: 2px;
	}
}


DIV#author {
	position: absolute;
	top: 5px;
	right: 10px;
	font-style: italic;
	color: #A0A0A0;
}


H1, H2, H3, H4, H5, H6 {
	margin-bottom: 0.2em;
}


H1 {
	letter-spacing: 0.3em;
	margin-bottom: 1.0em;
}


H1 .datetime {
	display: block;
	font-size: 50%;
	font-style: italic;
	color: #A0A0A0;
}


H2 {
	margin-bottom: 0.5em;
	padding-left: 5px;
	border-bottom: 1px solid #9C9CFF;
	border-left: 1px solid #9C9CFF;
	background-color: #DADAFF;
}


H3 {
	padding-left: 5px;
	border-bottom: 1px solid #A0A0A0;
	border-left: 1px solid #A0A0A0;
	background-color: #E0E0E0;
}


H5 {
	font-size: 10pt;
	color: #0099FF;
}


PRE, .code {
	width: auto;
	border: 1px solid #D0D0D0;
	background-color: #F0F0F0;
	padding: 5px;
}


.warning {
	width: auto;
	border: 1px solid #FF9C9C;
	background: #FFDADA;
	padding: 5px;
}


.info {
	width: auto;
	border: 1px solid #F2F200;
	background: #FFFFDA;
	padding: 5px;
}

		</style>
	</head>

	<body>

		<h1>Transparent PHP AOP - Manual <span class="datetime">Current Version: 1.0 RC 3 - Build 2006-12-22</span></h1>

		<div id="author">Guilherme Blanco</div>
		
		
		<h2>New Features of this version</h2>

		<div class="info">
			<ul style="margin-top: 0px; margin-bottom: 0px;">
				<li>Changed the compiled file name generator. Now it creates a more readable name<br />
					<strong>Example:</strong> class.Test.php into class.Text.eb4a5e7be51cfd2e7544f827a3807bd6.php
				</li>
				<li>Added "around" AutoPointcut</li>
				<li>Implemented "proceed();" wildcard for "around" AutoPointcut:</li>
				<ul>
					<li>If the wildcard is found, the previous code is appended at "before" AutoPointcut and the code after the wildcard is appended at "after" AutoPointcut</li>
					<li>If there's no wildcard present, the whole source is retrieved and attached at "before" and also attached at "after" AutoPointcuts</li>
				</ul>
				<li>Corrected a lot of bugs: reference return functions, undefined offset, unreachable code, etc</li>
				<li>Added new optional handler to external advice code loader: <strong>asrequire</strong> (default value: false), optimizing in 90% the necessary time and resources to load an external file</li>
				<li>Added new XAD pointcut optional modifiers:</li>
				<ul>
					<li><strong>nclass</strong>: Not In Class</li>
                    <li><strong>nfunction</strong>: Not In Function/Method</li>
				</ul>
				<li>&quot;Recompile&quot; automatically if external advice code is changed. Part of it is already implemented if <strong>asrequire</strong> equals &quot;true&quot;. Otherwise, it is not checked (consumes too much resources and time to do this)</li>
			</ul>
		</div>


		<h2>Table of Contents</h2>
		<ol>
			<li><a href="#1">Introduction</a></li>
			<li><a href="#2">Getting Started</a></li>
			<ol>
				<li><a href="#2_1">Installing</a></li>
				<li><a href="#2_2">Quick Tutorial</a></li>
				<ol>
					<li><a href="#2_2_1">Setting up a basic class</a></li>
					<li><a href="#2_2_2">Creating your custom code</a></li>
					<li><a href="#2_2_3">Loading basic class</a></li>
				</ol>
				<li><a href="#2_3">Testing your installation</a></li>
				<li><a href="#2_4">Troubleshooting</a></li>
			</ol>
			<li><a href="#3">What is AOP?</a></li>
			<ol>
				<li><a href="#3_1">Introduction</a></li>
				<li><a href="#3_2">AOP Naming Convention</a></li>
				<ol>
					<li><a href="#3_2_1">Aspect</a></li>
					<li><a href="#3_2_2">Advice</a></li>
					<li><a href="#3_2_3">Join Point</a></li>
					<li><a href="#3_2_4">Pointcut</a></li>
					<li><a href="#3_2_5">Weave</a></li>
				</ol>
			</ol>
			<li><a href="#4">Complete Guide</a></li>
			<ol>
				<li><a href="4_1">Introduction</a></li>
				<ol>
					<li><a href="#4_1_1">Briefing</a></li>
					<li><a href="#4_1_2">Conventions</a></li>
					<li><a href="#4_1_3">How does it work?</a></li>
					<ol>
						<li><a href="#4_1_3_1">Internal Structure</a></li>
					</ol>
				</ol>
				<li><a href="#4_2">XML Aspect Definition (XAD)</a></li>
				<ol>
					<li><a href="#4_2_1">XML Aspect DTD</a></li>
					<li><a href="#4_2_2">Defining Pointcut and Advice</a></li>
					<li><a href="#4_2_3">Applying restrictions</a></li>
				</ol>
				<li><a href="#4_3">PHP Class Code</a></li>
				<ol>
					<li><a href="#4_3_1">Custom Pointcuts</a></li>
					<li><a href="#4_3_2">Automatic Pointcuts</a></li>
				</ol>
				<li><a href="#4_4">Application Loading</a></li>
				<ol>
					<li><a href="#4_4_1">Loading Class File</a></li>
					<li><a href="#4_4_2">Modifying Compile Options</a></li>
				</ol>
			</ol>
		</ol>


		<h2><a name="1">1.</a> Introduction</h2>

		<p>
			In a few words, Transparent PHP AOP is a set of classes that work together to emulate AOSD (Aspect Oriented Software Development).<br />
			Supporting PHP 4.3.0+ installations, the simplicity is a strong point in Transparent AOP; everything is controlled in a human-readable and easily understandable XML Aspect
			Definition (XAD) file.<br />
			This document explain all the resources available to you with this package. It is a short document, because of class simplicity; however, it
			is still a very powerful tool.
		</p>


		<h2><a name="2">2.</a> Getting Started</h2>


		<h3><a name="2_1">2.1.</a> Installing</h3>

		<p>
			This is the best part! Look: It will not have more than one line! Here it comes:<br />
			<br />
			<strong>Unzip the content of this package inside your project's folder.</strong><br />
			<br />
        	Difficult, huh? ;)
		</p>


		<h3><a name="2_2">2.2.</a> Quick Tutorial</h3>

		<p>
			This chapter is like "Learn Transparent PHP AOP in 5 minutes" tutorials. It is simple, do not cover all features, but it is enough to
			developers use the basic features of this class without any problems.<br />
			In this tutorial, we will setup a class, will define an Aspect to be appplied and finally will apply it. The "Testing your installation"
			section will explain how to check if it worked well, and "Troubleshooting" will
		</p>


		<h4><a name="2_2_1">2.2.1.</a> Setting up a basic class</h4>

		<p>Suppose we have a class names Test. In our UML Class Diagram, we have this methods and properties:</p>

		<pre>
+-------------------------------+
| Test                          |
+-------------------------------+
| - message: string             |
+-------------------------------+
| + Test(m: String): Test       |
| + setMessage(m: string): void |
| + getMessage(): string        |
| + display(): void             |
+-------------------------------+</pre>

		<p>So, we create the following PHP Code:</p>

		<pre>
&lt;?php

class Test {
    var $message;

    function Test($m) {
        $this-&gt;setMessage($m);
    }

    function setMessage($m) {
        $this-&gt;message = $m;
    }

    function getMessage() {
        return $this-&gt;message;
    }
    
    function display() {
        echo $this-&gt;message;
    }
}

?&gt;</pre>

		<p>Finally, save this file in this location: AOP root folder + tutorial/class.Test.php<p>


		<h4><a name="2_2_2">2.2.2.</a> Creating your custom code</h4>

		<p>
			Suppose we have to track method calls, in a basic approach of a Debugger System; consider we want to include a Debugger Aspect.<br />
			To track calls, we just print the name of the function and if is in the beginning or ending of it.
		</p>

		<p>
			The XML Aspect Definition allows you to write PHP Code to be applied in the class (Advice).<br />
			We will write 4 custom pieces of code to be merged with class Test. The XML syntax uses a simple hierarchy that the root element is an
			Aspect and supports one or more Pointcuts. Each Pointcut contains some attributes that define the location to be applied and as a child
			it comes with a CDATA node containing the PHP code.
		</p>

		<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!DOCTYPE aspect SYSTEM "../aop.dtd"&gt;

&lt;aspect&gt;
    &lt;pointcut auto="after" function="setMessage"&gt;
    &lt;![CDATA[
        echo "End of " . __FUNCTION__ ."(\"" . $m . "\") call.&lt;br /&gt;";
    ]]&gt;
    &lt;/pointcut&gt;

    &lt;pointcut auto="after" class="Test" nfunction="display"&gt;
    &lt;![CDATA[
        echo "End of " . __FUNCTION__ ." call.&lt;br /&gt;";
    ]]&gt;
    &lt;/pointcut&gt;

    &lt;pointcut auto="before" nfunction="display"&gt;
    &lt;![CDATA[
        echo "Beginning of " . __FUNCTION__ ." call.&lt;br /&gt;";
    ]]&gt;
    &lt;/pointcut&gt;
    
    &lt;pointcut auto="around" function="display" class="Test"&gt;
    &lt;![CDATA[
    	echo "&lt;b&gt;Message: &lt;/b&gt;";
        proceed();
        echo "&lt;br /&gt;";
    ]]&gt;
    &lt;/pointcut&gt;
&lt;/aspect&gt;</pre>

		<p>
			The first pointcut is an AutoPointcut (detailed later) specific to setMessage method. Its Advice prints the name of the function and the
			$m local variable content.<br />
			The second pointcut apply the same Advice to all end of calls inside class Test, except in method "display".<br />
			The third pointcut is also an AutoPointcut and its Advice prints a message containing the name of the function, and it is applicable in
			the beginning of all methods (or functions) defined in the desirable document, but it will not be applyed to a function/method called
			"display".
			The last pointcut, another AutoPointcut will be applyed in method display inside of class Test. It will display the first line before the
			method commands, will execute them and after it will print the new line HTML code. The proceed(); method means the whole method content!
		</p>

		<p>
			Save this file as debugger.xml inside the AOP root folder + tutorial directory.
		</p>


        <h4><a name="2_2_3">2.2.3.</a> Loading basic class</h4>

		<p>
        	The last part of this quick tutorial explains supperficially how to apply the XAD into Original class.
		</p>

		<p>
			Transparent PHP AOP defines a function called require_aop. It is a require_once style method that either compiles the Aspects into
			Class files or load already compiled files. If the compiled file does not exist, the script compiles and try to save the compiled content
			into a unique named file. Since version 1.0 RC3, the compiled file name is more readable, allowing the programmer to connect the original
			class file with the compiled class file (they will have the same name, except that the compiled will have a md5 hash after it).
		</p>

		<div class="warning">
			<strong>NOTE:</strong> Make sure your tutorial folder has permissions for write. This is necessary to the script works correctly.
		</div>

		<p>
			Our script loader is our application. It is reduced into a minimum possible code, to show exactly only the AOP functionality.
		</p>

		<pre>
&lt;?php

require_once "../func.require_aop.php";

// Loading compiled class or compiling and saving
require_aop("class.Test.php", "debugger.xml");

// Testing...
$test = new Test("George Bush");

if ($test-&gt;getMessage() != "Author") {
    $test-&gt;setMessage("Guilherme Blanco");
}

$test-&gt;display();

?&gt;</pre>

		<p>
			Save this file into AOP root folder + tutorial with the index.php file name.
		</p>

		<p>
			Try running the index.php into your server and you will see the defined Advices begin displayed in screen, as defined. If not, proceed
			to Troubleshooting section.
		</p>


		<h3><a name="2_3">2.3.</a> Testing your installation</h3>

		<p>
        	Last topic we exposed a quick tutorial. It compiled the class Test with the debugger.xml aspect. As a result, it should generate a
        	compiled file, probably named "class.Test.4f207ed29fbb1b4b06f233a9fa05c471.php". If not, it will probably have a file with a name that
			is the original file name plus a md5 hash plus the PHP extension. Open it in your favourite PHP editor.
		</p>

		<p>
			If everything went ok, you'll see the defined debugger.xml code merged with class.Test.php code. For our example, it should be something
			like:
		</p>

		<pre>
&lt;?php

class Test {
    var $message;

    function Test($m) { /* AOP "before" Auto Code */ echo "Beginning of " . __FUNCTION__ ." call.&lt;br /&gt;";
        $this-&gt;setMessage($m);
    /* AOP "after" Auto Code */ echo "End of " . __FUNCTION__ ." call.&lt;br /&gt;"; }

    function setMessage($m) { /* AOP "before" Auto Code */ echo "Beginning of " . __FUNCTION__ ." call.&lt;br /&gt;";
        $this-&gt;message = $m;
    /* AOP "after" Auto Code */ echo "End of " . __FUNCTION__ ."(\"" . $m . "\") call.&lt;br /&gt;"; echo "End of " . __FUNCTION__ ." call.&lt;br /&gt;"; }

    function getMessage() { /* AOP "before" Auto Code */ echo "Beginning of " . __FUNCTION__ ." call.&lt;br /&gt;";
        /* AOP "after" Auto Code */ echo "End of " . __FUNCTION__ ." call.&lt;br /&gt;";  return $this-&gt;message;
    /* AOP "after" Auto Code */ echo "End of " . __FUNCTION__ ." call.&lt;br /&gt;"; }
    
    function display() { /* AOP "before" Auto Code */ echo "&lt;b&gt;Message: &lt;/b&gt;";
        echo $this->message;
    /* AOP "after" Auto Code */ echo "&lt;br /&gt;"; }
}

?&gt;</pre>

		<p>
			Next section explains commom mistakes. If the compiled file exist and if its code does not match with above code, notify me via email
			(guilhermeblanco [at] hotmail [dot] com), messenger (same as email) or at PHP Classes.org Forums.
		</p>


		<h3><a name="2_4">2.4.</a> Troubleshooting</h3>

		<p><strong>1. It appears some errors while using require_aop function?</strong></p>
		<p>
			This is probably because of your PHP version module installed in your server. Currently, Transparent PHP AOP supports versions since
			4.3.0+, basically because of tokenizer functions and Regular Expressions functions. Also, it uses internally the Expat XML functions,
			that is built-in with your PHP module (and if you don't want it, you remove it manually).<br />
			These are the main issues that can happen. If is everything fine and you still experience errors, feel free to contact me at
			guilhermeblanco [at] hotmail [dot] com.<br />
		</p>

        <p><strong>2. Every call to require_aop, appears this error: [Aspect Error]: File XXX [From Original: YYY] could not be created/loaded for write!</strong></p>
        <p>
        	This happens when you do not assign permissions to read/write in the directory that compiled file is generated. Please, assign a valid
        	CHMOD value and everything will work. If not, check if you are not exceeding your disk quota.
        </p>
        
        <p><strong>1. It appears some E_STRICT errors while using the package?</strong></p>
		<p>
			That's true. In PHP5 there is a E_STRICT error, that notifies commom differences between PHP4 and PHP5. This does not means that your code
			will not work; it just mention that the notifyed code has changed its declaration. To fix this, disable this type of error reporting.
		</p>

        <p><strong>New Troubleshooting itens will be added if encountered new user mistakes.</strong></p>


		<h2><a name="3">3.</a> What is AOP?</h2>

		<p>
			Several places around Web provide more complete guides to AOSD. This Manual explains the basic idea of usage and the terminology, to help
			introducing interested people in AOP that want to use this package. For more explanations and references, please refer to:
			<a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming" target="_blank">http://en.wikipedia.org/wiki/Aspect-oriented_programming</a>.
		</p>


		<h3><a name="3_1">3.1.</a> Introduction</h3>

		<p>
        	AOSD came to solve the existent problems of OOP approach. Imagine building a website, and you need to incorporate a debugging system on it.
        	In commom OOP approach, you have to create a Debbuger class, and trace your code by editting the class code, right? So, you have a single
        	class merging the whole system. That is not OOP, that is AOP. The only point I wrote here that is wrong, is to edit the class code. In AOP,
        	you do not edit code, you apply what we call Advices and they are aplied without change the original class code.<br />
        	You still do not understand? Ok, I will try to explain better. Instead of create a set of classes and embed their usage code inside your
        	application module, you merge different aspects of your system in your application module, and everything will be fine.<br />
        	Still don't understand? Check out WikiPedia text.
		</p>


		<h3><a name="3_2">3.2.</a>	AOP Naming Convention</h3>

		<p>
			AOP has a special naming convention, and knowing them will help you to understand how does this approach work. Read carefully this section
			and the "Conventions", that will explain how does this package works based in the AOP theory.
		</p>


		<h4><a name="3_2_1">3.2.1.</a> Aspect</h4>

        <p>
			To be very formal, an Aspect is a set of Pointcuts. Explaining better, an Aspect is a perspective of your system, for example, Logging,
			Debugging, Benchmarking, etc.
		</p>


        <h4><a name="3_2_2">3.2.2.</a> Advice</h4>

        <p>
			An Advice is a piece of code. AOP theory divagates a lot in this point, but this is a piece of code that can be applied in a Join Point.
		</p>


		<h4><a name="3_2_3">3.2.3.</a> Join Point</h4>

        <p>
			This is a place inside original file where additionally code (Pointcut) can be defined.
		</p>


		<h4><a name="3_2_4">3.2.4.</a> Pointcut</h4>

        <p>
			A set of Advices consists in a Pointcut. It is this code that is applied in a Join Point.
		</p>


		<h4><a name="3_2_5">3.2.5.</a> Weave</h4>

        <p>
			Weave is the whole behavior of your system. Technically speaking, a Weave is a set of Aspects.
		</p>


		<h2><a name="43">4.</a> Complete Guide</h2>


		<h3><a name="4_1">4.1.</a> Introduction</h3>


		<h4><a name="4_1_1">4.1.1.</a> Briefing</h4>

		<p>
        	This section tryes to explain the reasons of the existance of this class.<br />
        	The origin is a conversation between the author of the package and a friend, who came with the idea to break the paradigm that it was
        	impossible to create a complete AOP approach in PHP language. After some discussion and links popping at MSN, we found several
			implementations that uses external extensions, PHP5 dependency or even it's a module that must be installed on server.<br />
			Since none of these solutions match our needs, we continued discussing possibilities to solve the paradigm. More references we added,
			and we came up with the idea of compiling merged contents and use Tokenizer functions. This solved all our "to-be-defined" questions
			and allow me (the author) to start a project. My friend did not onboard it.
		</p>


		<h4><a name="4_1_2">4.1.2.</a> Conventions</h4>

		<p>
			While I was developing this package, I assigned some names to help to strict follow my idea. Since I think it's not necessary those
			UML diagrams (Use Case, Analisys Class, Implementation Class, Sequence) for small projects, I used some other names (different from
			AOP theory) to simplify my work.<br />
			Since version 1.0 RC2, I updated the whole system to follow the AOP theory.<br />
			Now, what AOP defines as a Weave, we have a class named Weave too. The same for Aspect, Pointcut (not exactly, it is called in my
			implementation as AutoPointcut) and Advice. The only missing point is the Join Point.<br />
			In AOP, a Join Point is a place where advice can be applied. My implementation does not have this, since XAD can refer to more than
			one Join Point. So, this is packed inside Pointcut class.
		</p>


		<h4><a name="4_1_3">4.1.3.</a> How does it work?</h4>

		<p>
        	The idea is simple. I'll draw it using ASCII instead of pic, since I want to make this Manual a unique file, not a package. I hope you
        	understand. Here is the approach I defined:
		</p>

		<pre>
          +-------------------+
          |     Class File    |
          +-------------------+
                   /\
                   ||                      +---------------------+
                   ||=====================>| Compiled Class File |
                   ||                      +---------------------+
    +-----------+-------------------+
    |           |                   |
+-------+   +-------+           +-------+
|  XAD  |   |  XAD  |  .  .  .  |  XAD  |
+-------+   +-------+           +-------+</pre>

		<p>
        	You have your class file. There, you can define CustomPointcuts (explained in details later), by adding some comment like lines.<br />
        	You also define you XAD (Xml Aspect Definition), that is a XML file with a strict DTD. This is converted in a PHP Aspect structure.
        	This structure stores 1..N Pointcuts. Each Pointcut contains a name (or its repectively auto), a possible se of classes and a set of
			possible methods to be applied. Finally, we have the code inside it too.<br />
        	When you want to get some Advice, each Aspect is checked and is exists any Pointcut that matches with the name/auto, function (optional)
			and class (also optional too), its code (an instance of Advice) is returned.
		</p>
		
		<h5><a name="4_1_3_1">4.1.3.1.</a> Internal Structure</h5>
		
		<p>
			Technically speaking, Transparent PHP AOP is simple.<br />
			It starts by calling a custom function, require_aop. Internally, it make some conditions to check if there is at least one Aspect
			associated, if a compiled file exists, and, if yes, check for recent changes in original class file or in one of the associated 
			Aspects.<br />
			If this condition is false, then it simply load the compiled class file; otherwise, start the pain!
		</p>

		<p>
			To compile a file, the package read each XAD file into an Aspect object. This object holds a list of Pointcuts (AutoPointcuts and 
			CustomPointcuts).<br />
			Each instance of Pointcut derived classes holds an Advice object, which contains the source code defined.
		</p>
		
		<p>
			The compiler retrieves the Original Class file source and then starts its execution.<br />
			The source is then passed to the lexer, which extracts each token. The compiler does a lot of jobs, and them compile first the CustomPointcut.
			This is done first bacause a CustomPointcut may also have an "after" JoinPoint, that should be treated by AutoPointcuts.<br />
			After the first compilation, another call to curly braces correction is done, to correct possible statements what define a single command block.<br />
			The last compilation does the AutoPointcut merging.
		</p>
		
		<p>
			The CustomPointcut compilation is done via Regular Expressions. The compiler looks for occurencies of <strong>/// Pointcut: XXX</strong> and 
			then replace the matched item by the Advice related to that name.
		</p>
		
		<p>
			AutoPointcut compilation does the hardest part.<br />
			First of all, it split the whole source code into tokens. Also, it defines a level stack, which hold the identation level in the current file.<br />
			The compiler then loops through all tokens, and it finds the class declaration, method declaration, function declaration and also function exit
			statements (like return).<br />
			When it finds a match, it looks for the list of attached Aspects for an Advice related to the JoinPoint in the Pointcut. Then, it replaces one 
			by the other.
		</p>
		
		<p>
			After the whole compilation, the package generated a cache file containing the orginal source file merged with the related aspects.<br />
			This compiled file is then loaded, as mentioned earlier.
		</p>


        <h3><a name="4_2">4.2.</a> XML Aspect Definition (XAD)</h3>


		<h4><a name="4_2_1">4.2.1.</a> XML Aspect DTD</h4>
		
		<p>
			XAD follows a very simple DTD. It consists in a root element, an aspect. Then, it accepts one or more childs, all pointcuts.<br />
			One pointcut can have modifiers, that will be detailed later. The pointcut childen can be the following things: CDATA sections,
			that contains PHP code or Advice tags, that loads external PHP source.<br />
			There is a DTD available that you can attach to your XAD file to be validated. Include it and in some browsers to check if it is
			validated successfully.
		</p>
		
        <div class="warning">
			<strong>NOTE:</strong> Since version 1.0 RC2 it is possible to merge CDATAs and Advice XAD tags, in an unlimited number of times.
			Older versions just accept a single child, a CDATA that contains the Advice.
		</div>
		
		<p>
			A simple structure can be extracted:
		</p>
		
		<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!DOCTYPE aspect SYSTEM "../aop.dtd"&gt;

&lt;aspect&gt;
    &lt;pointcut ...&gt;
    &lt;![CDATA[
        ...
    ]]&gt;
    &lt;/pointcut&gt;

    ...
&lt;/aspect&gt;</pre>

        <div class="warning">
			<strong>NOTE:</strong> One Aspect must have at least one Pointcut element.
		</div>
		
		
		<h4><a name="4_2_2">4.2.2.</a> Defining Pointcut and Advice</h4>
		
		<p>
			Previous section exposes the basic XAD definition.<br />
			To define one pointcut, it must be child of an aspect node. Then, you have its attributes, that are restrictions to be applied (defined
			in the next section).<br />
			An Advice is the PHP code that is relative to a Pointcut. It must be defined inside the CDATA node, defined as child node of the Pointcut
			XML node or an advice node, if you want to load external data.
		</p>
		
		<div class="warning">
			<strong>NOTE:</strong> Since version 1.0 RC2, it is possible to define Advices not only in classes, but also in functions. This is the 
			major improvement of this release, that also innovates bringing the possibility to load external PHP Advice code and tuning the package 
			to follow the AOP theory more strictly.
		</div>

		<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!DOCTYPE aspect SYSTEM "../aop.dtd"&gt;

&lt;aspect&gt;
    // [CORRECT] This code will work!
    &lt;pointcut ...&gt;
    &lt;![CDATA[
        echo "Here!&lt;br /&gt;";
    ]]&gt;
    &lt;/pointcut&gt;

    // [WRONG] This will not work...
    &lt;pointcut ...&gt;
        echo "Here too!&lt;br /&gt;";
    &lt;/pointcut&gt;
&lt;/aspect&gt;

// [WRONG] This will not work too...
&lt;pointcut auto="before"&gt;
&lt;![CDATA[
    echo "And here again!&lt;br /&gt;";
]]&gt;
&lt;/pointcut&gt;</pre>

		<p>
			Since version 1.0 RC2, Transparent PHP AOP enabled you to load external PHP Advice code. To make things happen, you have to define it
			in your XAD, using the Advice XAD tag. The usage is really simple, and I do not think you will have troubles on it.<br />
			In XAD, to define an external source, do this:
		</p>
		
		<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!DOCTYPE aspect SYSTEM "../aop.dtd"&gt;

&lt;aspect&gt;
    &lt;pointcut ...&gt;
        &lt;advice src="../MyAdviceExternalSource.php" /&gt;
        &lt;![CDATA[
            echo "Here!&lt;br /&gt;";
        ]]&gt;
        &lt;advice src="../MyAdviceExternalSource2.php" /&gt;
        &lt;advice src="../MyAdviceExternalSource3.php" asrequire="true" /&gt;
    &lt;/pointcut&gt;
&lt;/aspect&gt;</pre>

		<div class="warning">
			<strong>NOTE:</strong> Since version 1.0 RC 3, it is possible to have two different behaviors of external advice code. This is controlled
			by <strong>asrequire</strong> XAD attribute (default value is <strong>false</strong>), and does this:
			<ul>
				<li>
					<strong>asrequire="true"</strong>: Instead of the whole source being loaded, only a require call is appended to the compiled file.
					This optimizes the necessary compiler time in around 90%!
				</li>
				<li>
					<strong>asrequire="false" or not defined</strong>: Ihe file source is retrieved and appended to the compiled file.
				</li>
			</ul>
			The tendency of this package is to move to default behavior as a require (asrequire="true"), since it optimizes A LOT of the necessary compiler time.
		</div>

		<p>
			By doing this, you will load the file "MyAdviceExternalSource.php", that MUST have the &lt;?php and ?&gt; tags to enclosure PHP code.<br />
			This works exactly like any other PHP script, that you can close the PHP tag, print some HTML and then turn back to PHP. Just remember
			that PHP code must contains the PHP tags.<br />
			The Pointcut instance will, then, contains the merge of all defined Advices (CDATAs and Advices). To retrieve the whole merged code,
			you can access this: <code>$advice = & $pointcut->getAdvice();</code><br />
			You will experience that $advice variable will contain an instance of Advice class.
		</p>
		

		<h4><a name="4_2_3">4.2.3.</a> Applying restrictions</h4>
		
		<p>
			Restriction attributes will filter the occurency of your Advice in compiled code. This is obvious, but there are some restrictions that
			must be defined.<br />
			These filters enable you to define the Advice exactly in a Join Point or Pointcut. Read the attributes carefully, they have a lot of
			meaning in the way of package works.
		</p>
		
		
		<h5>auto="begin|after|around"</h5>
		
		<p>
			This is optional, but if not set, the attribute "name" must be defined.<br />
			If this attribute is included, this exposes which AutoPointcut will have the following Advice code. Since version 1.0 RC 1, it is
			possible to define one of the two possibilities, and version 1.0 RC 3 implements another one:
			
			<ul>
				<li>
					<strong>begin</strong>: defines the Advive in the beginning of the method;
				</li>
				<li>
					<strong>after</strong>: defines the Advice in the end of the method. If a exit, return or anything that goes out of the function is defined,
					the Advice will be applied there too;
				</li>
				<li>
					<strong>around</strong>: defines the Advice in the beginning and at the end. A "proceed();" statement is define, generating two possible behaviors:
					<ul>
						<li>
							<strong>With proceed(); call</strong>: The previous code is appended at "before" AutoPointcut and the code after the wildcard is appended 
							at "after" AutoPointcut.
						</li>
						<li>
							<strong>Without proceed(); call</strong>: The whole source is retrieved and attached at "before" and also attached at "after" AutoPointcuts.
						</li>
					</ul>
				</li>
			</ul>
		</p>

		<div class="warning">
			<strong>NOTE:</strong> Since version 1.0 RC 3, it is possible to use "around" AutoPointcut. Altho this is a great utility, you have to be careful about how
			to use it. You can use it without any problems, but there are some cases that you MUST pay attention: when you are using levels. What does this means?<br />
			A level is when you have some nested block inside, like an if statement, while statement, try-catch, etc.<br />
			I will highlight one example:
			
			<pre>
function getLine() {
    if ($this->line < 0) {
    	return 0;
    } // end of if statement
	
    return $this->line;
} // end of method</pre>
			
			A simple code, but can cause some headache, specially if I want to apply this Advice:
			
			<pre>
&lt;![CDATA[
    try {
        proceed();
    } catch ( Exception $e ) {
        die( $e->getMessage() );
    }
]]&gt;</pre>

			When I compile, It will result in this compiled file (I added identation to show you the problem):
			
			<pre>
        function getLine() {
            /* AOP "before" Auto Code */
            try {
                if ($this-&gt;line &lt; 0) {

                /* AOP "after" Auto Code */
                } catch ( Exception $e ) {
                    die( $e-&gt;getMessage() );
                }

                return 0;
            } // end of if statement
        } catch ( Exception $e ) {
            die( $e-&gt;getMessage() );
        }

    /* AOP "after" Auto Code */
    } catch ( Exception $e ) {
        die( $e-&gt;getMessage() );
    }

    return $this->line;
} // end of method</pre>

			As you can see, the last curly brace is two levels out of scope. Then the compiles file will generate successfully, but when loaded, 
			it will report a fatal error.<br />
			<br />
			My recommendation is to do not use levels inside an "around" AutoPointcut or do not use more than a single return statement in the 
			method declaration. PLEASE, PAY ATTENTION ON THIS PART!<br />
			I still need to plan in a solution to it. Currently, the only I can see is a internal complete reestructure of the compiler. Maybe a
			true compiler implementation, a PHP AST Compiler. =\
		</div>
		
		<h5>name="...[, ...]"</h5>

		<p>
        	This is optional, but if not set, the attribute "auto" must be defined.<br />
            If this attribute is included, this exposes which CustomPointcut will have the following Advice code.
		</p>
		
		<div class="warning">
			<strong>NOTE:</strong> Since version 1.0 RC2, it is possible to define more than one join point for each Pointcut. All you have to 
			do is to separate the name with comma, i.e., if you want to define a Pointcut to be applied in MyJoinPoint1 and MyJoinPoint2, just 
			set the name as this: <code>&lt;pointcut name="MyJoinPoint1, MyJoinPoint2" ...&gt;...&lt;/pointcut&gt;</code><br />
			This new feature can be applied to all properties of Pointcut XAD tag.
		</div>

		
		<h5>function="...[, ...]"</h5>
		
		<p>
			Optional attribute. By defining it, it restricts the Pointcut to that function. If the compiler code is not inside the defined function,
			it is impossible to retrieve Advice code.<br />
			Since Release Candidate 2, it is possible to implement a multiple Pointcut Advice code. Like an array, you define the same Advice to 
			more than one function. Read the note box above.
		</p>
		

		<h5>class="...[, ...]"</h5>

		<p>
			Optional attribute, but if defined, it restricts the Pointcut to that class.<br />
			The implementation of multiple Pointcut Advice code is allowed in this attribute.
		</p>
		
		
		<h5>nfunction="...[, ...]"</h5>
		
		<p>
			Optional attribute. By defining it, it restricts the Pointcut to other function, but not the defined. If the compiler code is inside the 
			defined function, it is impossible to retrieve Advice code.<br />
			This restriction was added in Release Candidate 3, and can deal with array definitions.
		</p>
		

		<h5>nclass="...[, ...]"</h5>

		<p>
			Optional attribute, but if defined, it restricts the Pointcut to all classes, except the listed ones.<br />
			This restriction was added in Release Candidate 3.<br />
			The implementation of multiple Pointcut Advice code is allowed in this attribute too.
		</p>


		<h3><a name="4_3">4.3.</a> PHP Class Code</h3>


        <h4><a name="4_3_1">4.3.1.</a> Custom Pointcuts</h4>
        
        <p>
        	The original release of Transparent PHP AOP covered just custom pointcuts. This is the basic - but powerful - functionality of this
        	package, that solves all your wishes while talking about include special behaviors in your class code.<br />
        	A Custom Pointcut, usually written in a single word, is a Join Point (AOP theory) that enables you to define points that XAD can 
			incorporate custom Advice code. XAD must define the "name" pointuct attribute in order to include special Advice code in the 
			CustomPointcut.
        </p>
        
        <p>
        	A Custom Pointcut is defined using a PHP special comment, like this: /// Pointcut: XXX<br />
        	Changing XXX to your pointcut desirable name, you have a Join Point defined. The following 2 codes describe a PHP Class and a XAD:
        </p>
        
        <pre>
&lt;?php

class Test {
    ...

    function someMethod($arg1, $arg2) {
        // Some stuff here
        ...
		
        /// Pointcut: simpleCustomPointcut
        ...
    }

    ...
}

?&gt;</pre>

		<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!DOCTYPE aspect SYSTEM "../aop.dtd"&gt;

&lt;aspect&gt;
    &lt;pointcut name="simpleCustomPointcut" class="Test"&gt;
    &lt;![CDATA[
        echo "Here!&lt;br /&gt;";
    ]]&gt;
    &lt;/pointcut&gt;
&lt;/aspect&gt;</pre>


		<h4><a name="4_3_2">4.3.2.</a> Automatic Pointcuts</h4>
		
		<p>
			This is the cute little baby of this package.<br />
			An Automatic Pointcut, usually called as AutoPointcut, is a Pointcut that strictly follows AOP theory. You do not need to define a PHP
			comment in your class code. All you have to do is to define the Advice code in the XAD file. To be applied in an AutoPointcut, you must
			have to use "auto" attribute of pointcut XML node. The "Quick Tutorial" section exposes exactly how to use this feature. Please move to
			there and take a look at XAD file.
		</p>
		
		
		<h3><a name="4_4">4.4.</a> Application Loading</h3>
		
		
		<h4><a name="4_4_1">4.4.1.</a> Loading Class File</h4>
		
		<p>
			Simple as take a lolipop from a child. This is how I describe the expertise needed to compile and load the class file using AOP
			approach.<br />
			Currently, you have your class inclusion using probably this: require_once "class.MyObject.php";<br />
			To incorporate the AOSD, you simply have to change this command to: require_aop("class.MyObject.php", "myXAD.xml");
		</p>
		
		<p>
			I will explain in detail. the require_aop function takes 2 arguments:
			
			<ul>
				<li>Original Class File Path</li>
				<li>Aspects to be incorportated</li>
			</ul>

			The second argument accepts a wide range of possibilities:

			<ul>
				<li>"XAD.xml"</li>
				<li>"../some/dir"</li>
				<li>array("XAD.xml" [, ...])</li>
				<li>Aspect::from("XAD.xml")</li>
				<li>array(Aspect::from("XAD.xml") [, ...])</li>
				<li>new Weave("XAD.xml" [, ...])</li>
				<li>new Weave(array("XAD.xml" [, ...]) [, ...])</li>
				<li>new Weave(Aspect::from("XAD.xml") [, ...])</li>
				<li>new Weave(array(Aspect::from("XAD.xml") [, ...]) [, ...])</i>
				<li>new Weave("../some/dir" [, ...])</li>
			</ul>
			
			As you can see, it is possible to use directories as a Weave. This will track for last modified date of the directory, and will
			recompile the package if necessary. A Lazy Load Pattern is implemented internally, to prevent looping though directory's content
			before the right time.<br />
			Aspects are loaded from Unique instances (Singleton), to prevent memory leak. Also, a Registry Pattern is implemented internally.
		</p>
		
		<p>
			So, I want to incoporate the "myXAD.xml" Aspect Definition file into my Original Class file "class.MyObject.php". First you have to
			load the require_aop function (that includes the whole AOP system), by loading the "func.require_aop.php" file.<br />
			After that, you can load your class via require_aop function, something like this:
		</p>
		
		<pre>
require_aop("class.MyObject.php", "myXAD.xml");</pre>
		
		<p>
			The whole example can be found in "Quick Tutorial" section, described in the beginning of this manual.
		</p>
		
		
		<h4><a name="4_4_2">4.4.2.</a> Modifying Compile Options</h4>
		
		<p>
			People usually ask my about the Compiler Options. I have to tell you that you do not need to modify Compiler Options, as soon as you
			are really sure of what are you doing. I enabled the Compiler Options just to simplify programmers life, but they maybe not recommended 
			for production usage.
		</p>
		
		
		<h5>AOP::CACHE("...");</h5>
		
		<p>
			Default value: <strong>Original Class file directory</strong>. To reset its value, use AOP::CACHE(".");<br />
			If you define another directory to AOP using this property, all the compiled class codes will be created there. This is very useful if
			you do not want to mantain all your folders with permissions to read/write. The argument to be passed is a valid directory.<br />
			Please remember that this property just configure the compiled files directory, it do not rewrite the current directory. For this, 
			take a look at <a href="http://www.php.net/getcwd" target="_blank">getcwd<a> and 
			<a href="http://www.php.net/chdir" target="_blank">chdir</a> PHP functions.
		</p>


		<h5>AOP::COMPACT(true|false);</h5>

		<p>
        	Default behavior of this property is <strong>false</strong>.<br />
        	If defined as "true", the Advice code will not be compacted, and lines reference between original class file and compiled file can
			differ. This is a very useful tool if you are looking for PHP Advice code error, but it is not the ideal thing to use it in production
			environment; although it will not overhead your system an will not implicate in load time. It is not recommended just because of the
			changes in the lines.
		</p>


		<h5>AOP::RECOMPILE(true|false);</h5>

		<p>
			Default behavior is <strong>false</strong>.<br />
			I really do not know why I added this. Maybe to satisfy "build on-the-fly" fans.<br />
			If you define this property as "true", every time your scripts runs, it will recompile the AOP compiled file, even if both files (XAD
			and Original Class) have not been changed.
		</p>

		<div class="warning">
			<strong>NOTE:</strong> Do not use this in production environment.
		</div>
	</body>
</html>
Return current item: Transparent PHP AOP