Hofstadter’s Law

Heh. Never heard of that Hofstadter guy before. However I immediately liked Hofstadter’s law:

It always takes longer than you expect, even when you take into account Hofstadter’s Law.

So much wisdom in only a few words! It should be printed on a T-Shirt, or a Poster, or be the first chapter of every “IT Project Management in 10 easy lessons” handbook.

Fixing Locale issues on Debian

Business as usual. New feature developed, tested, packed and ready to go. Let me just deploy it to production, smoke test aaaand …. damn! What happened to the currency symbols!?

In my particular case, PHP’s setlocale() returned false – so obviously those darned locales stroke again. SearchEngineOfYourChoice(TM) to the rescue!

Luckily even I was ably to fix this problem quickly without needing to contact the Admins (who wouldn’t have been in the office anyway):

$ locale -a
C
C.UTF-8
en_US.utf8
POSIX

Aha! It was missing almost all locales. However adding them is quite easy:

$ sudo dpkg-reconfigure locales

Generating locales (this might take a while)...
de_DE.ISO-8859-1... done
de_DE.UTF-8... done
de_DE.ISO-8859-15@euro... done
en_US.UTF-8... done
fr_FR.ISO-8859-1... done
fr_FR.UTF-8... done
Generation complete.

The dialog that appears after running this command shouldn’t be a problem at all, so I don’t mention it further here. Just select the locales you need there and go for it.

Afterwards check the results by again doing

$ locale -a

C
C.UTF-8
de_DE
de_DE@euro
de_DE.iso88591
de_DE.iso885915@euro
de_DE.utf8
deutsch
en_US.utf8
français
french
fr_FR
fr_FR.iso88591
fr_FR.utf8
german
POSIX

That’s already it. Don’t forget to restart your webserver!

Mocking magic methods with PHPUnit

If you want to test a method of an object which is supplied using the magic method __call(), you can’t simply mock the desired method. You have to go the longer way via __call(). So e.g. if your magic method you want to mock is called “myMagicFunction”, you could be tempted to write

$mock
    ->expects($this->once())
    ->method('myMagicMethod')
    ->with('123')
    ->willReturn('myResult');

since, after all, it is a mock, right? So why wasting time? Obviously PHPUnit (Version 4.5.0 at the time of writing) is doing some sort of internal checks, preventing our laziness and forcing us to mock the __call() method instead. I can only guess the reason here, any comments with more insight on this topic are highly appreciated!

Of course, mocking the __call() method instead is not much more work

$mock
    ->expects($this->once())
    ->method('__call')
   // Be sure to pass the method argument(s)
   // as array, even if you only have one 
   // argument!
   ->with(
      $this->equalTo('myMagicFunction'),
      $this->equalTo(['123'])
   )
   ->willReturn('myResult');

However PHPUnit will not throw any Exceptions if you use the first approach, instead it will only return NULL instead the expected ‘myResult’. This can be a bit frustrating 🙂

New Typo3 extension unleashed: cwdblog

Working with Extbase a lot, I always found it very cumbersome to see the actual SQL queries which were produced by the Persistance layer. One solution would be to turn on MySQLs general log, but this is not very convenient.

So I decided to change that. The result can be found here: cwdblog on GitHub

cwdblog will log all DB queries which are run against the table(s) you can configure via the Extension Manager. It will be logged using the system log and the devlog extension (if installed). It will also write the queries into a global array (GLOBALS[‘___cwdblog’]) so that it is even easier to access to debug sessions.

In order to tell cwdblog which tables to actually log, please go to the extension manager, edit the extension configuration and change the tableName regular expression as you need.

Slashes will be added, so e.g. mycool will result in /mycool/, which will let cwdblog log all queries for tables which include the string ‘mycool’. This could be e.g. tx_mycoolextension_domain_model_blog or tx_myotherextension_domain_model_mycooltable.

Please note that this extension should not be used on production servers yet, since it is not very well tested).

Of Typo3, Site Crawlers and Compression

A Typo3-Installation I currently maintain uses the sitecrawler extension to heat up the page cache every morning before the users are visiting our site. We encountered the problem that all pages that were cached didn’t use gzipped CSS & JavaScript-Files, only the non gzipped versions.

Typo3 first generates both the gzipped and non-gzipped versions of the CSS & JS files, and then checks the HTTP_ACCEPT_ENCODING setting whether gzip is supported and decides which of both versions is referenced in the HTML.

Since the Crawler is not sending the HTTP_ACCEPT_ENCODING flag when crawling the pages, Typo3 thus renders the Page HTML referencing the non-gzipped files. I tried to add the “Accept Encoding” to the crawlers requestUrl()-Function, but of course Typo3 now returned the HTML as gzip, which totally broke the crawlers logic …

Since as said Typo3 generates both versions of the files, eventually we came up with these two redirects:

RewriteCond %{HTTP:Accept-Encoding} .*gzip.*
RewriteRule ^typo3temp/compressor/(.*)\.js$ typo3temp/compressor/$1.js.gzip?%{QUERY_STRING} [L]
RewriteCond %{HTTP:Accept-Encoding} .*gzip.*
RewriteRule ^typo3temp/compressor/(.*)\.css$ typo3temp/compressor/$1.css.gzip?%{QUERY_STRING} [L]

In case the page is cached without referencing to the gzipped versions (which is the default state every morning), we just redirect all request to the gzipped versions.

Debugging Flow3 – ain’t got time for that!?

It is known that XDebug has a negative impact on performance, but what happens when you try to debug a Flow3 application can be something between absolutely surprising and totally annoying. But one after another.

XDebug is my every day tool. I use it not only for debugging, but for regular development as well. I simply enjoy the benefit to always know which variables are available in the current scope (Typo3 globals, anyone?), I don’t need to recall nested array structures, I can evaluate my code on the fly and so on. So naturally, on my dev XDebug is always enabled and listening, both for PHP SAPI or Webserver.

Working on my first Flow3 project, I suddenly found myself waiting over 30 minutes for the Cache to rebuild after flushing it manually. Running the application on a different machine worked ok, so it was obvious that the issue was somewhere in my setup. Wtf?

So I did what a normal XDebug user would do – let’s profile that damn thing! I realized the core problem as I found dozends of sometimes quite huge Cachegrind files in my output directory. What the heck, there must be really some serious action going on (and it does – see box below)! So I disabled XDebug for the moment, and voilà – the Cache was rebuild within seconds.

If you have not worked with Flow3 before you have to know that Flow3 actually requires cached class files because of the use of Aspect-oriented programming (AOP). In short, Flow3 scans the code files of the packages whether certain rules (the so called Aspects, defined via Annotations) apply, and changes the code in the classes according to the Aspect. Doing this for every request would be obviously insane, so the results are cached. We suddenly find our good old PHP scripts in some way being compiled.

There is a nice article about Flow3 and AOP to be found here which describes it more in detail.

Flow3 luckily has some advanced file monitoring which, when you work in Development context, makes it unnecessary to clear the whole cache manually every time you change a class, and rebuilding the cache for one class only will work within a reasonable amount of time even with XDebug turned on. Nevertheless sometimes you will need to flush the whole cache, and then you’re doomed. En-/Disabling XDebug in the php.ini manually would be too cumbersome (for me). So there has to be a more convenient solution.

How to debug Flow3 applications and stay sane

Here’s with what I ended up: I disabled XDebug for PHP via CLI by default, and enable it only when I need it using the “php -d” switch:

php -dxdebug.remote_autostart=On -dxdebug.remote_enable=On ./flow

Not a very easy one to remember, but we’re getting close. Why not put this into a separate shell script? Yes, why not. I called it “flowdebug”, and it is located in the project root (where the original flow command is located).

#!/bin/sh
export PHP_IDE_CONFIG="serverName=my.server"
export XDEBUG_CONFIG="idekey=PHPSTORM"
php -dxdebug.remote_autostart=On -dxdebug.remote_enable=On ./flow "$@"

As you can see I also put the environment variables needed to start the debugging session in that script.

So from now on, when I want to debug my Flow3 application, I simply use

./flowdebug mypackage:mycommand

Traits and Extbase

With Extbase, accessing the extensions settings outside Controllers (e.g. in a Repository) requires some manual work which is always the same. I don’t know why Extbase doesn’t support us with helper functions, but anyway, let’s put this needed code where we can reuse it easily.

Being limited to PHP 5.3 until last month, my usual approach was to inherit the Repository from an Abstract class which contained a set of often used functions. This still works fine, but if you want these functions to be used in let’s say a Typo3 hook class, or a Scheduler task (where the Extbase support is even worse! Geez!), you probably end up writing a couple of Abstract classes which are more or less the same. Of course you can inherit the Abstract class from another abstract class … which again doesn’t work with Scheduler tasks, because they need to inherit from a base class anyways… nah…

Since we now use PHP 5.4 on our production servers (and yes, I am aware that 2014 is almost over), I felt urged to find out whether Traits can be used with Extbase. Surprisingly (working with Extbase and Typo3 is easier with a good amount of sarcasm) it was as easy as it should be! I tested it on Extbase 6.2, and the Autoloader loads the Trait without any hassle.

Here’s some example. First, the trait itself:

<?php

namespace Vendor\Myextension\Library;

trait Settings
{
    /**
     * The extensions name
     * @var string
     */
    protected $extensionName;

    /**
     * Typo3 Settings array
     * @var array
     */
    protected $settings;

    /**
     * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
     */
    protected $configurationManager;

    /**
     * @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
     * @inject
     */
    public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager) {
        $this->configurationManager = $configurationManager;
    }

    /**
     * Getter for $extensionName
     * @return string
     */
    public function getExtensionName() {
        if ($this->extensionName === NULL) {
            $className = get_class($this);
            if (strpos($className, '\\') !== FALSE) {
                $classNameParts = explode('\\', $className, 4);
                // Skip vendor and product name for core classes
                if (strpos($className, 'TYPO3\\CMS\\') === 0) {
                    $this->extensionName = $classNameParts[2];
                } else {
                    $this->extensionName = $classNameParts[1];
                }
            } else {
                list(, $this->extensionName) = explode('_', $className);
            }
        }

        return $this->extensionName;
    }

    /**
     * Setter for $extensionName
     * @param string $extensionName
     * @return Settings
     */
    public function setExtensionName($extensionName) {
        $this->extensionName = $extensionName;
        return $this;
    }

    /**
     * Setter for $settings
     * @param array $settings
     * @return $this
     */
    public function setSettings($settings) {
        $this->settings = $settings;

        return $this;
    }

    /**
     * Getter for $settings
     * The settings are loaded from the configurationManager on demand only.
     * If this is called outside Extbase (i.e. from a system hook, or a scheduler task) you must use
     * \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT
     * and fetch the extensions settings via the array structure, e.g.
     * $this->settings['plugin.']['yourextension.']['persistence.']['storagePid']
     * @param string $settingsType
     * @return array
     */
    public function getSettings($settingsType = \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS) {
        if ($this->settings === NULL) {
            $this->settings = $this->configurationManager->getConfiguration(
                $settingsType, $this->getExtensionName()
            );
        }

        return $this->settings;
    }
}

No rocket science, but stuff you need all over again. I decided to use “Library” as namespace, but this doesn’t really matter.

So far, so easy. To include a trait, you only need to add the “use”-statement inside your class, e.g. in a repository:

<?php

namespace Vendor\Myextension\Domain\Repository;

class SomeSeriousStuff
{
    // Note the "use" statement within the class. This inserts our Trait class.
    use \Vendor\Myextension\Library\Settings;

    public function mySeriousFunction() {
        $settings = $this->getSettings();
        // ... do some serious things here with the settings
    }
}

This works really smooth, I think I will get used to Traits very soon.

Fun fact: shortly after finishing my Extension where I used Traits for the first time, I was asked for a PHP 5.3 compatible version. Fuuuuuu……

Remote CLI debugging with XDebug

There are quite some tutorials out there on how to use XDebug to debug PHP CLI code, which where more confusing than helpful (to me). I found out that, once you have a running XDebug configuration, it is very easy to debug on the console, particularly with phpStorm.

Simply run the following line once

export PHP_IDE_CONFIG=serverName=www.domain.com ; export XDEBUG_CONFIG=idekey=PHPSTORM

(after customizing it to your needs, of course), set your breakpoints and run the script. That’s already it. You can also put this into your .bashrc file.

T3CON14

Currently I’m attending the 10th International Typo3 Conference (or in cool: T3CON14) in Berlin, and although it is not over yet I really liked it so far. Not only because of the great location in one of the hippest parts of Berlin, or the tasty food, or that I was able to carry home a 3-years supply of stylish pens, no … the atmosphere is fantastic and it is very nice to see the faces behind the names. Also many sessions where very inspirational. My favorite so far was the brilliant speech of Clemens Prerovsky (Aloha-Editor).

Also, and I’m definitely no fanboy, but to attend a speech of the Typo3-founder Kaspar Skårhøj was really something I would not have expected after all these years 😉