Latest Articles

Private communication between PHP classes

Sunday, December 13, 2015 0 comments

Introduction
I am currently working on BaconPdf, and while doing so, I ran into an interesting problem. Consider that there are two classes, namely Document and Page. The user may extend both classes to add specific functionality, but they may never alter the underlying data structure, as that would mean that we'd always have to validate it completely whenever a Page is added to the Document. Thus we must prevent the user from ever getting access to that data structure.

Implementation
Since we don't have friend classes or private classes in PHP, this is kinda tricky. You cannot let the Document ask the Page for the data structure, as the user could do the same then. You also cannot let the Page tell the Document directly about it, as the user could tell the Document any invalid data structure then as well. Thus we need some kind of verification process, which doesn't involve validating the entire data structure. Thus I came up with the following architecture, which is somewhat related to the visitor design pattern. Consider the following Document class:
class Document
{
    private $pagesData = [];

    final public function addPage(Page $page)
    {
        $page->acceptDocument($this);
    }

    final public function addPageData(Page $page, $pageData)
    {
        if (!$page->verifyPageData($pageData)) {
            throw new DomainException('Supplied data are not coming from a Page');
        }

        $this->pagesData[] = $pageData;
    }
}
This is pretty simple and explained just as quickly. There is a public function specifically designed for users, where they can simply call addPage() with their Page object and that's all they have to care about. Now there's an additional public method called addPageData() which will accept page data, but only together with a Page object. The Document will ask the given Page to verify the data it received and throw a DomainException if the verification fails.

Since the $pagesData property is private, even an extending class will not be able to read it or write to it. The addPageData() method has to be final though, as the user could otherwise intercept the $pageData in an extending class. The addPage() method has to be final as well, the reason for that is explained later. Now lets take a look at the Page class:
class Page
{
    private $pageData;

    public function __construct()
    {
        $this->pageData = new stdClass();
    }

    final public function acceptDocument(Document $document)
    {
        $document->addPageData($this, $this->pageData);
    }

    final public function verifyPageData(stdClass $pageData)
    {
        return $pageData === $this->pageData;
    }
}
Here we have to methods again, of which none are actually meant for the user to be called. But even when they do call them, they can do no harm to the underlying data or even access it. Now when the user calls addPage() on the Document, it will pass itself to acecptDocument() on the Page object. This page object will tell the Document to add its private $pageData, together with itself as an instance for verifying the data. The Document will then call the verifyPageData() method on the Page to make sure that the page data actually originate from that Page object.

Since the page data are an object, all we really have to do to verify them is to check that they reference the same object. The verifyPageData() method has to be final of course, as otherwise the user could extend the class and override the method to always return true. The acceptDocument() method does need to be final, as a user could override it and make it do nothing, which would break the entire workflow.

So, to come back to the earlier question, why the addPage() method on the Document has to be final. The user could not only add pages to the Document via the addPage() method, but also by calling acceptDocument() on the Page object. Thus, if a user would override the addPage() method to add additional functionality, it would be circumvented by adding the Page via the acceptDocument() method. That's why there must not be any additional functionality in the addPage() method, it actually only exists for convenience there and to make the usage a bit more logical.

Conclusion
The entire approach is of course a lot of logic, and while it exposes three public functions which are technically not meant for the user, they cannot do any harm to the underlying structure by getting their hands on it. As this is PHP, they can still use reflection or abuse bound closures, but I'd consider that cheating. The important part is, that you cannot break the architecture via the public interface. It stil has the downside though that you do have a public interface, to which a change would be a backward incompatibility break, which must not be done in minor versions of a software, if you follow semver.

A short status update about Zend Framework 3

Tuesday, April 1, 2014 5 comments

As many of you surely know, the development of the next major version of Zend Framework pretty much came to a hold as the Zend team was and is still occupied with apigility. The maintenance of Zend Framework 2 is also coming along pretty slowly right now, although it's not completely stalled.

For those following the discussions in our development IRC channel more frequently, you probably saw that some of us are actually working on refactoring many components for Zend Framework 3, some a little more (like the completely rewritten Dash Router), and some with just minor BC breaks like the service manager, the event manager and everything around forms.

There was quite a bit of discussions on IRC, the mailing list and on GitHub about how we could speed up the development of ZF3, so we could get a release out in a proper time. We not only came to a final decision, but also developed a plan to reduce the number of future BC breaks permanently. So what does this look like? Well, this is actully a plan with multiple steps.

First we are going to define all component layers via interfaces within Zend Framework itself. We won't ship any concrete implementations with it, but only make our MVC layer consume and work with those interfaces. The next step is developing reference implementations as separate projects, although still maintained by Zend. This way we are still able to ship a complete application framework, while making it easier to completely swap out specific components. The reference implementations will hook into the system as normal modules, so that they can also supply application configuration on their own.

So what is the timeframe for all this you may ask? As I wrote earlier, we don't want to fall behind too much, so we planned to finalize all the interfaces until the end of this month. We then will write bridges to older ZF2 components where required, so that they can already be used in the new architecture. In cases where we already have new implementations in place, like the router, service mager and such, we will alter those to follow the defined interfaces.

Another plus side on this new approach is that we can directly target PHP 5.5 on components here it makes sense to use new features, while other components can still be PHP 5.4. For those components which make use of PHP 5.5 features, we will parallely maintain PHP 5.4 compliant versions, which will automatically be selected by composer if the user is running an older PHP version.

If everything goes as planned, we should have a beta release of Zend Framework 3 out by May 16th, and a release candidate around June 1st. Proposals for all interfaces will be posted throughout this month, so make sure to watch the mailing list and join the discussion and bring in your ideas!

About {@inheritDoc} and other useless documentation

Monday, October 28, 2013 5 comments

I've seen and followed many different documentation rules in my life. Everytime when I was taught something new for code documentation and it made any sense to me, I tend to addopt these pretty quickly. When looking back, some of the rules certainly made sense, especially when our poor IDEs weren't as good with resolving documentation as they are now. What I want to teach you with this article is, how to reduce redundant documentation and keep it as short as possible, without loosing any documentation from auto completion or API docs.

First, let's talk about the @return annotation. It became pretty popular in PHP to write "@return void" when the method will not return anything. Techncially though, it is actually returning "null". But writing "@return null" isn't actually helping much either. Since you are really not returning anything, it is perfectly fine to ommit the @return annotation completely. Any IDE or API-doc generator will interpret this as the classical "@return void".

So, let us start with a very simple interface to demonstrate all following usecases:
interface ToasterInterface
{
    /**
     * Toast a bread.
     *
     * This method will toast a bread for a given amount of seconds.
     *
     * @param Bread $bread
     * @param int   $time
     */
    public function toast(Bread $bread, $time);
}
When generating API-docs from this with phpDocumentor, it will look like this:
Toast a bread.

This method will toast a bread for a given amount of seconds.

    access: public

void toast (Bread $bread, int $time)

    Bread $bread
    int $time
There's nothing really special about this you haven't seen before. Now there are quite a few ways people take to document the method in an implementation. I won't list all here to keep the article short, so let's just get to the point. If your method doesn't do anything special over the already documented interface, just leave the doc-block out. Every API-doc generator will take everything from the parent, which is in this case the short description, long description and all annotations. Now let's say that you want to change something, e.g. you throw exceptions in your implementation. In that case, you'd only include the @throws annotation in your doc block:
class AwesomeToaster implements ToasterInterface
{
    /**
     * @throws RuntimeException
     */
    public function toast(Bread $bread, $time) {}
}
In case you want to override the short description, you can so so easily:
class AwesomeToaster implements ToasterInterface
{
    /**
     * Toast a white-bread.
     */
    public function toast(Bread $bread, $time) {}
}
Let's come to the {@inheritDoc} inline annotation. First I have to clearify that you cannot override the long description without having a short description first. The {@inheritDoc} annotation is there to include the parent's long description, so you can actually use that one and extending it with your own documentation. In your case, this could look like this:
class AwesomeToaster implements ToasterInterface
{
    /**
     * Toast a white-bread.
     *
     * {@inheritDoc} It only accepts white-bread thought.
     */
    public function toast(Bread $bread, $time) {}
}
There you go. We have the original description and on top of that our implementation-specific one. This would output like this:
Toast a white-bread.

This method will toast a bread for a given amount of seconds.
It only accepts white-bread thought.

    access: public

void toast (Bread $bread, int $time)

    Bread $bread
    int $time
A last thing about overriding @param keywords. This is possible, but will make no sense most of the time, since a parent pretty much describes what the method should be able to take. In some cases you may want to widen the allowed range of values though. If that's the case, you only have to put the @param annotation for that single argument in your doc-block, and not repeat any of the other annotations.

I hope that this helps a few people to reduce the insaneness of way too much redundant and copy-pasted inline documentation and gives you a bit more time to actually produce awesome code.

Update
I changed the Toast to Bread, based on Geeh's comment.

Zend Framework 2 Routing and Reverse Proxies

Friday, October 11, 2013 1 comment

I came about a pretty interesting routing scenario in #zftalk.dev which was not quite easy to solve, so I thought about writing a blog post about that. A user was using an HTTP reverse proxy with the following configuration:
ProxyPass /application/ http://www.example.com/
ProxyPassReverse /application/ http://www.example.com/
As it turned out, reverse proxies will not pass any path information via headers, so this is not detectable at all. What's even worse is, that the matching works as expected, but the assembling will not have the path from the proxy included. This means that assembled URLs cannot be matched. Setting the base path to /myapplication/newpath/ doesn't work either, as matching will fail in that case then. The solution to the problem is a little bit dirty, but it should work in 99% of all cases. What you must basically do is allowing the router to do the matching with the detected base path, and afterwards set it to the proxy's path, so assembled URLs look correct. The problem with this approach is, that this only works with a single reverse proxy. As soon as you have more (for whatever reason), this will not work anymore. This is, as I wrote, because the reverse proxy does not pass any path information to the target server.

So after coming up with this idea, Peter Hough, who asked the question, worked out the code for this and supplied me the code for demonstration. The entire code is compressed into a single re-usable module, so everyone who needs it can just use it:
class Module
{
    /**
     * @param \Zend\Mvc\MvcEvent $e
     */
    public function onBootstrap(MvcEvent $e) {
        $eventManager = $e->getApplication()->getEventManager();

        // Trigger after matched route & before authorization modules.
        $eventManager->attach(
            MvcEvent::EVENT_ROUTE,
            array($this, 'setBaseUrl'),
            -100
        );

        // Trigger before 404s are rendered.
        $eventManager->attach(
            MvcEvent::EVENT_RENDER,
            array($this, 'setBaseUrl'),
            -1000
        );
    }

    /**
     * Triggered after route matching to set the base URL for assembling with ProxyPass.
     * 
     * @param \Zend\Mvc\MvcEvent $e
     */
    public function setBaseUrl(MvcEvent $e) {
        $request = $e->getRequest();
        $baseUrl = $request->getServer('APPLICATION_BASEURL');

        if (!empty($baseUrl) && $request->getServer('HTTP_X_FORWARDED_FOR', false)) {
            $router = $e->getApplication()->getServiceManager()->get('Router');
            $router->setBaseUrl($baseUrl);
            $request->setBaseUrl($baseUrl);
        }
    }
}
To enable the replacement, you have to set an environment variable named APPLICATION_BASEURL. If that one is not set or it is not a proxy request (accessing the application directly), nothing will happen. Setting the base URL is pretty simple.

Apache:
SetEnv APPLICATION_BASEURL "/application/"
nginx:
fastcgi_param APPLICATION_BASEURL /application/;
Again, thanks to Peter Hough providing the code.

QR-Code generation in PHP, now with bacon flavor

Monday, April 1, 2013 6 comments

First of, this is not an April Fool's joke. I actually planed to make one this year, but eventually gave up. Anyway, as some of you who follow me on Twitter may know, I worked on a modern QR-Code library, known as BaconQrCode, the past few weeks. Eventually it is now fully working and the public API can be considered stable.

As a base for my implementation I had choosen the ZXing library library. After writing the first unit tests though I noted that their implementation of the Reed-Solomon codec performed rather bad in PHP, so I exchanged it with the much faster implementation by Phil Karn. As the rest of the library performed quite well and seemed much more logical, I choosed to stay with it instead of a different implementation like qrencode, which formed the base for PHP QR Code.

So far my complete implementation works, at least according to the unit tests and some personal testing. I'd like to encourage you to try it out and give me your feedback. I have implemented three different renderers so far, namely Bitmap (PNG), SVG and EPS. There is still a little bit of work to be done for me, like finishing the code-documentation, adding a few more unit tests and doing a few more PHP-specific optimizations, but all that work won't influence the public API anymore.

So, what are you waiting for? As always, you can find the library in the Bacon repository on GitHub or include it in your application via Packagist. If you are interested in more cool stuff, check out the website of of Bacon.

Oh and before I forget it. I may also add QR-Code decoding in the future. This would really be a feature you won't find in any other QR-Code library for PHP ;)