Services are classes where you will write the Business Logic code or any other treatment that you want to make accessible to a controller or another service. The Logger delivered with Symfony2 is a service, like the Registry of Doctrine, which gives access to the EntityManager.
The example below shows how to create a service, to pass two services it can use as parameters.1- We begin by defining our service in the configuration file for services of our bundle (AcmeDemoBundle) :
src/Acme/DemoBundle/Resources/config/services.xml
<?xml version="1.0" ?>Was added a node
As parameters we added 2
We added one more
2- We create the MyService PHP class containing the code of our service "my_service".
src/Acme/DemoBundle/Service/MyService.php
<?php namespace Acme\DemoBundle\Service; use Symfony\Bundle\DoctrineBundle\Registry; use Symfony\Component\HttpKernel\Log\LoggerInterface; class MyService { //default EntityManager protected $em; //Logger protected $logger; public function __construct(Registry $doctrine, LoggerInterface $logger) { $this->em = $doctrine->getEntityManager(); $this->logger = $logger; } public function insertTime($message = 'Default message :)') { $time = new \DateTime; $myRecord = new \Acme\DemoBundle\Entity\MyServiceTable(); $myRecord->setMessage($message); $myRecord->setCallTimer($time); $this->em->persist($myRecord); $this->em->flush(); $this->logger->info('Insert one record in my_service_table (' . $time->format('Y-m-d H:i:s') . ') !'); } public function getTimeSinceLastCall() { $calls = $this->em->getRepository('AcmeDemoBundle:MyServiceTable') ->findBy(array (), array ('callTimer' => 'DESC'), 2); if (count($calls) == 2) { $diff = $calls[0]->getCallTimer()->getTimestamp() - $calls[1]->getCallTimer()->getTimestamp(); } else { $diff = 'N/A'; } return $diff; } }We first wrote the constructor that takes as parameters the
Then we created two public methods :
- insertTime that writes a database record on each call, with a timestamp (my_service_table.call_timer)
- getTimeSinceLastCall that returns the duration (in seconds) since the last call.
src/Acme/DemoBundle/Entity/MyServiceTable.php
<?php namespace Acme\DemoBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * Acme\DemoBundle\Entity\MyServiceTable * * @ORM\Table(name="my_service_table") * @ORM\Entity */ class MyServiceTable { /** * @var integer $id * * @ORM\Column(name="id", type="integer", nullable=false) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var datetime $callTimer * * @ORM\Column(name="call_timer", type="datetime", nullable=false) */ private $callTimer; /** * @var string $message * * @ORM\Column(name="message", type="string", length=255, nullable=false) */ private $message; /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set callTimer * * @param datetime $callTimer */ public function setCallTimer($callTimer) { $this->callTimer = $callTimer; } /** * Get callTimer * * @return datetime */ public function getCallTimer() { return $this->callTimer; } /** * Set message * * @param string $message */ public function setMessage($message) { $this->message = $message; } /** * Get message * * @return string */ public function getMessage() { return $this->message; } }SQL script of the table my_service_table :
CREATE TABLE IF NOT EXISTS `my_service_table` ( `id` int(11) NOT NULL AUTO_INCREMENT, `call_timer` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `message` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Test table for MyService';3- We test our service by calling it from the demo controller of AcmeDemoBundle : src/Acme/DemoBundle/Controller/DemoController.php
<?php namespace Acme\DemoBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\RedirectResponse; use Acme\DemoBundle\Form\ContactType; // these import the "@Route" and "@Template" annotations use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; class DemoController extends Controller { /** * @Route("/my_service", name="_demo_my_service") * @Template() */ public function myServiceAction() { //Call the CallTimer insertion from MyService $this->get('acme.demo.my_service')->insertTime('Call depuis le controlleur...'); //Call the last 2 calls interval from MyService $diff = $this->get('acme.demo.my_service')->getTimeSinceLastCall(); //Send time interval to the view return array('diff' => $diff); } }For each call of the URL /demo/my_service, we call our service's method insertTime that writes a record in the table my_service_table and logs a message. Then we call getTimeSinceLastCall that returns the amount of seconds since the last call of the URL, and returns the result to the view.
src/Acme/DemoBundle/Resources/view/Demo/myService.html.twig
{% extends "AcmeDemoBundle::layout.html.twig" %} {% block title "My Service" %} {% block content %} <h1>My Service !</h1> <div> <span>Last Call was {{ diff }} seconds ago ...</span> </div> {% endblock %} {% set code = code(_self) %}Result :
4- Back on the
It defines the channel used by the logger Monolog (default Symfony2 Logger) when it writes in the log files, as shown below:
[2011-11-30 02:06:39] request.INFO: Matched route "_demo_my_service" (parameters: "_controller": "Acme\DemoBundle\Controller\DemoController::myServiceAction", "_route": "_demo_my_service") [] [] [2011-11-30 02:06:39] my_service.INFO: Insert one record in my_service_table (2011-11-30 02:06:39) ! [] [] [2011-11-30 02:06:39] request.INFO: Matched route "_demo_my_service" (parameters: "_controller": "Acme\DemoBundle\Controller\DemoController::myServiceAction", "_route": "_demo_my_service") [] [] [2011-11-30 02:06:39] my_service.INFO: Insert one record in my_service_table (2011-11-30 02:06:39) ! [] [] [2011-11-30 02:06:39] request.INFO: Matched route "_demo_my_service" (parameters: "_controller": "Acme\DemoBundle\Controller\DemoController::myServiceAction", "_route": "_demo_my_service") [] [] [2011-11-30 02:06:39] my_service.INFO: Insert one record in my_service_table (2011-11-30 02:06:39) ! [] [] [2011-11-30 02:06:39] request.INFO: Matched route "_demo_my_service" (parameters: "_controller": "Acme\DemoBundle\Controller\DemoController::myServiceAction", "_route": "_demo_my_service") [] [] [2011-11-30 02:06:39] my_service.INFO: Insert one record in my_service_table (2011-11-30 02:06:39) ! [] []More on these Dependency Injection Tags that can be used for many other things : Official tags documentation
All about Symfony2 ServiceContainer : Official ServiceContainer documentation
1 comment :
cool explanation
separtion the business logic into symfony service.
Thanks for sharing the tutorial
Post a Comment
Comments are moderated before being published.