Access Service from Controller and/or Twig template

controller, service, symfony, twig, yaml

Solution

You should not call your services from the twig file, but from the controller.

The role of the controller is to :

- validate your forms if there were a form posted

- call your services to get some stuffs to display in a view

- initialize forms if there is a form to display

- return a Response that typically contains a rendered twig view

Do not call your services using something like `$client = new ClientLocation();`, but call it using the service container. This will allow you to take the whole power of the dependancy injection offered by Symfony2.

Your controller will look like :

<?php

namespace MyApp\Bundle\ServiceABCBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller
{

    public function indexAction()
    {
        $locationService = $this->container->get('location_manager');

        $someStuffs = $locationService->someMethod();

        $response = $this->render(
           'ServiceABCBundle:Default:index.html.twig', array('stuffs' => $someStuffs)
        );

        return $response;
    }

}

From your twig file, you'll be able to use the `stuffs` variable :

- `{{ stuffs }}` if your variable is a terminal ( a string, a number... )

- `{{ stuffs.attribute }}` if your variable is an object or an array

About your services file, I am a bit confused, because your architecture does not look to be the standard Symfony2's one :

# ~/MyApp/Bundle/ServiceABCBundle/Resources/config/services.yml

Why your `services.yml` file isn't in the `src/MyApp/SomethingBundle/Resources/config/` directory?

If you didn't already read it, I suggest you to have a look to the Symfony2 : The Big Picture documentation, which is the best way to start with Symfony2.

Problem

Disclaimer: I'm slowly starting to get into Symfony and still have some problems understanding how the architecture works. Currently I set up different Bundles (Services, right?) that should deliver different output for different routes. So far I got around adding a simple Twig template that loads stylesheets and scripts via Assetics and Twig-blocks. Now I added another Bundle that queries data via Buzz from a remote location, which worked fine as a standalone script, but I don't get around printing output in a Twig template. The architecture of the original script is like the following (names made more generic): - Vendors - `abstract` class that serves as base for all remote request Bundles. - ServiceABC - `abstract` class that extends `Vendors` and defines Error handling and output preparation for the ABC service. - ClientXYZ - `final` class that extends `Service_ABC`, defines output parsing and normalization of the returned data. This Bundle got a `services.yml` file: ``` # ~/MyApp/Bundle/ServiceABCBundle/Resources/config/services.yml parameters: service_abc_manager.class: MyApp\Bundle\ServiceABCBundle\Models\Service_ABC location_manager.class: MyApp\Bundle\ServiceABCBundle\Models\Clients\ClientLocation monitor_manager.class: MyApp\Bundle\ServiceABCBundle\Models\Clients\ClientMonitor services: service_abc_manager: abstract: true location_manager: class: %location_manager.class% parent: service_abc_manager monitor_manager: class: %monitor_manager.class% parent: service_abc_manager ``` Names changed for easier reference - Typos by accident possible. Now my problem/question is, that I don't really get behind the Symfony2 concept of how to get the output into the template. ``` namespace MyApp\Bundle\ServiceABCBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use MyApp\Bundle\ServiceABCBundle\Models\Clients\ClientLocation; class DefaultController extends Controller { public function indexAction() { $services = array(); $services[] = $this->container->has('service_abc_manager'); $services[] = $this->container->has('location_manager'); $services[] = $this->container->has('client_location'); $services[] = $this->container->has('ClientLocation'); var_dump( $services ); $client = new ClientLocation(); var_dump( $client ); $response = $this->render( 'Service_ABC:Default:index.html.twig' ); # $response->setCharset( 'utf-8' ); # $response->headers->set( 'Content-Type', 'text/html' ); return $response; } } ``` The output of the first `array()` named `$services` is always `false` and the `$client = new ClientLocation();` throws an Exception that the class name wasn't found. How can I access those Services/Bundle(parts)/Classes? And how would I render the output to a template? Update After I added the complete tree definition to `Configuration()->getConfigTreeBuilder()`, I'm able to see the definitions in the CLI: ``` class Configuration implements ConfigurationInterface { public function getConfigTreeBuilder() { $treeBuilder = new TreeBuilder(); $rootNode = $treeBuilder->root( 'myapp_service_abc' ); $rootNode ->children() ->scalarNode('service_abc_manager')->end() ->scalarNode('location_manager')->end() ->scalarNode('monitor_manager')->end() ->end() ; return $treeBuilder; } } ``` The CLI command `php app/console config:dump-reference myapp_service_abc` now gives me the following output: ``` myapp_service_abc: service_abc_manager: ~ location_manager: ~ monitor_manager: ~ ``` I can as well see that the config data was loaded, when I `var_dump( $loader );` inside `MyAppServiceABCExtension` right after `$loader->load( 'services.yml' );` was called. The output is the following: ``` object(Symfony\Component\DependencyInjection\Loader\YamlFileLoader) protected 'container' => object(Symfony\Component\DependencyInjection\ContainerBuilder) private 'definitions' => array 'service_abc_manager' => object(Symfony\Component\DependencyInjection\Definition) 'location_manager' => object(Symfony\Component\DependencyInjection\DefinitionDecorator) private 'parent' => string 'service_abc_manager' // etc. ``` The problem itself remains: There's still a `FALSE` return value inside `DefaultController()->indexAction()` when I `var_dump( $this->container->has( 'service_abc_manager' );`. I as well tried `var_dump( $this->container->has( 'location_manager' );` and `var_dump( $this->container->has( 'myapp.service_abc_manager' );` with the same result.

Original source