Friday, July 30. 2010
Stubbles 1.2.0 released
Today marks the day of the release of Stubbles 1.2.0. This release features improvements for the XSL view engine, namely introduction of support for bot link cloaking, and the handling of the session id as a normal request parameter instead as part of the path. Additionally, if a user agent is now recognized as a bot the link creation functionality of the stub:link template will not add the session id to the created URL. This is applicable for user agents only which are not recognized as bots and which do not support cookies. All of this should help applications build on Stubbles to be more SEO compliant and should help improve the search indexing from search engine bots.
As this is a major release all code which was deprecated with 1.1.0 was removed. If you still rely on interceptor and database configurations in XML, now is the time to upgrade both to property file based configurations. With the addition of Romanian translations for error messages delivered by the framework Stubbles can now be used for Romanian applications out of the box. For a complete list of changes please consult the changelog. You can get the release on our downloads page. ![]() Tuesday, June 8. 2010
vfsStream 0.7.0 released
As promised in my talk about vfsStream at the International PHP Conference Spring Edition last week (see slides on slideshare) I released vfsStream 0.7.0 today. This release features two additions: an improvement for support of file permissions resulting from a bug fix, and an API improvement for simpler setups of test cases using vfsStream.
The improved file permissions support now respects file permissions when you access files and/or directories. Until now it was possible to write into a non-writable file or to read from a non-readable file. This is not possible any more, vfsStream enforces file permissions now in every situation. This allows you to create tests to check how your application responds if it does not have correct file permissions on a directory, for example. Please test this change, I'm not sure I got it completely right. With the API improvement it becomes much simpler to write the setup method for test cases using vfsStream. Before 0.7.0 you had to write something like this:
vfsStreamWrapper::register();
vfsStreamWrapper::setRoot(vfsStream::newDirectory('root'));
Starting with 0.7.0 this can be simplified into a single method call:
vfsStream::setup();
Still you can have all the flexibility you need. The vfsStream::setup() has the same arguments as vfsStream::newDirectory(), namely name and permissions for the new directory, defaulting to 'root' and 0777. Additionally, the method returns the newly created root directory so that you can use it to do further adjustments as required. If you like the new additions get the new release. ![]() Wednesday, March 17. 2010
Stubbles 1.1.1 released
Today we released Stubbles 1.1.1. This is a bugfix release, addressing three issues we found with 1.1.0: It turned out that the database bindings delivered within the framework are not sufficient for every use case. Therefore we rewrote net::stubbles::rdbms::ioc::stubDatabaseBindingModule to fit for new requirements, and removed the deprecation status of this class. However, if you still use XML config files for database connections you need to set the correct database initializer class via the new method stubDatabaseBindingModule::setDatabaseInitializerClassName() to net::stubbles::rdbms::stubDatabaseXJConfInitializer.
The other two bug fixed resort around the build files provided with Stubbles releases: PHP_CodeSniffer introduced a bc break with bugfix release 1.2.2. We adjusted the check-style target to be compatible with this version. Additionally we fixed the setup-examples target, which was broken due to the change of how the projectdir attribute is evaluated since Phing 2.4.0, and slipped through in 1.1.0 when we did the change to this Phing version. As always, you can get the release from our downloads page. ![]() Sunday, March 7. 2010
Stubbles 1.1.0 released
This weekend we shipped the fresh Stubbles 1.1.0 release to our downloads page, bringing one or the other great new feature to our users. This includes but is not limited to full support for dependency injection on interceptors, delayed logging, support for providing REST services, and several more improvements which allow simpler usage of Stubbles by supporting dependency injection on even more places throughout the framework.
Such improvements can be seen on the example of how the usage of databases had to be enabled in Stubbles 1.0.0 and how it could be done with 1.1.0: With 1.0.0 you had to configure the database connections in a config file, and you had to add the stubDatabaseBindingModule to the list of binding modules which configure the binder. Now in Stubbles 1.1.0 the last step is not necessary any more, you only require a config file (which, btw, changed from XML to ini format), and after the config file is there you can start in your application classes to get database connection or entity manager instances injected. This works because we added annotations to the framework classes, so that the framework provides a usable default binding without the need to explicit specify these defaults by the user. However, if the default bindings do not satisfy a user's needs he still can configure his own database bindings using his own binding module. Convention over configuration, sort of. Get the release from our downloads page, for a full list of changes see the changelog. ![]() Monday, February 15. 2010
vfsStream 0.6.0 released
Seldom in a life of a developer it comes to the point where a bug can be fixed by a feature addition. This February, it happend to vfsStream. A user reported a bug where overwriting an existing vfsStream file with new but smaller content replaced only portions of the file, leaving the rest in place instead of truncating the old content before writing the fresh content. After some investigation it turned out the best fix for the problem was to implement the long scheduled feature issue 7. Thought, said, done. So today I shipped vfsStream 0.6.0 including complete support for for $mode param when opening files.
While I was at it, I added support for the $options param as well, it now evaluates whether STREAM_REPORT_ERRORS is set and acts accordingly when opening a file. Unfortunately there are bad news as well. Due to another issue I found out that ext/zip does not work with vfsStream, and that there is no way to add support for it in vfsStream. Maybe if someone with slightly more C skills than me (which are equal to zero) might want to look into this problem for a better explanation, as I can only assume that it's due to ext/zip not supporting userland stream wrappers. If you like the new additions get the new release. ![]() Monday, January 25. 2010
vfsStream 0.5.0 released
Today I shipped vfsStream 0.5.0 which brings a new feature thanks to the efforts of Benoit Aubuchon: vfsStream now supports the rename() functionality which allows you to write test cases using vfsStream for methods that rename files. Another patch of him was to change the stat() call to respect the STREAM_URL_STAT_QUIET flag.
One more new feature is the added support for . as current directory alias so that vfs://foo/. resolves to vfs://foo - this allows to use file_exists($dir . '/.') as workaround for the failing is_executable() call on directories, as described in the comments to the is_executable() documentation in the PHP manual. Of course this raises the question if vfsStream will support .. as well - if somebody takes the time to create a patch I will incorporate this. I did not look into this issue further, but I guess it might involve recursion and a more advanced parsing of the vfs URL to make it work properly, as there might be cases like vfs://foo/bar/baz/../../dummy. So grab the release and make use of the new features, if you like to. ![]() Friday, January 8. 2010
Delayed logging in Stubbles 1.1.0 and API breaks
Today I want to present a new feature we will introduce with Stubbles 1.1.0: delayed logging. Stubbles already offers a simple to use but powerful logging API, so what can we achieve with this new feature and how to use it?
But first I want to take a look at how log data is generated and written. If you want to log something you first call $logger->createLogEntry('aTarget) which gives you an instance of LogEntry. Depending on the log entry factory which is actually used to create the instance this LogEntry instance might already be prefilled with some data, e.g. the session id, a timestamp and so on and so forth. After that you fill this instance with the data you actually want to log by using its addData() method, and finally calling log() to get it written to a logfile, a database or whatever appender you use. Now, what happens if you want to log data but when some data utilized by the log entry factory is not available at this point? An example might be the startup phase of your application, where some of the log data depends on calculations done in a later step, but you have to log some data from the current step which in turn is a prerequisite for the later step. Until now this was only possible using ugly workarounds and hacks - and if you are using Stubbles one thing is for sure: you neither like workarounds nor hacks. Stubbles 1.1.0 and delayed logging to the rescue: we extended the log entry class with a new logDelayed() method which will take care the logger knows about this log entry, but does not hand it over to the log appenders yet. Instead, the logger keeps the log entry in memory, and waits until someone calls it's processDelayedLogEntries() method, or (more likely) the logger instance gets destroyed. If this happens it asks the log entry factory to recreate the log entry in question before handing it to the log appenders, and this gives the log entry factory the chance to replace any earlier not available data with the current version before the log entry is finally written. Sounds good? Well, as all great stuff this comes with a price. The log entry factory interface had to be extended, so if you upgrade your application you have to change your log entry factory implementation as well: either provide an own implementation of the new recreate() method or extend the abstract log entry factory class introduced with 1.1.0 which provides a default implemention. Why this API break? We had two options: either provide a new interface or do the API break. Introducing a new interface would have saved us from the API break, but would be more effort to test and implement, harder to document and understand by (future) users and leading to more complications in the future as well. On the other hand, this is a minor release where API breaks are allowed. Keeping backward compatibility only to be friendly is nothing we should aim at as the API break would be have to be done somewhere in the future anyway, by deprecating the old interface. As users tend to delay API upgrades whenever they can it is better to force them to do it as early as possible. ![]() Wednesday, January 6. 2010
Interceptors and dependency injection
Interceptors in Stubbles allow to intercept (yeah...) the request before the actual processor is called (PreInterceptor) and after the processor has done it's work to create the response (PostInterceptor) but before this response is sent back to the user agent. This is quite powerful and allows manipulating the request before any real work is done as well as manipulating the response before it is sent. Usage examples range from setting up the correct variant for the website depending on request parameters or cookies up to turning the response from a default 200 OK into a 304 Not Modified status.
Until now creation of interceptors and their dependencies was quite limited as they were configured via XJConf and not with Stubbles' own IoC framework which means there was no proper way to get an interceptors' dependencies injected. It was only possible by using the stubBinderRegistry as a kind of service locator, which means to actively look for things instead of just ask for them as explicit dependencies via constructor and/or setter method parameters. Fortunately, this is going to change with Stubbles 1.1.0. Stubbles 1.1.0 introduces a new interceptor initializer based on a property file. The property file contains a list of both pre- and postinterceptor class names, and this new interceptor initializer will iterate through this list and create every interceptor instance using Stubbles IoC, allowing you to make full usage of Stubbles IoC features in your interceptor class. No more looking for things which makes your interceptors hard to test, but just explicitly asking for dependencies. What about the old way? Stubbles 1.1.x will still support the old way using xml configuration files and XJConf without Stubbles IoC, but you have to activate it explicitly when upgrading. To do this, put a call to stubWebsiteBindingModule::usingInterceporInitializer( 'net::stubbles::ipo::interceptors::stubInterceptorXJConfInitializer') in your index.php file (please note that this is not a static method call, but a method call on an instance of stubWebsiteBindingModule). However, we encourage to upgrade to the new behaviour, as it is more powerful and much cleaner. The old way becomes deprecated with 1.1.0 and will be removed with 1.2.0 or 2.0.0 (whichever comes first, we don't know yet). ![]() Monday, January 4. 2010
Registry Design Pattern - useful or harmful?
About a year ago I wrote about How to get a Singleton right. While nothing has changed my opinion about the Singleton Design Pattern - contrary, I'm even more convinced that it is bad, bad and bad - I still have homework to do. In the comments to this article I was asked about my opinion on the Registry Design Pattern, and I promised it would be worth an own blog entry. Well, I did not anticipate it would take more than a year to write it, but you know, work, and no time, and yada yada yada... so here it is.
When thinking about a Registry one has to consider two points: overall architecture of the application, and implementation of the Registry itself. It's not that much what you can say about the implementation of a Registry. For PHP, it should just follow one rule to make it testable and to ease testing of classes using the registry: do not make it a Singleton. (You might have guessed that already.) PHP offers the possibility to implement the Registry as a pure static class, where data within the Registry can be stored within a static class variable, and setters as well as getters can also be static methods. There is no value in making it a Singleton, it just more stuff to type where the result is the same: global state. So if you implement it as pure static, the Registry in itself is neither bad or good. Speaking of global state, it should be common sense by now that global state is a bad idea, at least if this global does not mean the root of the application itself, which leads us to the overall architecture of the application. How is this related to the Registry Design Pattern? The Registry is intended to allow access to configuration data, objects etc. which you don't want to pass around in your application but require them in different parts (or layers) of your applications. If you have such a need from my point of view this means the application is not fully based on the Dependency Injection principle, it does not separate object creation and business logic as much as it should. If the application is completely based on Dependency Injection, there is no need for a Registry any more. Did I just say that there is no need for a Registry any more? Well, two exceptions. First, unfortunately in PHP there might be cases where you can not influence the creation of an object instance, and if you want to pass data or other objects to such an instance, you have to take cumbersome actions to pass those. Creation of user land stream wrapper instances is such an example, as those instances are created by PHP itself and there is no possibility to intercept this. Here a Registry might be of help, but it stays what it is: a workaround for a flaw in PHP. The other exception is the case of using a Dependency Injection framework. You do not need a Registry here - your DI framework already has something like this. It just not called Registry, but it is it's mechanism where you bind data or objects for example in the case of Stubbles or Google Guice, and in Symfony it is called Service Container. (Please note that this is just a quick thought I had in the last days, I might be wrong on this.) To conclude, the Registry itself is neither useful or harmful. The more important question is how strong you apply the Dependency Injection principle in your application. ![]() Wednesday, December 30. 2009
Stubbles 1.0.2 released
Some minutes ago we released Stubbles 1.0.2. This is a bugfix release, containing the following fixes:
You can get the release from our downloads page. ![]() Thursday, November 5. 2009
Stubbles 1.0.1 released
Some minutes ago we released Stubbles 1.0.1. This is a bugfix release, containing the following fixes:
We encourage all users to upgrade due to a security issue with 1.0.0 with route names where the validation of the selected route name was not done properly. You can get the release from our downloads page. ![]() Monday, October 19. 2009
Stubbles 1.0.0 released
This weekend we released Stubbles 1.0.0 as the first non-alpha/non-beta version, recommended for production usage. We decided to drop all view engines except the XML/XSL one as we recommend only using this. The Memphis view engine using patTemplate was just a heavy steel ball on our feets, and our decision to drop it manifested in the way that we were able to improve Dependency Injection support all over the way for the XML/XSL view engine.
Further improvements compared to the last release focused on the command line support. Now you can write your script as implementation of the net::stubbles::console::stubConsoleCommand, using Dependency Injection in all places, and run the command with our new stubcli script which is capable of running all net::stubbles::console::stubConsoleCommand implementations. The filter API saw a major rework making it simpler then ever to apply filters to input values. We will improve the validator API in the same way with the 1.1.0 release. Of course several bug fixes found their way into the release. See changelog for a complete list of changes. You can get the release from our download pages. Unfortunately the documention is not complete. If you have questions just open tickets, we will address documentation issues then. What's next? We have planned bugfix releases for 1.0.0 if necessary. Additionally we already planned the 1.1.0 release. See list of tickets for milestone 1.1.0 on what we have planned. ![]() Monday, September 14. 2009
PHP Unconference Hamburg: a great event
This weekend I attended the PHP Unconference in the lovely city of Hamburg (if you don't count the wheather in). It was a really great event with a superb organisation, from my point of view even better then the some "professional" conferences. So, first a big thank you to the hosts from the PHP Usergroup Hamburg, you did a wonderful job.
Speaking about professional conferences, it's interesting to see that I'm not the only one with a very sceptical look on the International PHP Conference. Other attendees I spoke with had similar thoughts: always the same speakers with nearly the same topics, degrading the purpose of IPC to networking only. It would be more interesting with more fresh blood and a broader range of topics. Of course this would mean more risk for the host, but I believe in the long run the current development will ruin the IPC. Or can I just not imagine that there are so much companies out there paying several hundred Euros just for networking? From the sessions I attended the Performance pessimization talk was really fun and insightful. Starting with an optimal (hardware) architecture Kris Köhntopp, Johann Hartmann, Stefan Priebsch and Lars Jankofsky made changes to this architecture to decrease its performance one after another. Both the audience and the speakers had very much fun in adding one "improvement" after another. For the PHP in the Enterprise session I have rather mixed feelings. While Kris Köhntopp made some really good remarks on maturity of business models and their surrounding processes I think the whole session suffered from an undefined target. "Talking about Enterprise PHP" is not sufficient as session target. It was like a "Let's have a meeting on topic X, but we don't define an agenda for it." Well, from that point it was really enterprisy. Together with Thorsten Rinne I did a presentation on Things to consider for testable code - I feel a bit sorry for Thorsten as his main purpose was to stress the important points of my presentation rather then talking about refactoring bad code to better code, the topic originally voted for. To my surprise the audience seemed to appreciate it. I was very unsure if it would work out in the way I intended it. Probably I should add more examples for the Dependency Injection part as it was requested to see some real-life code, however I'm not sure how much it helped to better understand how it works. In every case I will add one or another point against Dependency Injection, as it seems that there are only benefits but no drawbacks. If you attended the session and would like to give feedback about what can be improved please drop a comment. On sunday Oliver Müller (Btw, thanks to Oliver for taking us on a tourist tour around the Reeperbahn on saturday night. Another interesting session was from Stefan Priebsch about the Model-View-Controler (MVC) design pattern. While I felt uncomfortable with the label "MVC" on Stubbles for quite some time now the talk finally convinced me to drop this label. MVC in the web is fundamentally different from MVC in desktop gui applications, where it was originally invented for, and there seems to be no common understanding of what MVC in web applications should really look like. That's not surprising as there are different solutions possible, and it strongly depends on the type and size of the application you create. Heck, there are even frameworks out there with a "Model" class you should inherit all your models from, which is independend of the application totally pointless and makes me cry. Because the Deployment talk took not place due to a missing speaker I switched to a MySQL High Availability talk. I'm really glad we have database admins in our company which take care of this, but it was interesting to see what the important points are and how such an architecture is build. The last talk was about experiences on pre-commit-hooks. It was suggested to deny commits if they do not fulfill the coding guidelines. For projects with release cycles of at least several days it seems to be really useful, but if you do several releases per day it has a high chance of getting in the way in the moment you want to deploy a bugfix for a bug you deployed earlier the day. (Please do not comment that one should not do this - it boils down to a business decision if you do it or not, wheighing less quality against time to market.) Doing a php lint check and enforcing a certain style of commit messages however seem to be useful in such projects as well. Finally: thanks to everyone who attended. It was a great event with really interesting topics, chats and a fantastic atmosphere. ![]() Monday, August 31. 2009
Extending objects with new methods at runtime
While the title of this blog entry might sound rather scary to straight OO evangelists it might attract other developers - e.g. those that played around with runkit or had a look into the Ruby world where the language supports adding new methods to a class or just to an instance of a class at runtime (see singleton methods, and this blog article; for those not familiar with Ruby: Fixnum is a class already defined by Ruby core.)
With the advent of PHP 5.3 adding new methods to an instance of a class at runtime becomes possible with PHP as well, using anonymous functions and a little bit of __call() magic. First, let's define a new class (boring old foo, bar, baz example for lack of fantasy):
class Foo
{
public function bar()
{
echo "This is Foo::bar()\n";
}
}
As you surely already know you can add public properties to an instance at any time:
$foo = new Foo();
$foo->baz = 'Hello World.'`;
We can use this to store an anonymous function:
$foo = new Foo();
$foo->baz = function () { echo "This is Foo::\$baz()\n"; };
Unfortunately, we are not able to call this as a method:
$foo->baz();
This will blow up with a fatal error saying "Call to undefined method Foo::baz()". Of course we could do
$func = $foo->baz;
$func();
but that is not what we wanted to achieve. Let's add some __call() magic to our Foo class:
class Foo
{
// method bar() omitted
public function __call($method, $args)
{
if (isset($this->$method) === true) {
$func = $this->$method;
$func();
}
}
}
Now we can safely call $foo->baz() with the desired result. However, compared to Ruby you can not redefine existing methods. Therefore,
$foo->bar = function () { echo "This is Foo::\$bar()\n"; };
$foo->bar();
will still call the method Foo::bar() defined earlier and ignore the redefinition due to the nature of how __call() works. What can you do with it? If you use duck typing this might be useful as it reduces the amount of code required for the Adapter design pattern as you just extend the instance you want to use instead of creating a separate adapter class. The result is the same, both a full fledged adapter class and the closure can only access the public properties and methods of the instance to adapt. Problem is, the class to adapt most likely does not have the required __call() implementation. Another use case could be a simplified version of the extension methods mechanism where you want to add a method locally without the need to have it available globally in the application. If you have another good idea of what this can be used for please feel free to comment - just wanted to write my thoughts down. ![]() Monday, July 13. 2009
vfsStream 0.4.0 released
Some minutes ago I released vfsStream 0.4.0, introducing support for file modes, owners and groups. While I planned to implement this at least since a year it took me three tries to get it implemented, and while implementing this I stumbled about some issues which can not be solved by vfsStream. Major problem is that the PHP functions chmod(), chown() and chgrp() do not work with vfsStream URLs due to limitations imposed by PHP (or possibly by underlying C, not sure). The stream wrapper API has no support to enable setting file modes, owner or group of a userland stream implementation. This means the usage of file mode support is limited and can not be applied to create tests for classes using one of the three functions. However, it is still possible to use file modes for testing correct usage of is_readable(), is_writable() and is_executable(). Another usage scenario is to make sure directories created with mkdir() receive the correct file mode, see the file mode example. I'm sure users will come up with other usage scenarios I did not even thought of.
Beside this new feature the release contains a bugfix for vfsStreamDirectory::addChild() to make sure adding another child of the same name as an existing child replaces this existing child, and a fix to return correct results for stat() calls. Grab the release via it's pear channel pear.php-tools.net and try it out. I suspect the file mode support may contain bugs because I did not have the time to use it in other projects, but after all, it is still in alpha stage. ![]() ![]() |
![]() ![]() Calendar
![]() Archives![]() Categories![]() Quicksearch![]() Blogs we read...![]() Syndicate This Blog![]() Blog Administration![]() ![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||




