Aspect-Oriented Programming in PHP

Aspect-Oriented Programming in PHP

Tutorial Details
  • Language: PHP
  • Framework: Flow3
  • Difficulty: Advanced

There’s a new player in town, and he brought new toys: The PHP World welcomes FLOW3, an enterprise application framework written and backed by the community of the TYPO3 CMS. FLOW3 can be used as standalone full-stack framework for your applications. It’s interesting, because it introduces some concepts of software development that haven’t been adapted to PHP before.

Among these new concepts is “Aspect Oriented Programming”. We will have a look on the theory of the pattern, and will set up a basic FLOW3 Application and weave in our own aspect!


Why Should I Care?

If a new framework hits stable, an excellent question to rise might be: What can it do that the tools that I love can’t?

PHP already has an armada of excellent frameworks and most of them claim to be written with separation of concerns in mind. So does FLOW3.

In terms of software development this means, that the classes that are implementing the logic of your application should only care about one thing. For example, a mailer class should send mails. It should not retrieve potential receivers from a database.

All modern frameworks (including FLOW3) push a lot of patterns into the software stack that do a great job at separating the concerns of your business logic; among them the famous MVC that is separating your logic into different layers.

However, an application is not only built on business logic alone. As it grows, you may want to implement additional services, features, plugins or plugins of plugins. You surely don’t want this stuff in your business logic! But what are your options?

Let’s say you want to implement a logging service that writes some stuff to a text file every time a specific set is deleted from the database. Naturally, the logging service is not part of your database layer. But in order to make it work, you have to place some code right there, like this:

/**
 * Delete a user
 * @param UserModel $user
 * @return void 
 */ 
public function deleteUser(UserModel $user) { 
$this->loggingService->log('removing user ' . $user->getName()); 
$this->users->remove($user); 
}

Horrible, isn’t it? Let’s face it: The logging service adds dirt to your code. You have to touch the original code in order to implement it and you add an additional dependency, in this case an instance of the LoggingService.

Hence, you’re adding complexity. And you likely will have to add it all over your app (depending on what else you want to log).

You may come up with an pattern like an event dispatcher or a hook system like it’s implemented in Drupal and WordPress and then have your logger listen for events:

/**
 * Delete a user
 * @param UserModel $user
 * @return void 
 */ 
public function deleteUser(UserModel $user) { 
$this->eventDispatcher->dispatch(self::USER_DELETED);
$this->users->remove($user); 
}

This is better, but it’s still not cool. You’re code is still dependency aware: it has some code with the sole purpose of informing other parties that something happens.

This has some bad side-effects: What if you want to log something, but there’s not an event dispatched at that time? What if you haven’t written that code because you are writing a plugin? You’d have to change the original code – not once, but every time an update is available.

Let’s call the logging service an aspect and see how FLOW3 takes care of the problem.


Aspect Weaving

Our logging service is only interested in one thing regarding the existing code: It wants to intercept it in some classes at various points (e .g. when something is deleted). With the implementation discussed above, the existing code controls the points of execution.

Wouldn’t it be nice if the service could define a set of rules at which point it would want to inject itself into the class?

This is a software development concept named Inversion of control. It decouples classes from another, because there’s no need to change existing code when you’re changing the service. The service takes care of this itself.

Let’s say we simply want to execute logging on every method in every class that starts with delete, like deleteUser(), deleteEntry() or whatever. A convenient way would be to write a rule into the logging service and let the framework take care of the correct execution of the code. This is remarkably easy in FLOW3:

/**
 * An aspect that is executed on all methods that start with "delete". 
 * 
 * @FLOW3\Before("method(.*->delete.*())") 
 */ 
 public function logginMethod() {
// Do some logging here.
 }

FLOW3 performs some really advanced PHP techniques under the hood.

The rule is named pointcut in AOP and there are some easy-to-learn ways to define them. The one above tells FLOW3 to inject the logging code in every class before every method that starts with delete.

It does so by using the method keyword and by adding wildcards (*) for the class and for parts of the method name. If you’re adding this code in an Aspect Class (as we do later), you’re good to go. You will be able to access properties of the class that you are targeting as well. The targeted class itself remains untouched. It may not yet be written – if it’s added to your app in the future, the rule will then match and the code will be injected.

Maybe you have read the above paragraph twice and are asking yourself: Is this magic? What’s the damn trick? – I sure did, when I was first introduced to AOP!

Well, AOP has been around for some time in the Java world. FLOW3 is heavily inspired by the AOP implementation of Spring, a Java Framework. The word was on the street, that the pattern can’t be transferred to interpreted languages, because it requires compilation.

The trick is, that the framework – or some tools like JAspect – intercepts the compilation process (from Java code to bytecode, that can be executed by the Java runtime) and do an analysis of the defined aspects. Whenever a set of rules (aka the pointcut) matches a method, it is weaved directly into the compiled code. Hence, the framework takes care of merging the code parts together:

FLOW3 did adapt that concept to the world of PHP by introducing an advanced cache. While most frameworks offer caching to increase performance, FLOW3 additionally uses the cache to weave aspects into the original classes.

If you are running your app, FLOW3 delivers the cached classes instead the ones you’ve written. Hence, your original code remains untouched.

This sounds complex – and it is: FLOW3 performs some really advanced PHP techniques under the hood, that are well worth to be explored! But: To you as an application developer, it’s not complicated at all. You don’t have to care, if you don’t want to: FLOW3 monitors your files for changes and if you make some, FLOW3 auto-commits them to the cache upon your next request. If an aspect matches to a method, it’s automatically weaved in – no further configuration needed.

It’s a complex pattern conveniently at your service!


A Few Words About the Cache

Every cool feature comes with a downside – so does FLOW3. At the moment, we just scratched the surface of what FLOW3′s caching-mechanism is capable of, but I want to give you an idea.

Take a look at the following code:

/** 
 * @FLOW3\Inject 
 * @var \YourApp\MailerServiceInterface
 */
 protected $mailer;
/**
 * Sends a mail.
 *
 * @param \YourApp\Model\User $user
 * @param string $message
 */
 protected function sendMail(\YourApp\Model\User $user, $message) {
     // Sends a mail.
 }

The consequence is that PHP is to some degree no longer an interpreted language.

This may look like some code that is just well documented. But it’s much more.

The first property annotation (FLOW3\Inject) tells FLOW3 to look for some class in your app that implements the MailerServiceInterface and injects it here (and maybe configure it before). This pattern is known as Dependency Injection.

The second class defines some type definitions in its comment’s annotations – and FLOW3 uses them. If you’re giving the method some data that can be used to build a User object of your model (for example an array with pure strings from a HTML form), FLOW3 auto-transforms the data safely to a User object and applies some security and validation rules to the second parameter (in this case a string).

This is (among some other tricks) done by weaving in some code into the cache.

The consequence is that PHP is to some degree no longer an interpreted language. The process of caching is somewhat similar to compiling and it has the same downsides: You can’t just save & refresh your browser, you have to wait for the cache to be warmed up during development. If you are committing code to your production environment, you have to flush the cache in order to see the changes.

On top of that, FLOW3 adds some kind of type-validation at runtime: You can’t pass an integer as second argument in the example above – it’ll throw an error. I really like this, because I have a background in strictly typed languages like Java and ActionScript. It also adds a lot of security to your application. But if you’re a PHP purist, this may be something that you don’t want.


Setting Up Flow3

Alright, enough with theory. Let’s get our hands dirty.

Setting up FLOW3 is pretty straightforward, if you already have a PHP-capable server like XAMP or MAMP installed. Just grab a copy of the framework from FLOW3′s download site (or clone from git) and unpack it into your htdocs directory.

You should already be done now on Windows machines. Unix-based systems like MAC or Linux need to grant the required rights for building the cache. FLOW3 ships with a powerful command line tool, that packs this task into a one-liner:

# On linux:
./flow3 core:setfilepermissions chris www-data www-data
# On Mac:
./flow3 core:setfilepermissions chris _www _www

Please replace chris with your username! This should be enough. However, I’ve installed FLOW3 on
various machines and have run into some problems. The most common ones are:

  • If you’re on MAC and FLOW3 complains “index.php not found “, open the .htaccess in the webdir and add a # before the line Rewrite Base /“–
  • If you’re on Windows and the command line tool does not work, open Settings.yaml.example in FLOW3′s configuration directory, uncomment and adjust the phpBinaryPathAndFilename variable to the correct path (e.g. C:\xampp\php\php.exe) and save the file as Settings.yaml

  • On some machines, if FLOW3 is very slow, you have to increase the memory limit of PHP in the php.ini

If you run into problems, that are not listed here, please post them in the comments!

Now fire up your favorite browser and navigate to http://localhost/flow3/Web! FLOW3 should welcome you with an introduction screen:

The first run may take a while, as FLOW3 has to index your code and build all caches.

This is the Welcome Package. Every application in FLOW3 (and FLOW3 itself) is a package and packages can share code with each other. For example, once the new TYPO3 Version is finished, you can add it as a package and your application will then have an enterprise-ready CMS on top!

Let’s start our own package. It’s an easy task, because FLOW3′s command line tool will handle most of the work! Type in the following command:

# On linux / MAC
./flow3 kickstart:package Nettuts.AspectDemo
# On Windows
flow3 kickstart:package Nettuts.AspectDemo

This will create a ready-to-go package named Nettuts.AspectDemo in FLOW3′s Packages/Application folder. If you review the file structure, you will find many folders that do follow a specific convention.

The important ones are:

  • Classes: The home of your PHP Code, a first Controller is already created in the Classes/Controller Folder: the StandardController!
  • Resources/Private: The home of all templates that are fired into Fluid, FLOW3′s powerful Templating Engine. It hosts some other stuff like localization files as well.
  • Resources/Public: This has not been created yet, but every file in the Resources/Public folder will be directly accessible from the web. This is a good place for images, CSS, Javascript etc.

Building a full-featured app is beyond the scope of this tutorial, so we’ll go with the defaults. Please open the following URL: http://localhost/flow3/Web/index.php/Nettuts.AspectDemo

This is not much, but it’s a start. We want to write something to a logfile, every time this site is called. We do this by weaving in an aspect into the StandardController!


Writing a First Aspect

Take a look at the StandardController in theClasses/Controller Folder in your Nettuts.AspectDemo Package.

It implements a method, named indexAction(). FLOW3 has automatically configured our app in a way, that this method inside the StandardController gets called when we enter the URL above.

For the moment, we see that this method assigns some strings to the view:

/**
 * Index action
 *
 * @return void
 */
public function indexAction() {
$this->view->assign('foos', array(
'bar', 'baz'
));
}

If you open the file index.html of this view in Resources/Private/Templates/Standard inside our package, you’ll see how these strings are processed by the templating engine.

However, our goal is to intercept the code execution before this method gets called.

At first, create an empty file named Access.log in FLOW3′s Log folder at flow3/Data/Logs. You may save this file wherever you want, but this is a nice place for log files.

Next, create a folder named Service in your Nettuts.AspectDemo/Classes Folder and inside of it, create another folder, and name it Logging. Then create a PHP file named LoggingAspect.php inside of it. It should have the following content:

<?php
namespace Nettuts\AspectDemo\Service\Logging;
use TYPO3\FLOW3\Annotations as FLOW3;
/**
 * @FLOW3\Aspect
 */
class LoggingAspect {
   /**
    * Log a message if this site is called.
    *
    * @param \TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint
    * @FLOW3\Before("method(Nettuts\AspectDemo\Controller\StandardController->indexAction())")
    * @return void
    */
   public function logSiteAccess(\TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint) {
           $filePath = '/home/chris/www/flow3/Data/Logs/Access.log';
     $message = 'The site has been accessed at ' . time() . '.' . PHP_EOL;
     file_put_contents($filePath, $message, FILE_APPEND);
   }
}
?>

This is a very basic class, and if you’d like to have an advanced logger, you may want to separate the logging from the intercepting aspect.

What’s going on here? At first, we define a namespace, which is your package name and the path to the actual class (without the class folder itself). Next, we import FLOW3′s annotation namespace. Thus, we can use FLOW3′s powerful annotation parser to configure our class.

That’s exactly what we do in the class comments. We define the class as aspect with the following annotation:

/**
 * @FLOW3\Aspect
 */

From now on, FLOW3 is aware that this class may define rules for the interception of the code flow and watches our codebase for matches.

This is the rule:

@FLOW3\Before("method(Nettuts\AspectDemo\Controller\StandardController->indexAction())")

We could use regular expressions or some other techniques to match multiple methods or classes, but we know exactly where we want to go: Before the indexAction() Method in the StandardController – and that’s exactly what we’re telling FLOW3.

Note the $jointInterface Parameter of the logSiteAccess() Method, that is provided to us by FLOW3. We don’t use it here, but it contains some useful data about the actual context. For example, if the intercepted method would have arguments, that we may want to use, we could access them like this:

$argument = $joinPoint->getMethodArgument('argumentName');

The code in our logSiteAccess() method, itself, is fairly simple. Just adjust the path to the Access.log to your environment and you’re good to go!

Now, again, open http://localhost/flow3/Web/index.php/Nettuts.AspectDemo – nothing should have changed. But when you open the Access.log file, you should see the following entry:

The site has been accessed at 1335715244.

If you can read this, the aspect has been weaved into the cache. Let’s have a look at the magic!

FLOW3 stores the cache at flow3/Data/Temporary/Development/Cache/Code/FLOW3_Object_Classes.

You will find a class named Nettuts_AspectDemo_Controller_StandardController_Original.php. This is the original class from our codebase.

But there is another class: Nettuts_AspectDemo_Controller_StandardController.php. This class extends our original class and it is build up purely by generated code. Among the many lines you’ll find something like this:

$this->FLOW3_Aop_Proxy_targetMethodsAndGroupedAdvices = array(
   'indexAction' => array(
      'TYPO3\FLOW3\Aop\Advice\BeforeAdvice' => array(
         new \TYPO3\FLOW3\Aop\Advice\BeforeAdvice(                  
         'Nettuts\AspectDemo\Service\Logging\LoggingAspect', 'logSiteAccess'         
         $objectManager, NULL),
         ),
      ),
);

This is were FLOW3 initiates the aspect and it’s weaved in directly into your class. The aspect gets executed right where we want it – without touching the original controller.

The code snippet initiates an instance of the BeforeAdvice class, with our aspect, the respective method and the $objectManager as arguments. The object manager contains the needed information to build the jointInterface, that is passed to the aspect.

If you’re interested in the details, have a look at the AOP Folder in the FLOW3 package!


Conclusion

The aspect oriented approach has many advantages waiting to be discovered.

The aspect oriented approach has many advantages waiting to be discovered. For example, FLOW3 uses AOP to intercept its own bootstrap to build up a firewall if you choose to use FLOW3′s security framework. Apart from that, we haven’t yet discussed the specific terminology that is commonly used in AOP.

However, FLOW3 ships with some other unique concepts like Domain-Driven-Design. It has a powerful Doctrine integration and a smart Templating Engine. We have only seen the tip of the iceberg!

What’s your opinion? Are you eager to learn more about the philosophy behind FLOW3? What’s your impression of AOP? Are you excited to have a robust port for the PHP world or do you think it’s too much overhead for an interpreted language?

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • https://timshomepage.net Timothy Warren

    The term “enterprise” always makes me cautious. While I’m sure this solves some issues on huge projects, I see it as overkill for most php projects.

    It also adds a lot of complexity.

    The whole framework also makes me kind of leery. That’s a LOT of code as a starting point.

    Quite frankly, when you put something vital to code operation in comments, it seems like you are doing it wrong.

    • Chris
      Author

      You got a point there. Many people tend to dislike comment annotations that are vital to code: Code should be treated with code.

      However, basically it’s a separation of configuration from code. And annotations give you the option to keep your configuration nearby the affected code.

      You’re right as well when it comes to complexity. FLOW3 is not for the everyday blog or musicican homepage. It was build with one of the most complex CMS outthere (Typo3) in mind, it’s build for huge, enterprisy projects.

      Projects where the inital setup (aka the startpoint) tends to be not as important as overall and future proof maintenance.

    • http://inkwell.dotink.org Matthew J. Sahagian

      @Timothy, spot on.

      There is a growing desire to make PHP very similar to much more complex languages, frameworks, and the design patterns used in them, and quite frankly, I think it’s generally a bad idea. It all started with namespaces which were mashed into the language without much thought or foresight and now make programming not only more tedious, but far less intuitive: http://pornel.net/phpns

      @Chris

      There are much better ways to separate configuration from logic (which I will assume is what you meant instead of separate from code. I’m not sure if it was noted in the article, but I assume this relies heavily preloading the relevant classes, reflecting their code definition with comments, parsing the rules, and then defining them somewhere in actual code so they can be used in the framework logic. There’s a good way to skip the first three steps in that process, and that is simply to define them somewhere in actual code.

      Keep in mind, this does not mean they have to be jammed within the logic. They could easily be in a configuration file somewhere. http://inkwell.dotink.org/configuration goes over the configuration methodology I use in my framework and shows that you can have a class oriented configuration with various and meaningful keywords, that not only afford the ability for configuration to take effect on class load (rather than instantiation), but also the ability to preload those classes.

      Admittedly, the one thing my framework does lack at the moment is any extensively developed points for hooks. At some point I will most certainly be adding various hooks during the initialization process, so it could easy be the case that you would preload classes which in turn would load their configurations when they are loaded (not instantiated), and have them immediately register a whole host of hooks.

      Also, I’m not sure you have really overcome dependencies as much as it has been moved with this. Aside from the wildcard example, anything more specific would have to match a class and method the same as traditional hooks or observer type patterns. It may be true that the “code won’t break” if a class name or something like that changes because it’s not actually in the code, but my assumption here is that the code won’t really work either. At least, not as intended. It’s kinda like a hybrid car with a battery and gas… if the batteries die, your car is broken to the point that you can’t get from point a to point b, but you can’t really say it’s not broken at all.

      • http://digitale-avantgarde.com Chris
        Author

        I found that discussing annotations is like discussing politics and religion :) But let’s try.

        Maybe configuration is not the right word, because it’s really close to logic (which i mean btw, sorry, I’m not a native english speaker).

        However, let’s have a look at the controller: You pass a parameter, e.g. a string. As a good developer, you add the type in the comments anyway. It’s just a personal preference, but I think: Why not using this? Why duplicate? If you add this in a configuration file somewhere, you have to adjust this twice if the parameter changes.

        Developers have to look twice to understand whats going on. The data may come in from someone, you have to check it anyway (at least for security reasons), why not giving it away to the framework? You don’t have to care about it. Of course, FLOW3 pushes you to appropriately comment your code. If you don’t like it, it may not be the right framework for you.

        FLOW3 gives you options. E.g. you don’t have to do Dependency Injection via comments. FLOW3 supports setter injection as well as constructor injection or you could add a injectMyProperty() method and it will work.

        However, annotations are in FLOW3 by design. If you don’t like it, you may stick better with symfony (which gives you more options) or with your own framework.

        In the end, every framework has a basic principle: Convention over configuration. One of FLOW3s conventions is, that some configuration can/must/should be done with annotations. If you don’t like this convention, chances are you don’t like the framework.

  • pierlo

    I’d love to check this out, but the required terminal access is a drag for me, as most website hosting providers don’t offer such a feature for cheaper plans.

    • http:/bloggiver.blogspot.mx OliverHR

      Terminal is only for development, but in fact Flow3 team are working on a non terminal way to generate the framework stuff.

    • http://digitale-avantgarde.com Chris
      Author

      This is not necessarily a problem: Terminal access is not required, it’s a feature. It helps you getting the job done faster.

      You could use the terminal commands with some minor tweaks, because they are written in pure php and you could place the stuff needed for production environments (database migration / versioning, cache flushing) into your administration area and call it via URL instead of the terminal.

      If you develop locally and push to your production server, you can abandon terminal related logic on your production environment completly, if you have to: All you’d have to do is flushing the cache (e.g. deleting the content of the respective folder) and migrate the database.

      However, like all modern frameworks, FLOW3 makes heavy use of 5.3-and-later PHP Features like namespacing and has some php.ini settings that are (for reasons of backwards compatibility) not common on shared hosting.

    • http://inkwell.dotink.org Matthew J. Sahagian

      @pierlo

      I never understood the “required terminal access is a non-starter” argument as it relates to cheap hosting. If you have cheap hosting, I assume you’re using something like FTP or SFTP to upload your files onto your web server. Why don’t you just run the terminal commands, etc, on your local system and then upload the changed files?

      Pretty much every “required” (even though they’re not required) terminal commands are for code generation, modification, etc, which inevitably effects the files in the framework. There is nothing insanely difficult about installing PHP on Mac or Windows, and definitely not Linux or most other *nix systems.

      My assumption here of course, is that you do maintain a local copy of all the files on the site anyway so that you actually work on them on your system, and then upload…. right? How is any code generationg or modifying command/terminal a non-starter on your local system/working copy?

      • Philipp Gampe

        FLOW3 has build in support for deployment :)

  • http:/bloggiver.blogspot.mx OliverHR

    AOP and Inversion of Control, is the trend for the new php frameworks.

  • Sergey

    Very interesting pattern. I’ve never heard about it. Thanks for expanding it!

  • http://ph-7.github.com Pierre

    Thanks!

  • http://www.brianscaturro.com Brian Scaturro

    I have to agree that this is attempting to make a language like PHP something that it is not. AOP is great, and really helps manage those cross cutting concerns, but I have to wonder if PHP is built for that. Traits in 5.4 might be a better choice. AOP is a lot more robust and useful in a language like C# that supports attributes, and has great tools like postsharp.

    • David

      Dude you look like Phillip Phillips!

  • Franklin

    Hi Chris, I have been trying to set up things but I get the error below; I tried to do what you wrote about changing the path but still getting the error I have installed wamp. Can you help me please? I am very interested in making the example.

    Thanks.

    Uncaught Exception in FLOW3
    #1315561483: It seems like the PHP binary “C:\php/php” cannot be executed by FLOW3. Set the correct path to the PHP executable in Configuration/Settings.yaml, setting FLOW3.core.phpBinaryPathAndFilename. (More information)

    TYPO3\FLOW3\Exception thrown in file
    C:\wamp\www\FLOW3-1.0.4\FLOW3-1.0.4\Packages\Framework\TYPO3.FLOW3\Classes\Core\Bootstrap.php in line 420.
    Reference code: 20120510165330136e63

    Go to the FORGE issue tracker and report the issue – if you think it is a bug!

    • http://digitale-avantgarde.com Chris
      Author

      Thanks for your interest!!

      Your error reports that something went wrong with the configuration settings.

      This can be caused by several problems, so let’s lool. First of all, check if the file you saved the settings.yaml.example to is really named settings.yaml! For example, if you used netbeans as code editor, it may have saved the yaml file as settings.yml (something that caused me a headache once …).

      If this is true, check if the yaml file is written well. Blank spaces do matter in yaml. So tab intends do not work, it has to be spaces! I’ve posted a working settings.yaml here, but you may adjust it to your actual php version: http://pastebin.com/WrhkkGRC

      If this does not work as well, please post your settings.yaml to pastebin.

      Meanwhile you can workaround by adjusting flow3.bat in a text editor. This file does nothing else than executing a PHP file and it needs the right settings.

      Have a look on it an adjust the SET Parameter. This may look like this, again you may have to adjust the path:

      @ECHO OFF

      REM Replace the following line with the path to your PHP executable if required
      REM This can include the php.ini to be used (for example “SET PHP=C:/php/php.exe -c C:/php/php.ini”)

      SET PHP=C:/wamp/bin/php/php5.3.8/php.exe

      %PHP% Packages/Framework/TYPO3.FLOW3/Scripts/flow3.php %*

      • Jimako

        Hi Chris, great work, thank you.
        I really would like to try Flow3, but I’ve got the same mistake like Franklin. Changes in yaml or flow3.bat didn’t help.

        By the way, at first I tried version 1.1 with virtual server (step by step of The Definitive Guide, but I still have mistake> FLOW3 – 500 Internal Server Error.) Then I delete virtual server, tried on normal server (xampp/htcdocs), found more advices about changes in htaccess… nothing helped)

        So I tried fresh installation of version 1.0 on localhost, xampp and I got mistake:
        #1315561483: It seems like the PHP binary “C:\php/php” cannot be executed by FLOW3…

        Then I found on http://wiki.typo3.org/wiki/Exception1315561483:
        Throwing an exception when using a FLOW3-based application on a server with a Windows environment.
        Solution: Not found yet!

        I spent almost all day on trying only install Flow3, not to learn it or use it. I am really dissapointed in this time, but propably I will tried it again some time later. It really seems good.

        Thank you for your work.

      • Jimako

        Again me, but I found solution for FLOW3 1.0. (sorry for my English)
        You need set Windows system variable %PHP_BINDIR%
        (it is used in C:\xampp\htdocs\FLOW3\Packages\Framework\TYPO3.FLOW3\Configuration/Settings.yaml on line 36 phpBinaryPathAndFilename: ‘%PHP_BINDIR%/php’)

        For me: PHP_BINDIR C:\xampp

        (plus changes in C:\xampp\htdocs\FLOW3\Configuration/Settings.yaml, but it’s not necessary in typo3.bat)

        I have next problem with links, but this works. Thank again

  • Me, myself and I

    Excellent excellent post. Flow3 looks really great. It somehow does things like Symfony2 right now for DI.

    When you keep studying; you will find articles about DI, application environments (production, development, test); architecture design; quality of code; and when you do you find out that frameworks like this are master pieces.

    I do not see any over-configuration on PHPDoc blocks; devs are suppose to write them already in their code , for jesus christ!

    Hopefully when developers stop doing blogs and musician websites and start doing medium to large web application they will appreciate this great post and frameworks like Flow3.

    • https://timshomepage.net Timothy Warren

      I find that quality of code matters less and less the harder it is to find that line of code.

      Plus this has ton’s of transformation going on. I sure don’t want to have to be the one to hunt down a bug in the Framework.

      • Philipp Gampe

        FLOW3 has good test coverage.

        Tests: 2653, Assertions: 6311, Incomplete: 19, Skipped: 98.

        Lines:
        Functions/Methods:
        Classes:

        TYPO3.FLOW3
        60.70% 8534 / 14060
        52.24% 1075 / 2058
        45.10% 161 / 357

        TYPO3.Fluid
        70.66% 1659 / 2348
        61.02% 227 / 372
        57.78% 52 / 90

        TYPO3.Kickstart
        11.60% 21 / 181
        20.00% 3 / 15
        50.00% 1 / 2

        And for functional tests:
        FAILURES!
        Tests: 137, Assertions: 156, Errors: 18, Incomplete: 40, Skipped: 4.
        (I used the current master … do not know why there are so many errors.

        Code coverage is about 30%. Fluid again with 70%, the other packages beetween 7% to 43%

    • http://digitale-avantgarde.com Chris
      Author

      @Me, myself & I: If you’ve worked with symfony, you’ll quickly experience that both frameworks share common ideas. In fact, the lead developer of FLOW3, Robert Lemke, stated that he would fork symfony if he had to start from scratch today. If you’re experienced with symfony, you’ll be very quickly up and running in FLOW3. Main differences are SOA (symfony) vs Domain-Driven-Design (FLOW3) (which, in my opinion, are not that present during development on real world projects) & FLOW3 is not a component framework (which would not work due to the caching implementation of FLOW3).

      I personally think, that PHP is a great language, that has something for everyone. Again in my personal opinion, PHP should move forward, because the web does. If the language doesn’t move forward, coders will move away. But this is a discussion that maybe far away from the daytime business where you earn money with musicians websites.

      FLOW3 is not for those sites. It’s for big apps. If you’re in the big apps business, FLOW3 is definitely worth a look. It’s about long term maintenance with modern architecture. It just don’t fit for smaller projects.

  • http://www.youtube.com/w3peak/ Junaid Ali

    It’s time people should start working towards a proper “PHP Compiler”,,,, I believe most of the PHP programmers are really happy with Codeigniter and do not really wanna leave PHP, but this CPU Usage issue is killing us…

  • satya

    i need help installing flow3

    i’m getting this error…
    FLOW3 does not support Windows versions older than Windows Vista or Windows Server 2008 (Error #1312463704)

    • Chris
      Author

      I never got this one …

      What kind of operating system are you using and what do you use to run php? XAMPP? Which version?

      • Vadim F.

        Yes, you can’t use FLOW3 on Windows XP. FLOW3 uses (stupidly, I’d say) function symlink, that isn’t available on Windows XP.

  • Mehdi Lahmam B.

    You definitely want to take a look to Lithium, and it’s filter system which is inspired by AOP concepts.
    http://lithify.me/docs/manual/lithium-basics/filters.wiki

    • Philipp Gampe

      OK, I did.

      It looks quite hacky, you have to write your code to support his and it will not work with third party code.

      So compared to FLOW3, it looks like a much more basic approach and is much more difficult to use.

      Please correct me if I am wrong.

  • http://codeforest.net Codeforest

    Hm, Flow3 looks very complicated (is that why you used Enterprise keyword?) and I think that it has really steep learning curve.

    I like what Flow3 is trying to achieve, but think that other frameworks are here to stay.

    • http://digitale-avantgarde.com Chris
      Author

      I like this quote from the original docs: “As a matter of fact, FLOW3 is easier to learn for PHP beginners than for veterans. It takes a while to leave behind old paradigms and open up for new approaches.”

      It’s true, you have to leave your comfort zone – but it pays back.

    • Philipp Gampe

      Have you read the getting started guide? I think FLOW3 is much simpler to learn than most frameworks I have seen.
      http://flow3.typo3.org/documentation/quickstart.html

  • http://robertlemke.com Robert Lemke

    Thanks for this great post!

    One word regarding complexity: AOP is certainly not the easiest topic and not the one a beginner will pick up first. And yet I tried to take the well-proven concepts and PHP-ify them (in the best sense) to give you access to this technique without a lot hassle.

    You might not start learning FLOW3 for a single standard CRUD app – but once you did, even hacking away some simple scripts without FLOW3 feels ugly.

    For a real-world FLOW3 you’ll write so few code that it’s scary. Youl spend most of yourbtimebwith creating concepts (or learning FLOW3 if you just started). But the key is tha FLOW3 is not based on the error-prone concept of scaffolding but on application of standard patterns and a lot of conventions. FLOW3 does not give you the maximum freedom for how you implement an application, but it gives you maximum possibilities to handle even complex projects.

    I don’t need expensive speakers for listening to children’s music with my kids. But if I have them anyway, I enjoy it even more.

  • pejay

    I think FLOW3 is great choice for enterprise projects. Creating web applications based on AOP theory is expected these days, but a good ready-to-go framework was missing.

  • http://techgolpo.com riad

    i really enjoyed …thanx

  • Martin

    I think there’s a little typo in your StandardController.php line 16:

    class StandardController extends \TYPO3\FLOW3\Mvc\Controller\ActionController

    but it has to be

    class StandardController extends \TYPO3\FLOW3\MVC\Controller\ActionController

  • G

    Domain driven design finally arrived to PHP planet:) I really like both DI and AOP solutions and looking forward to test them. I hope flow3 will also try to bring some “killer” features besides barebone framework, like admin module. That kind of feature would make a strong user base.

    • Marc Neuhaus

      I’ve already come a long way to build an Admin Package with FLOW3 :)

      https://github.com/mneuhaus/FLOW3-Admin

      Currently i’m refactoring it quite a bit to integrate it into the next TYPO3 version.

  • Richard

    What you’re referring to as Linux, is in fact, GNU/Linux, or as I’ve recently taken to calling it, GNU plus Linux. Linux is not an operating system unto itself, but rather another free component of a fully functioning GNU system made useful by the GNU corelibs, shell utilities and vital system components comprising a full OS as defined by POSIX.

    Many computer users run a modified version of the GNU system every day, without realizing it. Through a peculiar turn of events, the version of GNU which is widely used today is often called “Linux”, and many of its users are not aware that it is basically the GNU system, developed by the GNU Project.

    There really is a Linux, and these people are using it, but it is just a part of the system they use. Linux is the kernel: the program in the system that allocates the machine’s resources to the other programs that you run. The kernel is an essential part of an operating system, but useless by itself; it can only function in the context of a complete operating system. Linux is normally used in combination with the GNU operating system: the whole system is basically GNU with Linux added, or GNU/Linux. All the so-called “Linux” distributions are really distributions of GNU/Linux.

    • sfw

      *mimimimi*
      You call it GNU/Linux everytime….

      I’m smarter than that, i just “use GNU” an then call it Linux

      so stfu, cuz nbdy likes nitpickers

  • kevin

    Worlds collide! It’s strange, and great, to see a FLOW3 post here on tutsplus – thanks for the great writeup!

    I have a few general questions/thoughts in general:

    1) I understand and am somewhat familiar with the history of and reason for FLOW3 (TYPO3 v5), but even so I wonder why there are references to TYPO3 in the FLOW3 framework? Will they always be there? For instance in the default example, you have “TYPO3″ directories. I realize this isn’t a big issue perhaps, but it just seems like it’d be nice if FLOW3 didn’t have TYPO3 folders by default.

    2) Does FLOW3 still use Doctrine for it’s DB abstraction/ORM? I really like Doctrine, and last time I looked at FLOW3 (almost a year ago) I thought it was pretty great that Doctrine was being used.

    3) I’d love to see more FLOW3 tutorials here, things like your standard CRUD, routing, fluid templating. Perhaps a very simple (classic!) blog tutorial in the nettuts fashion. I realize that perhaps FLOW3 is overkill for many projects, but I always enjoy learning about new frameworks and programming techniques/patterns.

    Thanks again!

    • http://digitale-avantgarde.com Chris
      Author

      Hi Kevin!

      1. First of all, TYPO3 v5 is not the same as FLOW3. FLOW3 is a standalone framework and it will be the basic for the next TYPO3 Version (I know you know that, but for the other readers). For various reasons in the history of both projects (see http://bit.ly/yGAME6), this new version will be a new branch. It’ll not be a substitute, but a new project. This has some consequences, some bad, some good and it’s a hot topic in the community.

      However, the references you’re seeing are not referencing the TYPO3 CMS, but the TYPO3 association. By convention, every package in FLOW3 should consist of the package name and a vendor prefix. The vendor prefix is there to avoid duplicates. I used Nettuts as vendor prefix in my example. Since the FLOW3 Core developers are on the payroll of the TYPO3 Association, they choose TYPO3.

      2. Yes, FLOW3 ships with Doctrine by default and this is the way you’d normally build your apps. You can opt to use another ORM (like propel) or use plain sql (there’s an explanation about how to use another persistence backend in the docs and there are ready-to-go packages for other persistence backends available, for example for the NoSQL MongoDB: http://bit.ly/Jw0Iw8).

      3. Yes, I’d love that too. Maybe not the simple blog tutorial – because there’s already an existing one on the docs. I think that most people – including me – love to learn new techniques and patterns – and have some hands on along the way. I can think of introducing the doctrine implementation along with discussing Domain Driven Design. However, pure hands-on tutorials like Fluid would be great (Fluid can be used as standalone templating engine). There’s as well lot’s of cool stuff going on in the backport – Extbase – of FLOW3 for the actual TYPO3 version. This maybe of interest, as doing CMS extensions is something many people (like me) are confronted in there regular business.

    • http://castironcoding.com Zach Davis

      Re #2: Yes, FLOW3 still uses Doctrine as the default ORM (although the persistence layer is abstracted enough where you could, without too much trouble, use a different ORM).

  • http://php-training-free.blogspot.com sanj2cool

    Its really helpful for me as being a new programmer in PHP and on learning stage. I have learned a lot from tutplus and such post are always a plus. Thanks

  • Michel Maas

    Interesting concept and certainly useful, however I don’t really like sollutions where comments are used to overcome shortcomings of PHP. Maybe we’ll see a better implementation in the future?

  • http://www.technoslab.in/ Manish

    I’m on Windows and the command line too doesn’t work.

    • Chris
      Author

      Can you provide some more details, e.g. what error message you got? I wrote a comment above with some steps you can do, if that happens – check if this works for you and report back.

  • http://www.technoslab.in/ Manish

    I’m on Windows and the command line tool doesn’t work.

  • http://robertlemke.com Robert Lemke

    @kevin:

    1) there shouldn’t be direct references to TYPO3 in FLOW3 code-wise. However, TYPO3 is our mother project and is the community who made this project possible and thus it’s just natural to have TYPO3 related examples. There’ll certainly be a lot more non-TYPO3 related examples soon.

    2) yes, we are still using Doctrine 2 and love it

  • Ehud

    Hi Chris,
    I am really excited about FLOW3 and started to use it by going over the “Blog app tutorial”
    after finishing it i really thought that this framework is the one for me, it’s elegant and clean and the basic ideas behind it seems really thought of by php pros.

    I did have a huge problem when i tried to integrate it with a nosql persistent storage like couchdb or mongodb.
    I just couldn’t find enough documentation about it and the community that lives mainly in the irc channel seemed sleepy and non responsive.
    At the end of it i found the flow3 forge repository and found the FLOW3.CouchDB package which i downloaded and spent hours trying to figure out how to use.
    I managed to create an objects.yaml that overrides the main repositoryManager and repositoryManagerInterface and the correct settings.yaml configuration and successfully saved my models in there.

    I still have several problems using this storage at the moment and no solution in sight.

    I was really frustrated about the lack of community and support for this framework and the lack of documentation for integrating a really “hyped” technology – nosql, which every new framework should achieve to integrate with.

    I think the main factor a newcomer should consider when choosing a framework should be it’s maturity which is measured by it’s community livelihood and activity.

    My verdict although i wish was false is that FLOW3 is not yet mature enough.

    I will continue to keep an eye on it’s advancement though and I hope a day would come when i could change my mind about it.

    • Chris
      Author

      Ehud, you nailed it. Missing documentation is a problem at the moment and yes, it’s hard to get answers once you’re stuck somewhere.

      It’s a matter of fact, that FLOW3 is not as mature as symfony or rails (for ruby), and it’s not as great documented and the the irc of symfony is more crowded.

      As I understood the roadmap, the team is about finishing version 1.1, which will significantly improve compile speed. The next big step (between getting the next Typo3 done) will be documentation.

      However, you’re right that this is a problem right now. For the moment, FLOW3 is a young framework with very good ideas and much potential. But keep in mind, that the Typo3 Community is huge and when the FLOW3-based CMS will be ready, the community will grow rapidly.

  • http://www.spozzle.me Abishek

    How do you compare FLOW3 with codeigniter?

  • http://daGrevis daGrevis

    There is a good reason why no-one implemented it before in PHP…

  • http://prophpvn.com Hudson Nguyen

    I heard about AOP long time ago and was wondering how would it be implemented in PHP and this post is really interesting by showing the way Flow3 does. However, this is not I expect for some reasons:

    First of all, the term ‘cache’ that is used to transform comment into something usable in the code flow is not OK for me at all. Clearly it’s not a cache. Cache is when you have something keep changing during the application lifetime but you don’t want to rebuild it in every request so you compromise the up to date of data with the speed of your app. I think Java or compiled languages do this the right way by adding logic to compile the comment into generated code at build time.

    Secondly, if you look at the code at the beginning and at the end, well i have to say I’d better go with the early code. The namespace of PHP is over used. The article doesn’t mention a case study where you reverse engineering a project and fix the issue of code changing, new logic having to be added. How effectively is it with this AOP approach ? For me, making thing more abstract and independent cost too much unless I spend my 5 or 10 years on one big, enterprise project. I agree with some other comments here that this overkill small PHP projects if they are started this way.

    Lastly, I am not sure how many strong OOP developers can embrace this approach, unless it would be made much simpler. There are many ways to do one thing as there are too many frameworks to use in a PHP project. Most of use and many people at the decision making position would only look at the tip of the iceberg to decide the framework to be used.

  • flyingfox

    FLOW3 will rock!. I have been following along the development for quite a while, and I must say, there has never been such a holistic, up to date, and dedicated approach to developing a framework in PHP before.

    One must not forget that it will serve as the base for the new TYPO3 5.0, a giant player among PHP CMS solutions which will come to stay just like the older versions have proven.

    The project team is excellent, very high quality programmers at work. I expect nothing less than full approval of FLOW3 among pro PHP coders.

    Is AOP easier to implemet in more sophisticated languages like C#? Yes, but PHP is the tool of trade for many web developers, and it is just great that the effort is made to squeeze the last bit out of the limited capabilities of PHP.

    Will I have to leave my beloved RoR or ASP.NET MVC grounds for a future project, FLOW3 will be my choice.

  • Guido Contreras Woda

    Chris:
    This looks very interesting! I’m about to start my first Enterprise project in Spring and I’m glad to see AOP can also be implemented in PHP.
    It seems PHP has made a name for being “simple”. I believe that people confuse doing things on a simple way with doing plain junior 200′ish code. PHP has a lot of programmers that don’t get past the MVC architecture (implemented through a framework they’ll never understand fully) and never think about the flaws in this simplicity. Other languages (like Java), by being “harder on the programmer”, force good habits and practices that result in better, more organized code.

    I believe that even small projects shouldn’t disregard this kind of stuff. You never know if that small project ends up growing, and you can prevent huge costs in redevelopment and migration with just a few good practices.

    Cheers!

  • coldwinds

    I’m wondering how the flow3 aop intercept the class inclusion then generate the proxy cache, where it take place in php code, through registering an autoloader or php stream filter or something to deal with it? I want to learn about the internals.