In this post I walk through creating a basic Symfony project that uses the ThruwayBundle to publish update and new events to a Thruway WAMP (Web Application Messaging Protocol) router. This can be used to create a realtime system that monitors your traditional Symfony application.
This post touches just the surface of the ThruwayBundle. Hopefully I will continue this as a series. For now this is it though.
I assume that you are relatively familiar with Symfony and are able to create basic projects and connect to databases as well as do common Symfony tasks (cache:clear etc).
Let’s Go
Install the Symfony project:
$ symfony new SymfonyWithThruway $ cd SymfonyWithThruway $ composer require voryx/thruway:dev-master $ composer require voryx/thruway-bundle:dev-master
You can just install just the bundle, but at the time of writing I wanted to use the latest dev master so I required that for voryx/thruway as well.
Add the ThruwayBundle and JMSSerializerBundle to AppKernel.php:
new JMS\SerializerBundle\JMSSerializerBundle(), new Voryx\ThruwayBundle\VoryxThruwayBundle($this)
Add some configuration for the ThruwayBundle to your config.yml:
voryx_thruway: realm: 'realm1' url: 'ws://127.0.0.1:8081' #The url that the clients will use to connect to the router router: ip: '127.0.0.1' # the ip that the router should start on port: '8080' # public facing port. If authentication is enabled, this port will be protected trusted_port: '8081' # Bypasses all authentication. Use this for trusted clients. # authentication: 'in_memory' locations: bundles: ["AppBundle"] # files: # - "AcmeDemoBundleControllerDemoController"
CRUD
In this post, I am going to build an application that will highlight a common use-case for the ThruwayBundle.
When you are using the ThruwayBundle, you are most likely integrating some real-time aspects into an existing project. We will create a simple entity with a standard doctrine CRUD interface and then add hooks to publish updates to Thruway as entities are updated through the standard CRUD system.
Simple CRUD:
Create a simple entity:
php app/console doctrine:generate:entity --entity=AppBundle:UserStatus --format=annotation --fields="user_status:string(141) user_name:string(255)" --with-repository --no-interaction
This creates a UserStatus entity. Our marketing department wanted us to allow one more character than Twitter on user statuses so that we can say that we are better.
Make sure your database is configured.
If needed:
php app/console doctrine:database:create
Then:
php app/console doctrine:schema:create
Generate your regular CRUD:
php app/console doctrine:generate:crud --entity=AppBundle:UserStatus --with-write -n
Try the CRUD:
Start the web server:
php app/console server:start
Open a browser to: http://127.0.0.1:8000/userstatus/
You should be able to add and edit UserStatus entities through the forms-based CRUD that Symfony created for you.
Event Listening
In order for us to be notified on UserStatus updates, we will use a doctrine event listener.
First create UserStatusListener.php in src/AppBundle/EventListener/:
thruway_client = $thruway_client; } private function publishInfo(LifecycleEventArgs $args) { $entity = $args->getEntity(); if ($entity instanceof UserStatus) { $this->thruway_client->publish("user_status.new", [$entity]); } } public function postPersist(LifecycleEventArgs $args) { $this->publishInfo($args); } public function postUpdate(LifecycleEventArgs $args) { $this->publishInfo($args); } }
We now need to create an entry in services.yml for the listener service:
user_status.listener: class: AppBundle\EventListener\UserStatusListener arguments: - "@thruway.client" tags: - { name: doctrine.event_listener, event: postPersist } - { name: doctrine.event_listener, event: postUpdate }
The tags will tell symfony to hook up the class as an event listener and send postPersist and postUpdate events to it. Notice that we are sending in the “@thruway.client” service so that we can publish events from inside the listener.
Clear the cache so the service container gets rebuilt:
php app/console cache:clear
Fire up the Thruway router so that we can have something to route messages:
php app/console thruway:router:start
Now if you add or update a user status, you should be able to see the messages getting published on the router console.
Seeing Events in the Browser
Lets make something that can use these events in the browser to update statuses real-time as they are changed by the “traditional” back end.
You can make an html file with:
Now you should be able to open another browser window at http://127.0.0.1:8000/livestatus.html. Open the javascript console and update or add a status through the traditional CRUD stuff we made before. You should see the updates being logged there.
Building a page to display this information would be a whole post unto itself; so until someone writes that, it is an exercise for the reader.
- Limiting Concurrent Subscriptions With Rx - October 18, 2017
- Authorization/Permissions with Thruway - November 5, 2015
- Integrating Symfony Authentication for ThruwayBundle - June 22, 2015
Hi,
(Sorry for my poor english).
Thank you for your post.
First question : If the Thruway server is not on the local server where is the browser. How is the config.yml and the url for the ws ?
Second question : app/console start in dev environment and not in prod environment. How start thruway router ?
Thank you.
For production, you can start the symfony command with the flag: –env = prod
As far as connecting to a remote router, you should be able to do something like this:
voryx_thruway:
realm: ‘myrealm’
url: “ws://example.com:9090”
trusted_url: “ws://example.com:9090”
…