jurian sluiman

{
Wissel naar

SlmMail: transports to send emails with Zend\Mail

Yesterday, I released the Release Candidate number 1 of SlmMail. SlmMail provides API implementations of the largest email service providers. So if your sendmail or SMTP fails, include SlmMail and offload the risk of sending emails to others. In the last years, emails must be secured with all kind of mechanisms like SPFDKIM and DMARC. It just costs a lot of time and knowledge to maintain your email stack, so that's why email service providers comes to help.

SlmMail has implemented the API of various of the largest players in the field:

  • AlphaMail
  • Amazon SES
  • Elastic Email
  • Mailgun
  • Mandrill
  • Postmark
  • Postage
  • Send Grid

The main benefit of SlmMail is these integrations are possible without any modification to your message objects or service layer! If you handled the transport with dependency injection (as you should do!), then you simply inject another Transport implementation. And guess, it works out of the box.

Strategies for hydrators: a practical use case

After using Zend Framework 2 for more than a year, I just found out about strategies for hydrators today. Yes, today and thanks to Michaël Gallego who introduced me to this concept. But I think many people underestimate what they can do with hydrators and their strategies, so this post explains why strategies for hydrators are awesome.

Take an entity for example which contains a timestamp. You prefer to type hint on the setter for a DateTime object, for obvious reasons:

public function getDate()
{
    return $this->timestamp;
}

public function setDate(DateTime $timestamp)
{
    $this->timestamp = $timestamp;
    return $this;
}

However, you run into troubles if you bind this entity to a form. By default the POST contains string values, so a date value can be send to the server as "2012-11-06". The hydrator wants to set this string to your entity, but it fails due to the missing DateTime object. And then the strategy comes to the rescue!

Factories for translator loaders

Many components in Zend Framework 2 following the adapter or plugin pattern, make use of the Zend\ServiceManager\AbstractPluginManager. The abstract plugin manager is a service locator implementation which allows to define services as invokable or with factories. Many of these plugin managers are loaded automatically (see for example my earlier post about service managers). However, the manager for loaders of Zend\I18n\Translator is a stranger in our midst.

As of an IRC conversation today on #zftalk I, with a few others, found out how the plugin manager of Zend\I18n\Translator works. On the outside, it is an implementation of the abstract plugin manager. But if you look more closely, the plugin manager has no "parent" service locator. That means, if you have defined a reposity or service you need inside a loader, you don't have access to it!

In this blog post I will show how to fix this with an example loader, a database loader based on the EntityManager of Doctrine.

Joining YES!Delft's LaunchLab programme

Tomorrow is the first day of LaunchLab: an initiative I will join with my company Soflomo. LaunchLab is a new program from the incubator from the Delft University of Technology, called YES!Delft. The idea is to help start-ups creating their business model based on lean methods: validate your assumptions, talk with your potential clients and do not muddle along too long with your initial plans.

Out of many, 10 teams will participate in the three months programme. And tomorrow the bootcamp starts with two full days of intensive workshops from Patrick van der Pijl. Based on the ideas from Business Model Generation and the quite similar strategies from The Startup Owner's Manual I will be thought how to develop new businesses. Exciting!

Why am I writing this? Well, to be honest I am not quite sure... But what I do know is the programme will give me more insights in business development for lean start-ups. Information I am eager to adopt and probably even share here on this blog. So if everthing goes well, there is more to come about business model generation!

Use Soflomo\Prototype for quick website prototypes

Today we at Soflomo released Soflomo\Prototype, a new Zend Framework 2 module. The module is just in use for about a couple of hours, but it already saves us so much work, we would like to share it. It is available under the New BSD (3 clause) license, feel free to use it!

The goal is to make it extremely easy inside Zend Framework 2 to start prototyping html pages. Designers and frontend developers currently often have to wait for a Zend Framework 2 developer to create a couple of routes, link them to a controller, assign the right view script and enable this all in a module. With Soflomo\Prototype, you simply say url /foo/bar must render /foo/bar.phtml. Nothing more.

Interface injection with initializers in Zend\ServiceManager

The Zend\ServiceManager is a component which handles (besides other stuff) dependency injection. During the developments of Zend Framework 2 I have looked at dependency injection thoroughly. A good resource is from Martin Fowler, where he explains there are three types of dependency injection. In this post I am particularly interested in injecting soft dependencies with interface injection.

The help of the Zend\ServiceManager makes it straightforward to have decoupled objects. For the use cases where you have a soft dependency, the ServiceManager has a great tool called initializers. Initializers are small "callables" providing add-on features for your objects you pull from the service manager.

Using Zend Framework service managers in your application

Zend Framework 2 uses a ServiceManager component (in short, SM) to easily apply inversion of control. I notice there are good resources about the background of service managers (I recommend this blog post from Evan or this post from Reese Wilson) but many people still have problems to tune the SM to their needs. In this post I will try to explain the reason why the framework uses multiple service managers and how you can use these. I address the following topics:

  1. What are the different service managers?
  2. For what reason are different managers used?
  3. How does the service locator relate to the service manager?
  4. How can you define services for all those service managers?
  5. How can you retrieve services from one manager inside a second one?

Attach a view strategy for specific modules

There have been some questions around in the IRC channel and on Twitter how you could enable the Json view strategy for only a specific module in Zend Framework 2. Because I was requiring this feature too in the near future, I started exploring the code behind Zend\View and its strategies, to make this happen.

In fact the code is really simple, but like others who struggled with it, it took a while before I got to the result. If you're not interested in the working, simply copy the example code below to your module class and it should work.

namespace MyModule;

use Zend\ModuleManager\Feature;
use Zend\EventManager\EventInterface;
use Zend\Mvc\MvcEvent;

class Module implements
    Feature\BootstrapListenerInterface
{
    public function onBootstrap(EventInterface $e)
    {
        $app = $e->getApplication();
        $em  = $app->getEventManager()->getSharedManager();
        $sm  = $app->getServiceManager();

        $em->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH, function($e) use ($sm) {
            $strategy = $sm->get('ViewJsonStrategy');
            $view     = $sm->get('ViewManager')->getView();
            $strategy->attach($view->getEventManager());
        });
    }
}

In this example, I start injecting the JsonStrategy only when controllers inside my module are dispatched. Therefore I listen to the "dispatch" event only for event managers having the identifier equal to my root namespace. Then I am sure every MyModule\Controller\SomeController will cause the event to fire, but any other AnotherModule\Controller\SomeController will not.

The strategy is retrieved from the service locator, where it's directly injected with a Json renderer too (so we don't need to care about that). The service manager has also a registered ViewManager, which is a Zend\Mvc\View\Http\ViewManager, connecting the MVC parts of the framework to the Zend\View component. This manager is obviously aware of a Zend\View\View responsible for rendering view scripts and so on. The view has its own event manager, triggering events to get a renderer and inject responses into the Response object. This is where the JsonStrategy wants to listen for, so the strategy attaches some listeners to the event manager of the view.

It took some time to figure this out, but hopefully others will benefit from this article and do not get stuck in exploring the MVC layers of Zend Framework 2.

Auto detect user locale with Zend\Http\Request headers and ext/intl

With the recent beta5 release of Zend Framework 2, a completely new Zend\I18n component is shipped. The component is (without any misunderstanding about the work to get this done) a kind-of helper layer on top of ext/intl, a php extension for all kind of i18n tasks.

Since this Zend\I18n release I was thinking about using the Accept-Language header a browser sends with a request. When there is no Accept-Language header, or all the accepted languages are not in a list of supported languages, a default locale is set. It is really useful here to use the Zend\Http\Header\AcceptLanguage object here, as it returns a Zend\Stdlib\PriorityQueue. You can iterate the queue, having the best-choice language first until you get to the least-best match for a language.

To make this happen, I created a listener in a module for the bootstrap event, to register a default locale as fast as possible. For example the Module class of your Application module:

namespace Application;

use Locale;
use Zend\EventManager\EventInterface;
use Zend\ModuleManager\Feature;

class Module implements
    Feature\BootstrapListenerInterface
{
    public function onBootstrap(Event $e)
    {
        $default   = 'en';
        $supported = array('en-GB', 'en-US', 'en', 'nl-NL', 'nl');
        $app       = $e->getApplication();
        $headers   = $app->getRequest()->getHeaders();

        if ($headers->has('Accept-Language')) {
            $locales = $headers->get('Accept-Language')->getPrioritized();

            // Loop through all locales, highest priority first
            foreach ($locales as $locale) {
                if (!!($match = Locale::lookup($supported, $locale))) {
                    // The locale is one of our supported list
                    Locale::setDefault($match);
                    break;
                }
            }

            if (!$match) {
                // Nothing from the supported list is a match
                Locale::setDefault($default);
            }
        } else {
            Locale::setDefault($default);
        }
    }
}

Perhaps later on I will update it to a decent listener in a separate class. I could then use a factory to inject a default locale and a list of supported locales from the configuration. But for now, it is simple and "good enough".

Use 3rd party modules in Zend Framework 2

The release of the first RC (release candidate) of Zend Framework 2 is getting close. One last beta (beta5) and then the RC will be announced! With the current pace of modules spawning on GitHub, I think it is a good idea to give some insights in how you can use 3rd party modules. In this blog post I will focus on MVC modules: modules with routes pointing to controllers and view scripts for rendering.

Because using a 3rd party MVC module does not mean you are enforced to follow their routing scheme, use their view scripts or use the predefined forms, I will explain how you can modify those options to your needs. In short, this post contains three different topics:

  1. Change a route
  2. Change a view script
  3. Change a form

To give you a concrete example, I will use the ZfcUser module as use case, currently available on GitHub and one of the best examples of a generic 3rd party MVC module. It provides domain models (a User), controllers (for login/logout etcetera) and views. There are also some forms for ZfcUser, to be able to login and register.

Older artices can be found in the archive.