Bastian's Blog ~~~~~~~~~~~~~~ :Author: lapis :Date: Sun, 19 Dec 2010 17:35:05 +0100 :Revision: 4 :Copyright: CC by-nc-sa ================================ Symfony2 - Using the SF2 console ================================ :Keywords: Symfony2, Symfony, console, command line script, script, php, cronjab, automation, data import, :Description: :Abstract: The current project I am working on is not the first one depending on an external data sources. It is even not the first one doing it continiously. But for me it is definetly the first one using the Symfony2 framework. Seriously I was surprized how easy it was to implement it loosly and writing tests to ensure its reliability. It is always almost the same story: "As a customer I want to import data from the the superseded system in to the newly build environment". So whats the deal? Building the new system based on the database structure to make the import as easy as possible? No, way to many drawbacks and since we have our lessons learned we know that flexibility matters and we'd rather go for a better fitting database design. Webservices for the rescue ========================== As for the flexibility decoupling is the magic word. A webservice might be the right answer to this question. Why? Because there are a huge number of standards (HTTP, RSS, ATOM, XML-RPC, AJAX, …) supporting this approach, they are locally independend, and they really easy to implement. At least the old system had a RSS-feed in place. So I started investigating if there is a way in Symfony2 to call recieve data from a feed. Do you know *app/console*? ========================== Seems at least some people had the same idea as I had, retrieving data from a feed via HTTP GET. So Symfony2 comes up with a nice litte wrapper - the *console*. Unfortunately the documentation_ on the website only gives a very brief introduction to it. .. _documentation: http://docs.symfony-reloaded.org/quick_tour/the_architecture.html?highlight=console#the-command-line-interface Located in the *app* directory of your project it is ready to be called as soon your Symfony2 installation is ready to be used. Executing it on the command line without an argument it exposes its help page. .. include:: examples/024_app_console_help.txt :literal: The console provides you with almost everything necessary to run your bundle from the command line. It is even capable of creating a base setup of a new bundle using the *init:bundle* command. For example: :: $>php app/console init:bundle Application/MyBundle Making you bundle accessible from the cli ========================================= Since the search in the online documentation directly passed me to the Doctrine integration of Symfony2 using the console to do some magic handling the cache or setting up the Doctrine environment I found this as a nice source of information how to do this. Also my college Jordi_ was very helpful getting a clue of all this. .. _Jordi: http://seld.be Preparing your Bundle --------------------- Basically you just have to create a directory in your toplevel of your Bundle name *Command* and place every classfile in to be available from the command line. Surely the filenmame and the name of the containing class have to end with *Command* (e.g. 'ImportCommand'). The nice thing with his is that Symfony2 finds your class on its own. So no further configuration has to be done. Adding functionality -------------------- Before we could start implementing what your cli representation of your Bundle shall do we need to set some basics first. For starters your command class has to extends *\Symfony\Bundle\FrameworkBundle\Command\Command* to integrate well into the SF2 environment. Doing this you enables you to override the *execute()* and *configure()* functions. The names of he methods will let your guess their function. Configuration ------------- I earlier quoted that there is no further configuration is to be done. This is true in case of the registration of your command in Symfony2. Surely there is some configuration to be done in terms of name, arguments, description, and perhabs a little help text. The extended class (\Symfony\Bundle\FrameworkBundle\Command\Command) provides you with a set of setter methods to add the mentioned and more information to the configuration of your command. Since Symfony2 is still under developement please checkout the API-documentation_ for a conclusive list of those setters. .. _API-documentation: http://api.symfony-reloaded.org/PR4/Symfony/Bundle/FrameworkBundle/Command/Command.html The Name is used as the *command* in the console arguments to address your implementation. You should take care that this is all unique. One way to assure this is to adda prefix divided by colon from the realname (e.g 'myprojectname:importer'). The next specialty is the arguments list. This is defined by the *setDefinition()* method expecting a list of *InputAgrument* instances. I put together an example to make this more clear to you. .. include:: examples/024_configure.txt :literal: Once you are done you will find your implementation in the help text of *app/console*. .. include:: examples/024_app_console_myProject.txt :literal: Execution --------- As we now have configured our command Bundle we need to tell it what to do in case it gets called. For this purpose the method *execute()* was introduced. The definition of this method tells us to define two arguments: + an implementation of the *InputInterface* + an implementation of the *OutputInterface* But don't worry as usual in Symfony2 you don't have to care about their origin just make sure they are available in your implementation of *execute()*. You will need them that's for sure. The input object grants you access via a number of getter methods (like *getArgument($name)*) to it's attributes. The output object enables you to output information e.g to the console or a stream, setting the verbosity level, and so on. All you ned to do is implementing your own logic doing whatever you want after your command object was executed. To execute your implementation from the command line just type :: $php app/console myProjectName:importer RSSfeed http://feeds.liip.ch/liip_news_de to per example read the Liip_ feed into your RSSfeed interpreter. .. _Liip: http://liip.ch/jobs Conclusion ========== Once you know where to look it is a very easy process getting your Bundle accessible from the command line. The next step is running it as a cronjob to get feed updates in to my data storage. Trackbacks ========== Comments ========