Local composer package development

A new feature on composer which I really appreciate is the “Path” repository type.

Imagine you are working on your super-cool-project, and one task requires new functionality where there is no composer package existing yet – yeah, this probably is a bit hard to imagine. Now you want to create your own super-awesome-package, because we all like it nice and separated and such.

So far, I would have developed the super-awesome-package directly inside the vendor folder of my super-cool-project – which somehow did not feel right. Obviously others felt the same, so now we can use the “path” resource type for packages which you develop right at the moment!

  "require": {
    "my-namespace/shoppingcart": "*@dev"
  "repositories": [
      "type": "path",
      "url": "../shoppingcart"

Instead of using VCS as package source, you simply specify the directory (relative or absolute path both work) where your super-cool-package is located on your machine. In my case, I just refer to the shoppingcart folder, where the package is currently developed.

Composer will then add a symlink in the vendor folder upon running composer update, so all your changes on that package can immediately be used in your super-cool-project.

Now that’s what I call convenient!


“Look at her! Isn’t she beautiful? Ahhh, that smell.” Carsten’s fingers were running gently across the black case of their new colleague, a Blade Server with dozens of cores and hundreds of Gigabyte of storage, inspecting all those little details here and there. “I think I’ll call her Babette!”

“Well, finally we got it.” Mike completely ignored Carsten’s gibberish. It has “only” been three month since their Virtual Servers have been “accidently” canceled by “the Admins” in “the HQ”, leaving half of the Software Development department without a reasonable development environment all of a sudden. Good for “the Admins” that HQ was about 800km from their office. Too far away for a spontaneous visit or, let’s say, a Team Building Exercise.

After that incident it was decided to place a server right in the office, so that the Development Team could set up Virtual Hosts as needed and without going the long route via “the Admins”. Everybody was quite excited, yes, even – happy! A way of happiness only developers can understand.

“So, when will the server be configured?” Stephen asked. A good question.

“The Admins told us this will be done next week.” Mike replied.

Just one month later, and after a couple of friendly reminders, they received an email from “the Admins”. The server is now ready to be tested, please let us know if you need anything, et cetera, blabla.

The Devs responded quickly: “Guys, we can’t even access the server with the credentials you gave us. Please tell us what we are doing wrong!”. Although they were no “Admins”, the Devs were a bit skilled with that stuff from their everyday work, but still there was a chance that the error was on their side.

Needless to say that the admins reply came promptly after another week, and yes, after some not-so-friendly-anymore reminders. “Oh well, the server has crashed somehow, but we fixed that now”.
“Buckle up guys, we’re almost there. I can access the server now!” Carsten shouted through the office.

Surely some useful stuff was missing, but at least the basic setup was ok. So everyone inspected it, writing down what would be needed for a standard development environment, which would then act as image for the Virtual Hosts later.

“All right, the email is out. It can now only be a matter of days until we can start working on it.” said Mike, still trying to be optimistic, but with a noticeable amount of skepticism. Too many lessons they learned the hard way.

Days passed.

“What do they mean, we are not allowed to setup the Virtual Hosts by ourselves?? I thought this is our development server, it is not even reachable from outside of the companies VLAN, why should we ask THEM all the time?!”. Dang. Situation got critical.

More days passed. Then they got another email…

“So it seems our new colleague hasn’t made it through the probation phase”. Mike sighed as he pulled the power. The only noise in the silence was the sound of the fans getting slower and slower.

The Dev Team has been informed that currently there are no spare resources to take care of the development server, and they shouldn’t expect it to be available within the next 6 months.

The fans finally stopped spinning.

Good bye, Babette.

Updating Typo3 CMS 6.2 to 7.2

Updating our companies major portals from Typo3 CMS 4.7 LTS to 6.2 LTS was a good piece of work, so I was not really keen on updating any websites again. A good excuse for us was the fact that RealURL was not yet available for Typo3 CMS 7, but now it is – no more excuses. We need to do it anyway.

Before you even start, you should check the requirements of Typo3 CMS 7. It requires at least PHP 5.5 and MySQL 5.5, which might not be available on your server. So check the Typo3 CMS 7 System requirements before you continue.

I started with a relatively small project, which was ideal to get some experience. Only a few dozens of pages, a couple of TypoScript files, and most important, no legacy extensions but only good maintained Extbase 6.2 extension. I was pleasently surprised that the whole migration with fixing all issues (see below) only took roughly one hour, so my thanks to the Typo3 CMS team for that great job!

If you have one or more pre Extbase 6.2 extensions which don’t yet use namespaces (i.e. classes are named like Tx_MyExtension_Domain_Model_Whatever instead of just Whatever), there is an extension called “compatibility6” which comes bundled with Version 7.2. You can also use it if you already screwed your Typo3 installation and you can’t login into the backend anymore: you can install it manually by editing the typo3conf/PackageStates.php, search for compatibility6 and change the state from inactive to active. Please note that the usage of this extension has a negative impact on performance, although I can’t quantify the impact. It might just be ok for smaller websites.

The update process is explained here: http://wiki.typo3.org/TYPO3_CMS_7.2.0. In our case, the basic steps were:

  • download the Typo3 sources
  • uninstall RealURL
  • delete typo3temp/Cache folder
  • switch typo3_src to new version
  • run all checks in the Install tool
  • login into the backend, update RealURL to the recent version and
  • install it again

Update problems

Of course the update did not go without any problems, so let’s discuss them in this section.

CSS missing!

After finishing the update work in the Install tool I went to the backend login page and was somewhat suprised – I didn’t expect that fresh oldschool style:


Ok wait, there’s something wrong. Obviously the t3skin.css was missing.

It turned out that somehow the PackageStates.php was mixed up, and although the t3skin system extension was marked as active, it obviously wasn’t. Doing some internet research revealed that this problem occurred for others as well. I ended up in simply deleting the PackageStates.php (after doing a backup) and reload the login page. This way, the PackageStates.php was regenerated from scratch. Once it was created again, I needed to re-activate almost all system extensions manually. All in all this was just a matter of minutes, so no big deal.

No leading backslashes please!

After fixing the CSS issues, I loaded the start page which includes one of our custom extensions, and ended up with another exception:

$className “\My\Nifty\Class” must not start with a backslash.

Some of our makeInstance() calls had a backslash before the FQCN, which whith Typo3 CMS 7 is not allowed anymore. Since the backslash is not needed, we simply removed it, e.g.

// works ok with Typo3 CMS 6.2, but not 7.2:
$myInstance = GeneralUtility::makeInstance('\\My\\Nifty\\Class');

// works ok with Typo3 CM 6.2 AND 7.2:
$myInstance = GeneralUtility::makeInstance('My\\Nifty\\Class');

This also applies for calls to the ObjectManagers get-function!

Stating the class name as a string leads to the ugly double backslashes, which nobody likes. With PHP 5.5+, we now can use the ::class constant:

$myInstance = GeneralUtility::makeInstance(My\Nifty\Class:class);

which I really prefer because it is more readable and you can now use your IDEs code completion.

When the views are gone

Next reload, the page loads … yay! No exceptions. Good. So on to the next issue (a real classic):

Sorry, the requested view was not found. 

The technical reason is: No template was found. View could not be resolved for action "index" in class "My\Nifty\Controller\IndexController".

This time the problem was in the Configuration\Typoscript\setup.txt of one extension, where we still used the old name for the view folders:

# this works until Typo3 6.2
templateRootPath = {$plugin.tx_mynifty.view.templateRootPath}
partialRootPath = {$plugin.tx_mynifty.view.partialRootPath}
layoutRootPath = {$plugin.tx_mynifty.view.layoutRootPath}

# with Typo3 7.x, use
templateRootPaths.10 = {$plugin.tx_mynifty.view.templateRootPath}
partialRootPaths.10 = {$plugin.tx_mynifty.view.partialRootPath}
layoutRootPaths.10 = {$plugin.tx_mynifty.view.layoutRootPath}

Extbase supports fallback paths for templates, layouts and partials, which is quite cool – when you know it. Fluid uses the highest index (in our case only one, the 10) as directory for looking up the templates, and tries out the next lower one if it fails. Oh, and also it is called RootPaths instead of RootPath for a while already.

Say “hi” to number seven

Updating to Typo3 CMS 7.2 caused far less trouble than the previous “LTS-Jump”. I really like the fresh look of the backend, and the fact that the Typo3 core has been cleaned up even further.

Surely the website I migrated was only a small one with no legacy extensions, but I think I covered some issues which might be helpful to others!

Typo3 CMS hooks and namespaced classes

During work on my extension cwenvbanner to make it compatible with Typo3 CMS 7.2, I came across a good old friend, the hooks array $GLOBALS[‘TYPO3_CONF_VARS’][‘SC_OPTIONS’]. Since I sometimes struggle with the way how to declare the class and function to be called, I decided to write it down here – once and for all :-)

In short, this is how a hook can be defined


The ampersand before the class name is optional. If you add it, the class will be instantiated using the Singleton pattern.

Let’s have some examples. Firstly, let’s have a look at the old version I had in my extension:

	= 'EXT:cwenvbanner/class.tx_cwenvbanner.php:&tx_cwenvbanner->contentPostProc_output';

For the new Typo3 CMS 7 compatible version of cwenvbanner I wanted to use a namespaced classes for the heck of it. I came up with the inspiring name “Main” which now resides in the Classes directory of the extension, so need I changed the path and filename accordingly. I also need to provide the fully qualified class name, i.e. Cw\Cwenvbanner\Main.

This is how it looks like now:

	= 'EXT:cwenvbanner/Classes/Main.php:&Cw\\Cwenvbanner\\Main->contentPostProc_output';

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

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


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


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

   // Be sure to pass the method argument(s)
   // as array, even if you only have one 
   // argument!

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.