Creating simple Symfony2 service

Featured Image

I am not talking about web services, but I am talking about symfony2 service container and the way of basic creating services inside Symfony2 project that are accessible from all other bundles via service container.

Why do I need to make some part of code like service inside Symfony2 anyway?

There is one possible problem:

When I started my project, I started with administrator area of application for handling CRUD operations. But this bundle is just for administrators of application. On the other side, I have to provide REST web service API that will be consumed by various devices (iPhone, Android, …).
I don’t want to put together my code for administrators and web services API code. So, after AdminBundle was finished, I decided to make another bundle inside project that will be ‘public’ side bundle and called it: ApiBundle. Inside this I will provide data that is entered and organized inside Admin area of application with REST based API .

For API, I also need same Entities used inside Admin Bundle that will handle database layer for web services too.

If I try to use  my entities that currently are inside AdminBundle from API bundle it doesn’t sounds logically to me. What if I want to separate API bundle from Admin Bundle in the future. How will I then use my entities in both? Duplicate them? I don’t think so!

For purposes like this, it’s better to create one more, separate Bundle that I called ‘CoreBundle’ that will hold all shared classes and also my entity classes for both: AdminBundle and ApiBundle.

Accessing those classes from AdminBundle and also ApiBundle I want to be via service container, so all of these methods are separated and public available for using in other bundles.

Because of that, I want to build simple Symfony2 services: one for AdminBundle and second for ApiBundle – to separate application logic.

Inside CoreBundle, I made folder called ‘Services’ and inside I put two files: Admin.php and Api.php.

Inside CoreBundle\Resources\config I made some changes to the file called ‘services.xml’:

<?xml version="1.0" ?>
 
<container xmlns="http://symfony.com/schema/dic/services"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
 
  <parameters>
     <parameter key="surgeworks_core.admin.class">Surgeworks\CoreBundle\Services\Admin</parameter>
     <parameter key="surgeworks_core.api.class">Surgeworks\CoreBundle\Services\Api</parameter>
  </parameters>
 
  <services>
     <service id="surgeworks_core.admin">
        <argument type="service" id="service_container" />
     </service>
     <service id="surgeworks_core.api">
        <argument type="service" id="service_container" />
     </service>
  </services>
</container>
//...
 
<?php
// Surgeworks\CoreBundle\DependencyInjection\Configuration.php
namespace Surgeworks\CoreBundle\DependencyInjection;
 
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
 
/**
* This is the class that validates and merges configuration from your app/config files
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritDoc}
*/
public function getConfigTreeBuilder()
 {
   $treeBuilder = new TreeBuilder();
   $rootNode = $treeBuilder->root('surgeworks_core');
 
// Here you should define the parameters that are allowed to
// configure your bundle. See the documentation linked above for
// more information on that topic.
 
   return $treeBuilder;
 }
}
 
//...

I just have to write my own functions inside mentioned Admin.php and Api.php and call them via service container from amy bundle’s controller:

//some controller
public function testAction()
{
   $statusesCount = $this->get('surgeworks_core.admin')-> Statuses_getCount();
}

And function inside Admin.php:

public function Statuses_getCount() {
   $repository = $this->getEm()->getRepository('Surgeworks\CoreBundle\Entity\Status');
   $statusesCount = $repository->getStatusesCount();
   return $statusesCount;
}

9 comments

  1. how to create the webservice using the symfony framework..please help me step by step i am new on this framwork.Please help me.

  2. Dear Darko,

    Thank you for great post.
    I’m newb for Symfony and recently look inside ‘Service Container’ and get one confusing.

    You define two Referer classes in Core service.xml.
    Surgeworks\CoreBundle\Services\Admin Surgeworks\CoreBundle\Services\Api

    It make Dependency with Referer classes who use Core Bundle, right?
    And i believed Service should be independent with any caller and Any caller just need to know the service name : $this->get(‘service_name’) to initialize her.

    It’s general Design question.

    Cheers!

  3. Thanks, @Jonathan. I appreciate your comments.I will be glad if you continue contributing on my posts 🙂

  4. Yes it would be fine to copy/paste the bundles, but for production sites would be much safer to just do “vendors:update” – anyway, thanks for the articles – I like reading them to learn more about the best way to design Symfony2 apps. Cheers, Jon.

  5. @Jonathan, sorry for misunderstanding. I have forgotten that I already published short post about REST in Symfony2: Symfony2 REST. 🙂
    Anyway, I didn’t try your proposition yet, because it’s currently unnecessary for me to have different bundles on different servers. I thing it is easier to copy/paste one bundle to every symfony2 application separately. But, if you succeed, I ‘ll be glad to publish your solution here if you want, so the whole community can see it … ;-D

  6. Wait? What do *you* mean? :S Is your next article about web services API?

    I am referring to the second one – I think it’s easier than you think – you simply create your bundles (e.g. CoreBundle, ApiBundle) – distribute them (say, on Github) and then create two SF2 apps – both apps simply “import” the bundles using the vendors script.

    I guess having the API on a separate application and a separate server, could have benefits. E.g. you could have it reading from a fast read-only replicated DB.

    But just to clarify my point before – you could also have the ApiBundle within the main app since it’s already got its own Controller dir (and the controller routes probably start with “api/1.0.”)

  7. Why didn’t you wait for my next article? 🙂 I did separate bundle for web services API I am building. To be honest, I don’t really understand what do you mean? Do you mean to build web services API on one server and consume it on another? Or to somehow share symfony services between servers? That second feature I dont thing that could be possible … 🙂

  8. Is it possible to extend a bundle to suit your needs? I remember in the SF2 cookbook/references there is a page about extending bundles?

    The reason I ask is because I’ve yet to figure out the best way to create an API for a SF2 app – at this stage I’ve also created a Core Bundle that holds all entites, etc.

    What about thinking of an API bundle as a different application altogether? It even lends itself better to being deployed on a different server. E.g. api.yoursite.com could be on a different server.

    Just some thoughts 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.