Ménage à trois: TYPO3 Flow, PHPUnit, Composer

The introduction of Composer support in TYPO3 Flow has caused some confusion when it comes to installing and using PHPUnit. In the past, PHPUnit was usually installed using PEAR and available as a system-wide command.

Now there are additional options: installation through Composer and as a standalone PHAR archive, each of them posing some issues.

PHPUnit installed via PEAR

Installing PHPUnit via PEAR is described in the PHPUnit manual, and besides the usual issues people seem to be having with PEAR in general, there is not much to say. If you have the phpunit command running, testing TYPO3 Flow applications boils down to

phpunit -c Build/buildessentials/PhpUnit/UnitTests.xml
phpunit -c Build/buildessentials/PhpUnit/FunctionalTests.xml

PHPUnit installed via Composer

Installing PHPUnit via Composer is easy. Just edit the composer.json file at the top level of your project and require phpunit next to the vfsstream dependency:

"require-dev": {
    "typo3/kickstart": "dev-master",
    "typo3/buildessentials": "dev-master",
    "phpunit/phpunit": "3.7.*",
    "mikey179/vfsstream": "1.1.*"

Afterwards, the installation can be done with

composer update --dev phpunit/phpunit

You will end up with a PHPUnit binary at bin/phpunit and can thus run

bin/phpunit -c Build/buildessentials/PhpUnit/UnitTests.xml
bin/phpunit -c Build/buildessentials/PhpUnit/FunctionalTests.xml

Attention (former) PEAR users: if you have PHPUnit installed globally and PEAR libraries are still in your include path, this may lead to very weird results. Just imagine PHPUnit from the composer install being used, but some parts of it are loaded from the PEAR path, possibly with mismatching versions…

So, if you use Composer to install PHPUnit, make sure no other version(s) of PHPUnit clutter your system.

PHPUnit standalone archive

Using the PHPUnit standalone archive is currently not possible. The problem is caused by the Flow bootstrap code and manifests in this error:

PHP Warning:  require_once(PHPUnit/Autoload.php): failed to open stream: No such file or directory in …/TYPO3/Flow/Core/Bootstrap.php on line 92

Since the class loading in the archive seems to be handled differently (it might well be that adding the archive to the include_path would help), our assumption that this file exists breaks (some) tests.


If you have PHPUnit installed via PEAR, there is currently no reason to change that. We might at some point make PHPUnit a (dev) requirement for TYPO3 Flow, but until then it's your choice.

If you do not have PHPUnit installed right now, using Composer is the easiest choice.


Upgrading from FLOW3 to TYPO3 Flow

If you have been using FLOW3 so far, chances are high you will want to follow up on TYPO3 Flow for all the new goodies it provides. But how hard is an upgrade of existing code? Let me show you…

What has changed

The most obvious change is the renaming of FLOW3 to TYPO3 Flow. Since the product name is reflected in the PHP namespace of classes, all code using FLOW3 needs to be adjusted and FLOW3 must be replaced by TYPO3\Flow.

The next big thing in TYPO3 Flow is the integration of composer for dependency management. This requires all code to follow the PSR-0 rules for class autoloading - something FLOW3 did not do fully. So the vendor and package name parts of the PHP namespaces need to be reflected in the Classes folder structure of a package.

Finally we added  little change to your database schema - flow3_persistence_identifier has become persistence_object_identifier during the renaming.

Upgrading existing code

Here comes the easier part. As with earlier changes to FLOW3 that required code changes on the user side we provide a code migration tool. Given you have a TYPO3 Flow system with your (outdated) package in place you should run the following before attempting to fix anything by hand:
./flow core:migrate --package-key Acme.Demo
The package key is optional, if left out it will work on all packages it finds - for the first run you might want to limit things a little to keep the overview, though.

Inside core:migrate

The tool roughly works like this:

  • Collect all code migrations from packages
  • Collect all files from all packages (except Framework and Libraries)
  • For each migration and package
  • Check for clean git working copy (otherwise skip it)
  • Check if migration is needed (looks for Migration footers in commit messages)
  • Apply migration and commit the changes

Afterwards you probably get a list of warnings and notes from the migrations, check those to see if anything needs to be done manually.

Check the created commits and feel free to amend as needed, should things be missing or wrong. The only thing you must keep in place from the generated commit messages is the Migration: … footer. It is used to detect if a migration has been applied already, so if you drop it, things might get out of hands in the future.

Upgrading the database schema

Upgrading the schema is the harder part this time. You will probably start by running
./flow doctrine:migrationgenerate
as usual to create a migration based on the current state of database and code. This time things are a bit special, since the primary key of a lot of tables will change due to the renaming of the FLOW3_Persistence_Identifier property.

The hard part are the foreign key constraints that need to be updated with this. The migration generated by Doctrine will contain commands to rename that column for your package's models (tables) but will not handle any foreign keys from other packages that might point to them. We have a solution though.

When adjusting your generated migration (as usual you need to check it anyway), just follow the following recipe:

  • Order SQL statements to (the file might look similar to this afterwards)
    • dropping foreign key constraints
    • renaming fields
    • adding foreign key constraints
  • Remove any SQL statements dealing with foreign key constraints
  • Before the remaining statements adjusting your package's primary key columns add

    // collect foreign keys pointing to "our" tables
    $tableNames = array(
    'acme_demo_foo', // change this!
    'acme_demo_bar', // change this!
    $foreignKeyHandlingSql = Service::getForeignKeyHandlingSql($schema, $this->platform, $tableNames, 'flow3_persistence_identifier', 'persistence_object_identifier');

    // drop FK constraints
    foreach ($foreignKeyHandlingSql['drop'] as $sql) {
  • After the remaining statements add

    // add back FK constraints
    foreach ($foreignKeyHandlingSql['add'] as $sql) {

In the code to add, you have to adjust the list of affected tables - it needs to list all tables in your package that have a flow3_persistence_identifier column. The file should now look roughly similar to this one.

Afterwards make sure to try your migration in up and down direction as usual before using it in production!

Famous last words

In a nutshell, running
./flow core:migrate 
./flow doctrine:migrationgenerate
padded with some manual checking and adjustments needs to be done. That should result in a working package. *cough*

If it does not and you have no idea what to do next, please come over to #typo3-flow on freenode IRC or ask in the mailing list (news group) as you prefer.


Search Plus Your World - so what?

Why all the fuss?

As a user without that SPYW feature rolled out to so far, I only learned about it through the focus on the user initiative. And, frankly, i do not get the fuss. Google puts some Google Plus results in a sidebar, right. But above that, it exactly says what's in that sidebar.

If that box said "Social Media Results", I'd be all enraged (as far as such things are important). But it doesn't.

If Google would filter twitter and facebook from search results, I'd be all enraged (as far as such things are important). But they don't.

I am smart enough to ignore that box, if it doesn't seem work for me. If enough people do, it'll be changed.

Why is number of followers more relevant?

In the video showing how the focus on the user code works, the narrator states over and over again: This twitter profile has a gazillion more followers, it must clearly be more relevant. Yes, sure. That's because twitter is as young as Google Plus and obviously both have had the same amount of time to accumulate users.

I'm glad the actual ranking code focus on the user uses is the search result ranking determined by Google - and I really hope that is based on more than just the number followers.

Mixing apples and peaches

And today I stumbled accross Larry Page to Googlers: If You Don’t Get SPYW, Work Somewhere Else and also read some of the linked posts from there. Reading the comments I wonder why people start bitching about not getting Android updates from their provider below a post about SPYW. If that is the level people think at, it's no wonder they overlook that sidebar's title.