Installing Messenger

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Yo Friends! It's Symfony Messenger time!!! So, what is Symfony Messenger? It's a tool that allows you to... um... send messages... Wait... that made no sense.

Um, What is Messenger?

Let's try again. Messenger is a tool that enables a really cool design pattern where you write "messages" and then other code that does something when that message is sent. If you've heard of CQRS - Command Query Responsibility Segregation - Messenger is a tool that enables that design pattern.

That's all great... and we're going to learn plenty about it. But there's a good chance you're watching this because you want to learn about something else that Messenger does: it allows you to run code asynchronously with queues & workers! OooooOOoo. That's the real fanciness of Messenger.

Oh, and I have two more sales pitches. First, Symfony 4.3 has a ton of new features that really make Messenger shine. And second, using Messenger is an absolute delight. So... let's do this!

Project Setup

If you want to become a command-bus-queue-processing-worker-middleware-envelope... and other buzzwords... Messenger master, warm up your coffee and code along with me. Download the course code from this page. When you unzip it, you'll find a start/ directory inside with the same code that you see here. Open up the README.md file for all the details about how to get the project running and a totally-unrelated, yet, lovely poem called "The Messenger".

The last setup step will be to find a terminal and use the Symfony binary to start a web-server at https://localhost:8000:

symfony serve

Ok, let's go check that out in our browser. Say hello to our newest SymfonyCasts creation: Ponka-fy Me. If you didn't already know, Ponka, by day, is one of the lead developers here at SymfonyCasts. By night... she is Victor's cat. Actually... due to her frequent nap schedule... she doesn't really do any coding... now that I think about it.

Ponka-fy Me

Anyways, we've been noticing a problem where we go on vacation, but Ponka can't come... so when we return, none of our photos have Ponka in them! Ponka-fy Me solves that: let's select a vacation photo... it uploads... and... yea! Check it out! Ponka seamlessly joined us in our vacation photo!

Behind the scenes, this app uses a Vue.js frontend... which isn't important for what we'll be learning. What is important to know is that this uploads to an API endpoint which stores the photo and then combines two images together. That's a pretty heavy thing to do on a web request... which is why, if you watch closely, it's kinda slow: it will finish uploading... wait... and, yep, then load the new image on the right.

Let's look at the API endpoint so you can get an idea of how this works: it lives at src/Controller/ImagePostController.php. Look for create() this is the upload API endpoint: it grabs the file, validates it, uses another service to store that file - that's the uploadImage() method, creates a new ImagePost entity, saves it to the database with Doctrine and then, down here, we have some code to add Ponka to our photo. That ponkafy() method does the really heavy-lifting: it takes the two images, splices them together and... to make it extra dramatic and slow-looking for the purposes of this tutorial, it takes a 2 second break for tea.

Mostly... all of this code is meant to be pretty boring. Sure, I've organized things into a few services... that's nice - but it's all very traditional. It's a perfect test case for Messenger!

Installing Messenger

So... let's get it installed! Find your terminal, open a new tab and run:

composer require messenger

When that finishes... we get a "message"... from Messenger! Well, from its recipe. This is great - but we'll talk about all this stuff along the way.

In addition to installing the Messenger component, its Flex recipe made two changes to our app. First, it modified .env. Let's see... it added this "transport" config. This relates to queuing messages - a lot more on that later.

36 lines .env
... lines 1 - 29
###> symfony/messenger ###
# Choose one of the transports below
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
# MESSENGER_TRANSPORT_DSN=doctrine://default
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
###

It also added a new messenger.yaml file, which... if you open that up... is perfectly... boring! It has transports and routing keys - again, things that relate to queuing - but it's all empty and doesn't do anything yet.

framework:
messenger:
# Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
# failure_transport: failed
transports:
# https://symfony.com/doc/current/messenger.html#transports
# async: '%env(MESSENGER_TRANSPORT_DSN)%'
# failed: 'doctrine://default?queue_name=failed'
# sync: 'sync://'
routing:
# Route your messages to the transports
# 'App\Message\YourMessage': async

So... what did installing the Messenger component give us... other than some new PHP classes inside the vendor/ directory? It gave us one new important service. Back at your terminal run:

php bin/console debug:autowiring mess

There it is! We have a new service that we can use with this MessageBusInterface type-hint. Um... what does it do? I don't know! But let's find out next! Along with learning about message classes and message handlers.

Leave a comment!

  • 2020-05-05 Diego Aguiar

    Hey Ahmedbhs

    In that case, I think you will need some sort of push notifications, you can check out the Symfony Mercure component. Or, another thing you can do is to email the pdf to the user... or, if you like being old school, you can check if the PDF is ready periodically via an AJAX call

    Cheers!

  • 2020-05-05 Ahmedbhs

    Hey

    thank you for your answer, Imagine that we need to export some pdf to a user, via symfony messenger, and the task tsak some time, how I can tell the user wait and then give him a pdf response when the file is well generated under my handler ?

  • 2020-05-04 weaverryan

    Hey Ahmedbhs!

    I'm far from a CQRS expert, so I really can't answer too intelligently here :). But as far as Messenger is concerned, it doesn't say anything about Read and Write models: it's just about dispatching and handling "messages". So, I imagine that you would create some messages classes that are meant to be "read models" with handlers that "read data" and other message classes that are meant to be "write models" with handlers that write data. It's really up to you how you want to create your message and handler classes.

    Cheers!

  • 2020-05-03 Ahmedbhs

    Hey guys, It's clear that CQRS is about séparating Read model from Write model. With symfony Messenger how is the read model and how is the write model?

  • 2020-04-21 Diego Aguiar

    It seems like they deprecate it since PHP 7.4 in favor of using https://github.com/krakjoe/...

  • 2020-04-20 Ahmedbhs

    They gonna deprecate the pthpthreads ? Or just talking about how difficult tobuse the phpthreads? Anyway still have generator it's good solution for asynchron?

  • 2020-04-20 Diego Aguiar

    Hey Ahmedbhs

    That's a good question and I think I just found the reason: https://github.com/krakjoe/...
    Basically, Symfony Messenger works in a standard and accepted way, AMPQ. So, as I see it, it's like the right version of pthreads (and more)

    Cheers!

  • 2020-04-19 Ahmedbhs

    Hey guys, thank you so mush for the tuto,
    If I understood correctly the purpose of symfony messenger is to set up an asynchronous execution system with php. By cons php it already provides pthreads and generators for this kind of execution.
    So why not just mix one of the two solutions with the event subscriber and then send messages and execute it asynchronously?
    I know symfony messanger is easier to use, I just want to understand the difference betwwen Symfony Messenger and pthreads or generator and when using each solution.

    Thank you!

  • 2020-04-07 Victor Bocharsky

    We're really happy you like it, thanks for your feedback! :)

    Cheers!

  • 2020-04-06 Daria Motorina

    Thank you for response, Victor! This application is great as base for Messenger course and as standalone project too.

  • 2020-04-06 Victor Bocharsky

    Hey Daria!

    The initial project was built from scratch for this Messenger course! Unfortunately, we don't have any course where we're building it step-by-step. The idea was so that we already have a specific project from the beginning that do some job without queues. And then we're going to refactor it using Messenger. So the Ponka-fy project was written specifically for this course.

    Cheers!

  • 2020-04-05 Daria Motorina

    In which SymfonyCasts course "Ponka-fy Me" application was developed step-by-step?

  • 2020-03-23 weaverryan

    Thank you - it's a huge compliment ❤️

  • 2020-03-19 Jean A

    Awesome! I love your courses and good job for your english. You are the first foreign teacher i follow and it's a pleasure.

  • 2020-03-19 Jean A

    Thanks, i don't really undertstand what is RabitMQ and the Messenger component for now. And my Frenglish don't help me, fortunatly i have subtitles. I saw a conference of Kevin Dunglas in french, about Mercure and it seems really great.

    Regards.

  • 2020-03-19 weaverryan

    But Mercure *is* on our list of things to cover in a different tutorial ;).

  • 2020-03-18 Diego Aguiar

    Hey Jean A

    In this course we do not cover Mercure but we do cover RabbitMQ in case you are interested. If you want to learn more about Mercure you can check the docs https://symfony.com/doc/cur...

    Cheers!

  • 2019-12-23 Victor Bocharsky

    Hey tv78-coder,

    Hm, it sounds like you don't have GD library. Please, keep in mind that you need to enable it for both CLI and PHP-FPM - those are 2 different php.ini configs. To make sure it's enabled for CLI, you can run "$ php -m" and see if the list of modules contains "gd". For PHP-FPM - you can try to check "View phpinfo()" link in the Symfony web developer toolbar, just hover over Symfony version in the right bottom corner. SO, are you really see GD for both? Also, make sure to reload your PHP-FPM service to make sure all the php.ini changes are applied.

    I hope this helps!

    Cheers!

  • 2019-12-21 tv78-coder

    I try to upload an image from the example code downloaded from the tutorial and it give me "GD Library extension not available with this PHP installation." error.

    I'm using PHP 7.3 and i am sure the GD Library is enabled. : (

  • 2019-12-10 weaverryan

    Hey AymDev!

    Yea, sorry about that issue. We've become aware that PHP 7.4.0 has an incompatibility issue with doctrine/annotations. You need to update doctrine/annotations to 1.7.0 or higher to fix it. You're right that the start code should *not* have an error. We will be working to update the start code for the tutorials to make sure it works with PHP 7.4.0 :).

    About the "ManagerRegistry" thing, you *would* need to update the constructor IF you were upgrading this application to (if i I remember correctly) DoctrineBundle 2.0. That's probably one of the updates you got when running composer update. If you only updated doctrine/annotations, that won't be needed to get things running.

    Cheers!

  • 2019-12-07 AymDev

    Hi there,
    I recently upgraded to PHP 7.4.0 and during the composer install I get the following errors during cache:clear script:

    FileLoader.php line 166:


    Notice: Trying to access array offset on value of type null in config/routes/../../src/Controller/ (which is being imported from "config/routes/annotations.yaml"). Make sure annotations are installed and enabled.

    My Composer version is 1.9.1, I'm wondering if there is an issue about PHP/Composer/Symfony or am I just missing something ? This won't block me for the course but this error shouldn't be there. Any suggestion ?

    EDIT: It is blocking, the application is showing the beautiful red error page with the same message as above.

    EDIT 2: running composer update fixed the issue but the code provided in the /start/ directory is broken as the argument of the ImagePostRepository constructor must be type-hinted to Doctrine\Common\Persistence\ManagerRegistry. Then it works !
    Sorry if I wasted a bit of your time, maybe this will help other people encountering the same issue.

  • 2019-12-03 Amin Behravesh

    Thanks a lot. :)
    For sure I will read what you have offered.

  • 2019-12-02 weaverryan

    Hi Amin Behravesh !

    Thank you :). And excellent question! To be fully honest, the CQRS & event sourcing topics are not something I'm an expert on. I use the message bus, and increasingly I like the patterns it unlocks. So, in an almost accidental way, we are using more "commands" and "events" in our app - but it we are far from using this everywhere. And, we're rarely "purists" about anything around here :). This is a topic we may cover in greater detail in the future (probably with some expert help). Until then, I'd recommend Matthias Noback's blog about the topic - https://matthiasnoback.nl/ - just search for "Matthias Noback cqrs" or "query bus". He has a ton of great info, but has tended also to be a bit more pragmatic in recent years. And, btw, he has a post about "query buses" - according to that, he doesn't particularly like them (and I don't either). For event sourcing, I would also check out https://eventsauce.io/ and any docs/blog posts you can find out about it. The library is written by Frank de Jonge, who is an expert on this topic and who I trust very much (he co-authored our React tutorial).

    Cheers!

  • 2019-11-27 Amin Behravesh

    Hi there, it was by far the best course I have ever seen, I just wanted to ask, can we use this approach(query, and command bus) for whole project? so, somehow our application will be built in event sourcing or CQRS structure, right ? And can you please explain how we can have many representation models(query) in application? maybe I am totally wrong with my question, because I'm trying to implement these architectures or patterns (or whatever :|) in symfony, and I'm totally newbie at it.

  • 2019-07-24 Victor Bocharsky

    Hey Geoff,

    Literally, it means the Form component was installed, i.e. "composer req form". Please, follow this thread for more context and more possible options how you can bypass it. In particular, here's my answer where I list all the options: https://symfonycasts.com/sc...

    Cheers!

  • 2019-07-23 Geoff Maddock

    I'm running into this issue as well. You mentioned "Installing form resolves the issue". What do you mean by that?

  • 2019-07-11 Sargath

    Hi Victor,

    No worries, thank you very much for the info.

    Cheers :)

  • 2019-07-11 Victor Bocharsky

    Hey Sargath,

    Sorry for the delay on it! More information about this problem - it IS kinda BC break in the new PHP release 7.2.20 / 7.3.7 / 7.4. It was reverted in the PHP source code for 7.2.20 / 7.3.7, so still relevant for 7.4. And you have a few options:
    1. Just temporarily require necessary packages with Composer to suppress the error and wait for the new PHP release
    2. Downgrade your PHP
    3. Or wait for the new PHP release, not sure when exactly it might be released though

    Also, you can follow the issue in Symfony repository: https://github.com/symfony/...

    I hope this helps!

    Cheers!

  • 2019-07-08 Victor Bocharsky

    Hey Sargath!

    Thank you for providing additional information! Btw, I just upgraded my PHP to the latest 7.3.7 and was able to reproduce this error! So, it sounds like PHP 7.3.7 related issue, it worked well for me on PHP 7.3.6 :/ We'll try to figure out the probably and return back to you with more updates.

    Cheers!

  • 2019-07-05 Sargath

    Hey Victor,

    Sure, I'm eager to help :) These are the screenshots with part of the stack trace https://prnt.sc/oavy1h https://prnt.sc/oavzew

    I'm using ArchLinux which is a rolling release distribution that has recent versions of packages.

    PS.
    I've also tried to upgrade the project with recent symfony version, but without success. So it might be a bug within symfony itself related with this php version.

  • 2019-07-05 Victor Bocharsky

    Hey Sargath,

    Hm, PHP 7.3.7 was released on Jul 4, but your initial comment was left on Jul 3, so seems like not PHP 7.3.7 problem. FYI, every chapter downloads the same code, I mean we provide the code of the entire course in every chapter, so no matter on what chapter you download it - you always download the same archive. Also, I can't reproduce this error on my Mac, what OS do you use? Maybe it's related to the OS. I also see that we specify config.platform.php version to 7.1.3 in composer.json, so it just should work on PHP 7.3.7. So, because we still can't reproduce this error, it's difficult to say what was wrong without debugging. Do you see more detailed output on that error? Like file/line on what it was failed? Could you copy/paste the full error output so we have more context on it?

    Cheers!

  • 2019-07-04 Sargath

    I've checked it in start dir. I've also checked other chapter's code as well. I'm using PHP 7.3.7.

  • 2019-07-04 Victor Bocharsky

    Hey Sargath,

    We're sorry about that. Hm, but I can't reproduce your issue. In what directory you run "composer install": start/ or finish/ ? And could you tell me your PHP version?

    Cheers!

  • 2019-07-03 Sargath

    Just FYI. I've got "PHP Fatal error: During class fetch: Uncaught ReflectionException: Class Symfony\Component\Form\FormTypeGuesserInterface", during installation (composer install). Installing "form" resolves the issue. Maybe your vendors dir isn't sync with composer.lock. Cheers.