Symfony Catalunya

| Comments

Imagine yourself in front of the Barcelona’s beach in July. It sounds good, right? Then, continue imagining yourself with a great Symfony environment, with a very cold beer, amazing people and even better topics to talk about.

Isn’t it the best plan ever?

Well, if you feel that you need it, then you should continue reading this post…

I’m very very pleased to tell you that this plan is going to happen this summer. The Symfony Barcelona Association is working very hard on this first edition of Symfony Catalunya, an international Symfony event placed in our city. This event is 100% in english and is going to be very focused on how Symfony can help us in our day by day and in our jobs.

Symfony Catalunya 2016

What does it really mean? Let me explain you properly:

  • 0 smoke. This doesn’t mean that we will not talk about new concepts, like React for example, but everything will be constructive and focused on your next day work.
  • New talks. Don’t you feel that all events are populated with same talks year after year? In this event you will find only new talks.
  • Amazing speakers. Speakers are selected because their communication skills. The speaker quality is as important as the talk quality, don’t you think?
  • Community to Community. We will not make any money with that event. All earned gains will be invested in you somehow.
  • 50 euros early bird ticket. Get yours as soon as possible and join us :)
  • Take some breath. 7 talks per day, one after another is never a good option. With 4 talks per day you will be able to enjoy the city and the people.
  • Eat whatever you want, whenever you need. Your ticket doesn’t include food, but the venue is in front of great placed for having lunch and coffee.
  • Lighting talks. If you feel that you have something to show us, bring your 8 minutes speech.

Of course, and because you’re able to buy early bird tickets, we have published 4 of our 8 speakers in our website.

Companies

Are you a company placed in some part of the world? Do you like Symfony? Then this may interest you…

For only 300 euros you will be able to

  • Put your logo everywhere. We will mention you in our media channels at least once.
  • You will be able to add whatever you want in our Conference Attendee bag
  • You will get one free ticket for the conference
  • We will work very very hard to provide you an stand during the conference.
  • You will have the satisfaction to be helping the Symfony Environment, a very important part if you are looking for Symfony developers

We really appreciate companies sponsoring, and we strongly think that should always be that cheaper.

Communities

Are you a PHP or Symfony community? Well, you can help us too by spreading the word. In exchange of that, we will consider you part of our sponsoring group, adding your logo in our list as well.

And is free!

How can you help us? Well, for each new sponsor we have because of you, we will give you one free ticket for the conference. You will be able to raffle this ticket among your community.

Join us

Do you like that? Then…

To be aware of our news, follow our Twitter account (@symfonycat) and say hello :)

You Probably Need Bundle Dependencies

| Comments

This post tries to answer the Magnus Nordlander’s blog post, and to explain why the Symfony Bundle Dependencies is not just a personal project to fulfill my bundles dependencies, but a practice we should implement in all our Symfony bundles as well.

Believe me, I had a big post to explain why people really need this bundle, but I think that you don’t need these words, but a simple and real example.

Magnus, you’re right. Maybe soft dependencies between bundles could be a good option, but you know what? You know why Symfony is one of the biggest PHP projects ever? Because Symfony understands the real user needs, and furthermore, fulfills them the best way.

Why I tell this? Because your “You probably don’t need bundle dependencies” should be “You really need bundle dependencies, but you should work hard to don’t need them anymore”.

Remember, software is real, with real developers, real projects and real needs. We should take it in account as much as we can.

This is my example, from the most used bundle in the world, FOSUserBundle.

1
2
3
4
5
6
7
<service id="fos_user.user_manager.default" class="FOS\UserBundle\Doctrine\UserManager" public="false">
    <argument type="service" id="security.encoder_factory" />
    <argument type="service" id="fos_user.util.username_canonicalizer" />
    <argument type="service" id="fos_user.util.email_canonicalizer" />
    <argument type="service" id="fos_user.object_manager" />
    <argument>%fos_user.model.user.class%</argument>
</service>

I want you to focus on one single line.

1
<argument type="service" id="security.encoder_factory" />

We can discuss about how good or bad this is, but I really ensure you that you will find this in the 99,99% of all bundles. So maybe we need to change our mind and start doing decoupled bundles (not agree in fact, it depends on the case), but right now, hard bundle dependencies (composer and kernel) is something that should be covered the best we can.

About your last question, well, your libraries will require some other libraries and composer will make it happen, with an update and it’s autoloader. But your bundles will probably require dependencies as well, with composer and as well with a library like that, that will tell the Kernel witch bundle should be instanced as well to complain services dependencies.

Your Packages Dependencies

| Comments

  • A component should add as dependency all needed packages to have a complete functionality
  • A bundle should add as dependency as well all these bundles that define other services used in your own service definitions
  • Take care of your version policy. Being too restrictive reduces the compatibility with other packages.

Responsibilities

  • Hi. I’m Marc and I am an open source addict
  • Hi Marc, welcome!

That is a reality in fact. I’m part of this group of people that consider themselves addicts to open source. Big part of our work is created to be shared by everyone, and like Spider-man’s uncle said once… “With great power comes great responsibility”.

But what are those responsibilities we should take care of during our development? What parts of our application should we really take care of and which are more vulnerable over the time? Testing, documentation, clearness of our code, abstraction, extension capabilities… we could talk about them all, and for sure, each one can have enough material for an entire blog or a book.

In that case, I want to expose my personal experiences about what I learned over the time by leading an open source project, several small open source bundles and PHP libraries, and I want to do it by explaining how we should take care of our Symfony bundles or PHP component dependencies.

PHP Component Dependencies

When we talk about PHP components, we talk about framework agnostic packages, only coupled to the language itself, in that case PHP, and to some other libraries. Having said that, we could start by trying to understand how the components and bundles are split in some projects, for example Symfony or Elcodi. Both projects have components and bundles, providing the chance to all frameworks to work with their business logic.

  • So do we place all the business logic in components?
  • Yes. The why of your project is placed in libraries. This will be your service layer, and it should be covered with unit tests.

In regard to dependencies, components should only have dependencies on other components. But how can I discover what packages I really depend on? In that case it’s very simple, so we’re not working with any kind of magic. Because our packages are simple PHP classes, checking the usage of all external classes should be enough to know on which libraries we depend.

In that case, I always write code with use statements, so is much easier to check my external classes usage. Just by checking the first lines of all my classes I can guess what packages I should add in my composer.

1
2
3
4
5
6
7
8
9
10
11
12
namespace Elcodi\Component\User\EventListener;

use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Doctrine\Common\Persistence\ObjectManager;
use Elcodi\Component\Cart\Entity\Interfaces\CartInterface;
use Elcodi\Component\Cart\Wrapper\CartWrapper;
use Elcodi\Component\User\Entity\Interfaces\CustomerInterface;

/**
 * Class UpdateCartWithUserListener
 */
class UpdateCartWithUserListener

This piece of code makes you depend on four packages at least. Please, don’t focus on the versions, but only on the libraries.

1
2
3
4
5
6
7
8
"require": {
    "php": "*",

    "symfony/security": "*",
    "doctrine/common": "*",
    "elcodi/cart": "*",
    "elcodi/user": "*"
}

Dependencies of Dependencies

Your package must manage ALL of its dependencies, even if they are as well dependencies of your dependencies.

  • Your package A uses B and C.
  • Your package A requires B.
  • Package B requires C.
  • Then, your package A has both B and C. Enough.

Well, that’s not true at all, because you cannot depend never of the dependencies of your dependencies. Maybe now they require a package, but maybe this package won’t be required by your dependency anymore in the future. In that case, even if you still need it, your package will disappear from your vendor folder.

  • Your package A uses B and C.
  • Your package A requires B and C.
  • Package B requires C.
  • Then, your package A has both B and C.
  • Package B does not require C anymore.
  • You still have B and C.

Remember that… Require ALL your dependencies. All of them! That can make the difference.

Adapters

If our application is super decoupled from other libraries, and you have used adapters for those integrations, then things change. Because the use of adapters allows you to decouple from other packages literally, we should find another mechanism to say… hey, maybe you can depend on this package…. Composer proposes that mechanism, by using the suggest section.

1
2
3
"suggest": {
    "some/package": "Use ^2.5 for integration with Some Package"
}

Of course, this is not the only way of doing that. In this example we assume that our package will offer all the adapters implementing an interface, and this is just an option. In my case, I’ve been working for so long with a library called Gaufrette, and I really enjoy the way these kind of packages work.

Some of you could say… oh, but by doing that, then you’re not defining dependencies but only suggestions (sounds the same as saying nothing, in fact), but when we define a requirement is when our package cannot exist without this package. When it is a MUST.

Other kind of implementations don’t take into account the possibility of using the suggest section in composer, because they don’t really solve the dependencies problem. This implementation forces having 1+n packages, the first one containing the interface and the common content, and the other n containing each specific implementation, all of them requiring the first one as a dependency and the specific third-party package.

1
2
3
4
"require": {
    "myself/core": "*",
    "some/package": "^2.5 "
}

This is much more heavy to maintain, and only works if you only offer one port with n adapters in your package. In the case of Gaufrette, this could be a reality, so they only offer one port with n adapters, but of course, having this structure is more difficult to maintain.

Versions

That is a very complex topic. I will not talk about composer, but firstly, I will share some basic concepts that are used a lot when defining dependencies between packages.

  • ~2.5.4 means equal and bigger than 2.5.4 but smaller than 2.6
  • ~2.5 means equal and bigger than 2.5.0 but smaller than 3.0.0
  • ^2.5.4 means equal and bigger than 2.5.4 but smaller than 3.0.0
  • ^2.5 means equal and bigger than 2.5.0 but smaller than 3.0.0

The only thing I can say about that is that if your library aims to be usable by a biggest community as possible, then please consider checking your dependencies deeply, offering as much version-compatibility as possible.

The following composer requirements…

1
2
3
4
5
6
7
8
"require": {
    "php": "5.4.2",

    "symfony/security": "~2.7.3",
    "doctrine/common": "~2.7.3",
    "elcodi/cart": "~1.0.4",
    "elcodi/user": "~1.0.4"
}

are more restrictive than the following ones…

1
2
3
4
5
6
7
8
"require": {
    "php": "^5.3.9",

    "symfony/security": "^2.3",
    "doctrine/common": "^2.3",
    "elcodi/cart": "^1.0",
    "elcodi/user": "^1.0"
}

Of course, you should add requirement compliance as long as they really cover your library needs. If you use Traits, then you should use ^5.4, or if you’re using some Symfony features introduced in a specific version, then you become dependent, at least, on this version

1
2
3
4
5
6
7
8
"require": {
    "php": "^5.4",

    "symfony/security": "^2.7",
    "doctrine/common": "^2.3",
    "elcodi/cart": "^1.0",
    "elcodi/user": "^1.0"
}

Consider as well the compatibility with new major versions, as soon as they confirm their roadmap strategy and feature list. In that case, we could add compatibility with Symfony ^3.0 if we have removed all deprecated elements from old versions, or PHP ^7.0 if we don’t use any ^5.6 deprecated function.

1
2
3
4
5
6
7
8
"require": {
    "php": "^5.4|^7.0",

    "symfony/security": "^2.7|^3.0",
    "doctrine/common": "^2.3|^3.0",
    "elcodi/cart": "^1.0",
    "elcodi/user": "^1.0"
}

This is very important, because if you don’t offer this kind of compatibility, no one using your package will be able to evolve properly, and when I mean someone using your package I mean anyone using any package that, recursively, uses your package.

That can be tons of projects.

Symfony bundle dependencies

Once we have talked about PHP components, let’s talk about Symfony bundles. This is something much more complicated, because a Symfony Bundle is a PHP library that is co-existing in a framework, so it is not as easy to check all our PHP class dependencies.

The question we must ask ourselves when trying to resolve any Symfony bundle dependency map is… What do I really need to make this bundle work in any Symfony project?

Other bundles

This is one of the things Symfony doesn’t solve yet. How can a bundle depend on another bundle, but not only in the composer layer but as well in the application layer?

Well, there is a package for that (remember to star it if turns out useful for you).

Symfony Bundle Dependencies

This package allows you to create bundles with other bundle dependencies very easily. By using this package you will be able to say… okay composer, download this bundles, I need them to instantiate my bundle… and Symfony application, as soon you instantiate my bundle, please, install these other bundles as well before without any need to modify the kernel. Of course, this is only possible if the project works with that package as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
use Mmoreram\SymfonyBundleDependencies\DependentBundleInterface;

/**
 * My Bundle
 */
class MyBundle implements DependentBundleInterface
{
    /**
     * Create instance of current bundle, and return dependent bundle namespaces
     *
     * @return array Bundle instances
     */
    public static function getBundleDependencies(KernelInterface $kernel)
    {
        return [
            'Another\Bundle\AnotherBundle',
            'My\Great\Bundle\MyGreatBundle',
            new \Yet\Another\Bundle\YetAnotherBundle($kernel),
            new \Even\Another\Bundle\EvenAnotherBundle($kernel, true),
        ];
    }
}

If the project is not using this package, then the behavior of your bundle won’t change at all.

DIC Services

To resolve all your bundle dependencies you need to take a look as well at your Dependency Injection definition. Let’s imagine we have a bundle with this DIC definition.

1
2
3
4
5
6
7
8
services:

    my_service:
        class: My\Service\Class
        arguments:
            - @twig
            - my_other_service
            - @event_dispatcher

When Symfony tries to resolve this file, it needs as well all the definitions of the arguments (dependencies). The bundles that have these definitions automatically become your bundle dependencies.

The hard work here is to know which bundles have all these service definitions, and that is not always that simple. In that case, for example… Which package has the @twig service? We could think easily… well, twig/twig for sure has the class we are injecting here.

And you’re right, so if any of your classes, in that case My\Service\Class needs a class from the package twig/twig, this package will have to be required by your bundle.

But is that the real answer we need right now? Not at all. The question is not which package provides me with the Twig class, but with the @twig service, and this one is not twig\twig as this is only a PHP library, framework agnostic.

For this reason, we have a bundle called TwigBundle. This bundle, as well as other needed things, creates a new service called twig. This Bundle is required not only because we need the code under our vendor folder, but also because it has to be instantiated when our bundle is instantiated.

1
2
3
"require": {
    "symfony/twig-bundle": "^2.7"
}

If you decide to work with the symfony bundle dependency package, then this code is for you.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use Mmoreram\SymfonyBundleDependencies\DependentBundleInterface;

/**
 * My Bundle
 */
class MyBundle implements DependentBundleInterface
{
    /**
     * Create instance of current bundle, and return dependent bundle namespaces
     *
     * @return array Bundle instances
     */
    public static function getBundleDependencies(KernelInterface $kernel)
    {
        return [
            'Symfony\Bundle\TwigBundle\TwigBundle',
        ];
    }
}

If you don’t use this package, then you should add the TwigBundle instance in your AppKernel.

Requiring the Framework

How about this services file? What dependencies do you think your package has?

1
2
3
4
5
6
services:

    my_service:
        class: My\Service\Class
        arguments:
            - @event_dispatcher

Some people can say if quickly… the EventDispatcher is a requirement… but we have the same problem as before. The Event Dispatcher is a Symfony component, and has nothing to do with the exposure of their classes in the Symfony Framework dependency injection definition.

Symfony provides as well a bundle called FrameworkBundle. Its mission is, in addition to creating all the working environment for your project (the framework itself), to expose all needed services to the DIC. One of them is the Event Dispatcher from the component (if you check the composer.json file of that bundle you will discover that the symfony/event-dispatcher package is a requirement).

So, some of your bundle services should require as well this bundle.

1
2
3
"require": {
    "symfony/framework-bundle": "^2.7|^3.0"
}

This bundle is almost always required by all bundles (at least, it should), so make sure you’re really tolerant with its version, or you will make your bundle less usable than it could be.

Symfony ^3.0.0

Many packages are actually requiring a very restrictive version of Symfony. This fact has not been a problem during the latest 4 years, but nowadays Symfony v3.0.0 is going to be a reality soon, so all these packages need to make two easy things

  • Check if your bundle introduces a Symfony ~2.8 deprecated feature.
  • If it does, update your bundle to avoid this deprecation
  • Update your requirements to work as well with Symfony ^3.0.

Check that your Symfony requirements then are still valid. For example:

1
2
3
"require": {
    "symfony/framework-bundle": "^2.2|^3.0"
}

Applying this new requirement with Symfony ^3.0 maybe you had to use a new feature that was introduced in Symfony ^2.7.3. In that case, your composer.json is invalid, and if you have covered your class with tests and you run your tests with --prefer-lowest, then you will have some fails there.

You will have to update your dependency properly.

1
2
3
"require": {
    "symfony/framework-bundle": "^2.7.3|^3.0"
}

Development Dependencies

As you may already noticed, development dependencies are not loaded recursively. This means that the require-dev block of your require-dev packages is completely ignored.

In some way, this is great because you can define specifically what packages you need for your development (testing, mostly), without being worried about all the packages that require you.

In some other way, this can be bad… well, yes, you must know exactly all your dependencies for testing (there should be only a few…), so in that case, just make sure you know your application :)

Requiring PHPUnit

And then the question is… should I require PHPUnit or other testing libraries, as well as lints and formatters?

Again, some people will tell you… don’t do that! Your development and testing deployment will require more disk and more resources for composer. Well, sure, but if you depend on the pre-installed PHPUnit version, then you can have some trouble when testing.

1
2
3
4
5
"require-dev": {
    "fabpot/php-cs-fixer": "1.4.2",
    "mmoreram/php-formatter": "1.1.0",
    "phpunit/phpunit": "4.5.0"
},

I really need these versions. No others but these. For example, some lints can add some logic, or even change it. Because we’re responsible for our bundles, components or code, we should trust as less as possible in what other people can do to our dependencies (somehow we really trust a lot of packages by adding the ^2.2 symbol, but in that case we do it not for us but for our users). In testing mode, and because fortunately require-dev block is not recursive, we can perfectly be restrictive with the version we want, and as long as we want/need to change it… just do it :)

Trust

Trusting open source is something you cannot do blindly. Your project is your business, and you need to know that is safe from third party version errors and issues.

If you trust a package, like I do for example in Symfony, then use the semantic version notation in your requirements. Believe that the community will never allow back compatibilities breaks, or they will fix them all as soon as possible when introduced.

If you trust a library because it is tested, but you don’t trust their version policy, then just block the version (knowing that this restricts the compatibility with other packages), or make some push to this community for a really semantic version policy.

If you don’t trust a library at all, then don’t use it. That simple.

Conclusion

So, that’s it.

I highly recommend you, open source lover, to take as much care as possible of your package dependencies. A healthy and useful package is a package used by tons of people. Offer them some confidence and you will get a lot of feedback in return.

Share your work as much as you can, and don’t be afraid of your errors, they will be your biggest reasons for being a better developer day after day, and remember that all of us were inexperienced once.

Error is first step to success

Composer Install in CI

| Comments

If you have a project with a lot of dependencies, then you might now what I am talking about. We all love composer, but we all know as well that, at least with current PHP versions, some composer.json are very heavy to compute and fulfill. All this problems are reduced to time, and some CI engines, like Travis, only allow a finite number of seconds (in Travis case, 20 minutes).

That’s too much!

I found a solution (at least, I thought), but some days ago I saw that was not a solution at all, but a workaround that only sometimes works properly. I will explain exactly what’s the point here.

The problem

My composer.json is very big and composer needs too much time to compute all the dependencies. Reducing dependencies is not an option at all, so the only way of reducing dependencies is by doing some refactoring.

Any final project needs a lot of dependencies, and even if your composer.json file is small, you may need a dependency with a lot of dependencies.

My solution (the bad one…)

This solution is only wrong if you want to test your application under several PHP versions. That’s my case and could be yours…

Well. Computing the real dependencies in my environment seems a great solution, right? I run composer update in my computer, I update the composer.lock version in the repository, and then I only need to do composer install. What I reduce here is the computing time of all recursive dependencies from 20+ minutes to less than 5 minutes.

That’s great!

Why this is a bad solution?

Some projects have decided to increase the minimum PHP dependency only increasing the minor version of the package (and is not wrong, is not BC break). If your project believes in Semantic Version (semver), is usual to find these pieces of composer blocks

1
2
3
4
5
6
"require": {
    "php": ">5.4",
    "symfony/symfony": "^2.7",
    "doctrine/orm": "^2.5",
    "some/package": "^1.3"
}

If my development environment uses PHP 5.5, then I will be able to work with this composer requirements. Great. We update our dependencies, we update our repository with the composer.lock file, and everything should work as expected.

The problem here is that there is an scenario that we are not considering here, and is that for sure, our composer.lock is the result of computing the composer.json file in PHP 5.5, but this doesn’t mean that same dependencies will work as well in PHP 5.4.

Let’s see the some/package composer definition in version 1.3.

1
2
3
4
"require": {
    "php": ">5.4",
    "whatever/whatever": *
}

And then, let’s see the same composer file in version 1.4.

1
2
3
4
"require": {
    "php": ">5.5",
    "whatever/whatever": *
}

As long as we create the composer.lock file in our development environment (remember, with PHP 5.5), we will use version 1.4 of package some/package, but this package version is not compatible with PHP 5.4.

What will happens is that, when we do composer install in your CI, composer will throw an Exception. And that’s always bad news.

The good solution

There’s no good solution at all. In fact, there are only partial solutions, for example generating the composer.lock file with the highest PHP version allowed, but then, if you work with a dependency that forces a PHP version in each version, this won’t work at all.

1
2
3
4
"require": {
    "php": "5.4",
    "whatever/whatever": *
}

So, the only way of doing that is by using composer update in your CI platform. The good point is that you must take care of your composer.json file…

For libraries

If you work with a library, then use the biggest dependency scope. This will allow more users to use your library. Of course, you will increase the final time of composer computation time, but is not your problem at all.

Of course, library composer dependencies should be as small as possible.

1
2
3
4
"require": {
    "php": ">5.4",
    "whatever/whatever": *
}

For final projects

Final projects have the responsibility of reducing that scope, only allowing explicitly highest versions. Of course, final projects can host big composer structures (at least it’s not a bad practice…), so in that case you will have to work harder to reduce that file.

The problem here is not a problem at all, so it has no sense to test your final application under several PHP versions, at least in your CI platform. Just test it under your current PHP version, right?

1
2
3
4
"require": {
    "php": "5.5",
    "whatever/whatever": ^1.5.4
}

Symfony UG, Be Our Friend

| Comments

Symfony Barcelona UG have been looking some sponsors for a while, and we have had a great response from the community. We are so proud and happy about that.

As a User Group, we want to be a community group for all the community, so from today, you can be our UG friend :)

If you are a Symfony UG around the world and you want to be part of it, very easy. Just send an email to symfonybarcelona@gmail.com or just a simple tweet with @symfony_bcn. We will add your logo in our website and you will appear in our next event.

Then, we will be friends :)

Please, share this post on your social networks, and help us making a better world with tons of tiny and cute cats :)

Have a nice week!

Symfony Barcelona Event, September 2015

| Comments

It is a pleasure for me to announce that next September 22nd we will have a great event in Barcelona. I’ve talked many times about this local organization, but this time is pretty different. I’ll explain you.

This year Barcelona hosts the DrupalCon Europe 2015, and this is super exciting. Many people from around the world will visit our great and amazing streets and will attend to a great and big event, related with Drupal, Symfony and other interesting topics, always, related to the Drupal world.

This is very interesting from the point of view of Symfony, because as you may know, new version of drupal, Drupal8, is build using some Symfony components. This is one of the examples I refer when I talk about sharing technologies between PHP projects and when I talk about open source, community and other related topics. We’ve seen these synergies between other PHP projects and Symfony as well with Laravel, eZ Publish, Magento and Joomla (and many more, indeed)

So, this is a call to all the community coming to Barcelona next September 21st. We will host Fabien Potencier, the creator of Symfony, and Lukas Kahwe Smith, an amazing and super active PHP developer, member, for example, of the PHP-FIG group.

http://symfony-barcelona.es

Isn’t it interesting? Indeed, but this is not all!

We are planning to overcome our last assistance record, which is 140 attendees. This time, we want to fill an auditorium of 600 seats and show you what really is Barcelona, and how amazing can be :)

Our sponsors are ready
The community is ready
The organization is ready
Only one thing is missing here…

You!

Join us now for free! and please share this post to allow everyone to know about it!

EventListeners as Collectors in Symfony

| Comments

Some of my concerns during the last couple of years have been how to collect data from all installed bundles using available tools in Symfony packages. I say concerns because I don’t really know if is there a tool for that.

Some people have told me that the EventDispatcher component can do this work greatly, but then I have the same question once and again… is this component designed for such?

Let’s review some tiny concepts here.

Event immutability

Try to think what really is an event. Something that happens. For example, I wake up. Once I wake up, an event is dispatched called mmoreram.wake_up. This event, of course, is immutable. Nothing can change the fact that I woke up, so the event should be treated as an immutable object, with only reading actions.

One single property of the event is injected once is created. Did I wake up rested enough for a new crazy day with all cool guys from my office?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
namespace Mmoreram;

use Symfony\Component\EventDispatcher\Event;

/**
 * Marc woke up event
 */
class MmoreramWakeUpEvent extends Event
{
    /**
     * @var boolean
     *
     * Marc woke up rested
     */
    private $rested;

    /**
     * Construct method
     *
     * @var boolean $rested Marc woke up rested
     */
    public function __construct($rested)
    {
        $this->rested = $rested;
    }

    /**
     * Get if Marc is rested enough
     *
     * @return boolean Marc is rested enough
     */
    public function isRested()
    {
        return $this->rested;
    }
}

Of course, no one should be able to change the value of rested, because no one has the power to change the fact I woke up tired this night.

The main intention of an event is notify the world that something just happened, so any extra implementation changing this paradigm should be avoided in order to not corrupt the real meaning of the component.

Said that, and before continuing with the post… a question related to this topic. Just make sure that you can take some time to think about that.

If we talk about decoupling between components… is the concept of priority helpful? If any actor must know the priorities of all listeners in order to know its own… then can we consider that all event listeners are really decoupled between them? And how bad is that?

Collector

Let’s figure out that the system need to collect some feelings when I wake up. Let’s figure out as well that we don’t really care about how these feelings are sorted, so the problem of priority is not a problem anymore: we can ignore it completely.

We can change our event with this new implementation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
namespace Mmoreram;

use Symfony\Component\EventDispatcher\Event;
use Mmoreram\Feeling;

/**
 * Marc woke up event
 */
class MmoreramWakeUpEvent extends Event
{
    /**
     * @var boolean
     *
     * Marc woke up rested
     */
    private $rested;

    /**
     * @var Feeling[]
     *
     * Array of feelings
     */
    private $feelings;

    /**
     * Construct method
     *
     * @var boolean $rested Marc woke up rested
     */
    public function __construct($rested)
    {
        $this->rested = $rested;
        $this->feelings = [];
    }

    /**
     * Add new feeling
     *
     * @param Feeling $feeling New feeling to be added
     *
     * @return $this Self object
     */
    public function addFeeling(Feeling $feeling)
    {
        $this->feelings[] = $feeling;

        return $this;
    }

    /**
     * Get if Marc is rested enough
     *
     * @return boolean Marc is rested enough
     */
    public function isRested()
    {
        return $this->rested;
    }

    /**
     * Get all feelings
     *
     * @return Feeling[] Set of feelings
     */
    public function getFeelings()
    {
        return $this->feelings;
    }
}

Of course, in our domain we must dispatch this event one I really wake up (for example a service called MmoreramVitalActions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Mmoreram\MmoreramWakeUpEvent;

/**
 * Marc vital actions
 */
class MmoreramVitalActions
{
    /**
     * Marc wakes up
     *
     * @return Feeling[] Set of feelings resulting of the action of waking up
     */
    public function wakeUp()
    {
        $rested = $this->didMarcRestedProperly();
        $eventDispatcher = new EventDispatcher();
        $event = new MmoreramWakeUpEvent($rested);

        $dispatcher
            ->dispatch(
                'mmoreram.wake_up',
                $event
            );

        return $event->getFeelings();
    }

    /**
     * Get if Marc rested properly
     *
     * @return boolean Marc rested properly
     */
    private function didMarcRestedProperly();
}

As you can see, after dispatching the event you should be able to get all collected feelings. This means that the one in charge to fulfill this information related to my feelings should be any event listener interested in adding it’s own related feeling.

For example, an Event Listener will have the responsibility to add a feeling related to the temperature of my room.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
use Mmoreram\MmoreramWakeUpEvent;

/**
 * Marc wake up event listener related to temperature.
 * This class is intended to add a feeling depending on local temperature
 */
class TemperatureMmoreramWakeUpEventListener
{
    /**
     * Marc wakes up listener
     *
     * @param MmoreramWakeUpEvent $event Marc wake up event
     *
     * @return $this Self object
     */
    public function addTemperatureFeeling(MmoreramWakeUpEvent $event)
    {
        $feeling = $this->getTemperatureFeeling();
        $event->addFeeling($feeling);

        return $this;
    }

    /**
     * Get feeling related to the temperature
     *
     * @return Feeling Feeling related to temperature
     */
    private function getTemperatureFeeling();
}

Of course, you must add this event listener using tags in the Dependency Injection Symfony configuration.

Using tags for our listeners definition

At this point, you can see that maybe this is useful. This is a very easy and fast collector implementation, but not enough good. The event is not immutable anymore and you can change if from any event dispatcher, very far from the real intention of the component.

Solution

I am using this approach in order to be as much pragmatic as possible. Of course this works properly by adding an extra definition and documentation layer, but I wonder if other people is concerned about that in Symfony.

I don’t really think that yet another component called Collector would be necessary at all unless there is an abstraction between both components (they share some common things related to the fact of broadcasting and subscribing).

Of course, again, simple theory and personal thoughts brought to the community. I will continue using this approach even knowing that should be solved using another one as long as people understand it and is easy to work with.

Feedback and people thoughts will be appreciated, as always :)

Symfony in Barcelona

| Comments

Barcelona, one of the best cities in the world.

For you, Symfony lover. Do you know where is Barcelona, right? Well, this is a call for all Symfony lovers who want something special, something really different. Amazing people, amazing food and tons and tons of new experiences with one of the greatest Symfony Communities around the world.

A lot of companies are actually being built in this city, so we really want you with us. No matter your Symfony expertise, no matter how good you really are… in Barcelona only matters one simple thing… How good you want to be. If you want to be one of the bests, then Barcelona can be your new home :)

If you want to know more about it, just send an email to Symfony Barcelona User Group and you will be properly helped to move here with us. The group email is symfonybarcelona@gmail.com

You want to join us, but you don’t know it yet :)

Re-thinking Event Listeners

| Comments

Let’s talk about Event Listeners. Do you know what an Event Listener is?

Well, if you are used to working with Symfony, then you should know what is intended for. If you don’t, don’t hesitate to take a look at the Symfony documentation.

This post aims to start a small discussion about how an Event Listener should look like if we really want to keep things decoupled.

TL;DR

  • If we place our business logic inside the Event Listeners, we will not be able to use this logic from other points, for example sending a “Order created” email by hand from our Admin using a simple button.
  • What we could do is place ALL the logic inside a service that ONLY sends that email, exposing a simple and documented api.
  • Then, considering that this service is injectable using any Dependency Injection implementation, we can inject it into the Event Listener.
  • So, EventListeners are only a point of entry to your service layer

Using Event Listeners

To understand what I am talking about, let’s use an small example to make things more clear…

1
2
3
4
5
6
7
8
9
10
11
Scenario: You buy something in an e-commerce, so, internally, your Cart became 
an Order. Of course, and because user experience is important in that cases, you 
want to send an email to the user with some Order information, so you need to 
send an email to the Customer.

Problem: You want to create this feature in a very decoupled way, of course. The
e-commerce framework provides you that way, by proposing you an event once the
Order is created. You can access the Order itself and the Customer.

Solution: Create a new Event Listener object, subscribed to this event called
order.oncreate, and sending that email.

Let’s see a small example about how this Event Listener should look like. We will follow the simple way, only focusing about sending that email in a decoupled way with the action.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class OrderEmailEventListener
{
    /**
     * We send an email to the Customer once an order is created
     *
     * @param OrderOnCreatedEvent $event Event
     */
    public function sendEmail(OrderOnCreatedEvent $event)
    {
        $order = $event->getOrder();
        $customer = $event->getCustomer();

        /**
         * Send the email
         */
    }
}

And we could use this configuration in our bundle.

1
2
3
4
5
6
7
8
9
services:

    #
    # Event Listeners
    #
    project.event_listener.order_created_email:
        class: My\Bundle\EventListener\OrderCreatedEmailEventListener
        tags:
            - { name: kernel.event_listener, event: order.oncreate, method: sendEmail }

So this could be a simple implementation. I’ve been using it since the beginning of times as this could be considered a good practice. But, during this time doing more and more Event Listeners, some questions have come to my mind.

Decoupling from the Event

Let’s consider that our project has an admin panel. Of course, we should be able to send this email any time we need (for example, our email server was down during the order conversion and we must re-send it). Is this possible with this implementation?

Yes. Let’s do this considering that we have injected our EventListener and this one is accessible locally!

1
2
3
4
5
$event = new OrderCreatedEmailEventListener(
    $order,
    $customer
);
$orderCreatedEmailEventListener->sendEmail($event);

Well, this piece of code will really send the email… but is this implementation enough right? I don’t think so…

This Event should only be dispatched when the real event happens. It has no sense to create a new OrderEmailEventListener instance without using the event dispatcher. This means that, indeed, any Order has been created.

So first of all, creating a new Event out of turn, is not a good practice at all.

For solving this, We could do that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class OrderCreatedEmailEventListener
{
    /**
     * We send an email to the Customer once an order is created
     *
     * @param OrderOnCreatedEvent $event Event
     */
    public function sendEmail(OrderOnCreatedEvent $event)
    {
        $order = $event->getOrder();
        $customer = $event->getCustomer();

        $this->sendOrderCreatedEmail(
            $order,
            $customer
        );
    }

    /**
     * We send an email to the Customer once an order is created, given the 
     * order and the customer
     *
     * @param OrderInterface    $order    Order
     * @param CustomerInterface $customer Customer
     */
    public function sendOrderCreatedEmail(
        OrderInterface $order,
        CustomerInterface $customer
    ) {
        /**
         * Send the email
         */
    }
}

And then, we could do this

1
2
3
4
$orderCreatedEmailEventListener->sendOrderCreatedEmail(
    $order,
    $customer
);

Much better, right? But is this good enough? No is not.

Decoupling from the Listener

We are using an instance of an Event Listener to send an email. Our analysis could be exactly the same than before… Should we use an Event Listener even when an event is not dispatched?

No we should not.

An Event Listener is an event listener. Listens one event, and that should be all its work. So, we should never inject any event listener, anywhere. Let’s do some refactor here!

First of all, let’s isolate our business logic in a new service. This service will only do one thing; sending this email.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class OrderCreatedEmailSender
{
    /**
     * We send an email to the Customer once an order is created, given the 
     * order and the customer
     *
     * @param OrderInterface    $order    Order
     * @param CustomerInterface $customer Customer
     */
    public function sendEmail(
        OrderInterface $order,
        CustomerInterface $customer
    ) {
        /**
         * Send the email
         */
    }
}

This service has only one mission. Sending this email, no matter what event executes it, no matter its environment. So if we take a look at what the Event Listener implementation should look like now…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class OrderCreatedEmailEventListener
{
    /**
     * @var OrderCreatedEmailSender
     *
     * Order created email sender
     */
    private $orderCreatedEmailSender;

    /**
     * Constructor
     *
     * @param OrderCreatedEmailSender $orderCreatedEmailSender
     */
    public function __construct(OrderCreatedEmailSender $orderCreatedEmailSender)
    {
        $this->orderCreatedEmailSender = $orderCreatedEmailSender;
    }

    /**
     * We send an email to the Customer once an order is created
     *
     * @param OrderOnCreatedEvent $event Event
     */
    public function sendEmail(OrderOnCreatedEvent $event)
    {
        $order = $event->getOrder();
        $customer = $event->getCustomer();

        $this
            ->orderCreatedEmailSender
            ->sendEmail(
                $order,
                $customer
            );
    }
}

Finally, we should refactor as well the way we have defined our service in the DependencyInjection config file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
services:

    #
    # Business layer
    #
    project.business.order_created_email_sender:
        class: My\Bundle\Business\OrderCreatedEmailSender

    #
    # Event Listeners
    #
    project.event_listener.order_created_email:
        class: My\Bundle\EventListener\OrderCreatedEmailEventListener
        arguments:
            - @project.business.order_created_email_sender
        tags:
            - { name: kernel.event_listener, event: order.oncreate, method: sendEmail }

And that’s all. This example is so easy and simple, but I am sure that if you take a look at your project, you will find a lot of logic inside your Event Listeners. Maybe could be a good idea start moving all this logic out of the box, treating these listeners as real entry points, like we do with our Commands, Controllers or Twig extensions.

Defeating Expression Language

| Comments

How beautiful Expression Language definitions are, right? I mean, inserting that complex expressions in a Dependency Injection configuration file is so nice and fast if you need to inject the result of a method in a service (one of the multiple examples we can see)

Let’s see a simple example of how we use this library.

1
2
3
4
5
6
7
8
9
10
services:

    #
    # My managers
    #
    some_manager:
        class: This\Is\My\Manager
        arguments:
            - @=service("another_manager").someCall("value")
            - @=service("yet_another_manager").getInjectableInstance(parameter("my_parameter"))

This is not a bad idea, really, but because we are engineers and we should have as much information as possible in order to be able to choose between the best option, always, I will show you another way of defining this piece of code.

Let’s do that!

Factories

Remember the Factory pattern in Symfony2 post I wrote some time ago? I talked about how this pattern can be implemented in your Symfony projects.

Well, just for your information, most of your Expression Language definitions can be nicely done using Factories.

Let’s reproduce the same example using factories.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
services:

    #
    # My managers
    #
    some_manager:
        class: This\Is\My\Manager
        arguments:
            - @my_injectable_value
            - @my_injectable_service

    my_injectable_value:
        class: StdClass
        factory:
            - @another_manager
            - someCall
        arguments:
            - value

    my_injectable_service:
        class: This\Is\My\Injectable\Class
        factory:
            - @yet_another_manager
            - getInjectableInstance
        arguments:
            - %my_parameter%

Dependency

Take a look and realise that we’ve removed a package dependency from your project, as you don’t need symfony/expression-language anymore, and your DIC definition will be easily exportable to another format if someday is needed.

Reflexion

Is Expression Language a bad choice? Well, only you should be able to know if using this library is a good choice or not, because only you know your needs and your resources, but every time you add a new Expression Language line, just ask yourself…

Can I use simple DI definitions here? Is the only way I can do that?