Symfony: add your custom service

Oh, this is the core part of doing symfony project

Add your own custom service

Since we could use as much different service from installing bundles

but what happend if we need the complex method to combien those service into one method?

so this case could be solved by customise your own service

and in this service you could inject dependencies which simply use after called one method

so that’s do it!!

For this case we want the article content part has markdown formatted html, what is this? you could check the good doc here

that’s the service need to add here: MarkdownBundle

Step 1 Installing MarkdownBundle

go to terminal, type follow command:
$ composer require knplabs/knp-markdown-bundle

check in bundle.php file, you should be able see the service is been add:

Knp\Bundle\MarkdownBundle\KnpMarkdownBundle::class => ['all' => true],

then run this:

$ ./bin/console debug:autowiring

you should be see the alias has been add:

Step 2 changed twig template content variable

find the article text you want to called by twig variable:

<div class="article-text">
    <p>Spicy jalapeno bacon ipsum dolor amet veniam shank in dolore. Ham hock nisi landjaeger cow,
        lorem proident beef ribs aute enim veniam ut cillum pork chuck picanha. Dolore reprehenderit
        labore minim pork belly spare ribs cupim short loin in. Elit exercitation eiusmod dolore cow
        turkey shank eu pork belly meatball non cupim.</p>

    <p>Laboris beef ribs fatback fugiat eiusmod jowl kielbasa alcatra dolore velit ea ball tip. Pariatur
        laboris sunt venison, et laborum dolore minim non meatball. Shankle eu flank aliqua shoulder,
        capicola biltong frankfurter boudin cupim officia. Exercitation fugiat consectetur ham. Adipisicing
        picanha shank et filet mignon pork belly ut ullamco. Irure velit turducken ground round doner incididunt
        occaecat lorem meatball prosciutto quis strip steak.</p>

    <p>Meatball adipisicing ribeye bacon strip steak eu. Consectetur ham hock pork hamburger enim strip steak
        mollit quis officia meatloaf tri-tip swine. Cow ut reprehenderit, buffalo incididunt in filet mignon
        strip steak pork belly aliquip capicola officia. Labore deserunt esse chicken lorem shoulder tail consectetur
        cow est ribeye adipisicing. Pig hamburger pork belly enim. Do porchetta minim capicola irure pancetta chuck
        fugiat.</p>

    <p>Sausage tenderloin officia jerky nostrud. Laborum elit pastrami non, pig kevin buffalo minim ex quis. Pork belly
        pork chop officia anim. Irure tempor leberkas kevin adipisicing cupidatat qui buffalo ham aliqua pork belly
        exercitation eiusmod. Exercitation incididunt rump laborum, t-bone short ribs buffalo ut shankle pork chop
        bresaola shoulder burgdoggen fugiat. Adipisicing nostrud chicken consequat beef ribs, quis filet mignon do.
        Prosciutto capicola mollit shankle aliquip do dolore hamburger brisket turducken eu.</p>

    <p>Do mollit deserunt prosciutto laborum. Duis sint tongue quis nisi. Capicola qui beef ribs dolore pariatur.
        Minim strip steak fugiat nisi est, meatloaf pig aute. Swine rump turducken nulla sausage. Reprehenderit pork
        belly tongue alcatra, shoulder excepteur in beef bresaola duis ham bacon eiusmod. Doner drumstick short loin,
        adipisicing cow cillum tenderloin.</p>
</div>

we could first change this part as follow:

<div class="article-text">
    {{ articleContent }}
</div>

wow, this is just cut all those long text into one variable called

Step 3 Inject the articleContent variable in Controller

That’s put this variable in src/Controller/ArticleController.php, function show():

$articleContent = <<<EOF
    Spicy **jalapeno bacon** ipsum dolor amet veniam shank in dolore. Ham hock nisi landjaeger cow,
    lorem proident [beef ribs](https://baconipsum.com/) aute enim veniam ut cillum pork chuck picanha. Dolore reprehenderit
    labore minim pork belly spare ribs cupim short loin in. Elit exercitation eiusmod dolore cow
    turkey shank eu pork belly meatball non cupim.
    Laboris beef ribs fatback fugiat eiusmod jowl kielbasa alcatra dolore velit ea ball tip. Pariatur
    laboris sunt venison, et laborum dolore minim non meatball. Shankle eu flank aliqua shoulder,
    capicola biltong frankfurter boudin cupim officia. Exercitation fugiat consectetur ham. Adipisicing
    picanha shank et filet mignon pork belly ut ullamco. Irure velit turducken ground round doner incididunt
    occaecat lorem meatball prosciutto quis strip steak.
    Meatball adipisicing ribeye bacon strip steak eu. Consectetur ham hock pork hamburger enim strip steak
    mollit quis officia meatloaf tri-tip swine. Cow ut reprehenderit, buffalo incididunt in filet mignon
    strip steak pork belly aliquip capicola officia. Labore deserunt esse chicken lorem shoulder tail consectetur
    cow est ribeye adipisicing. Pig hamburger pork belly enim. Do porchetta minim capicola irure pancetta chuck
    fugiat.
 EOF;

and we need to call the service Markdown to make this content show out correctly with html format

Step 4 Call the service

here is the key point, we could either call the service inside the function show(), like this:

public function show($slug, MarkdownInterface $markdown)
{
  $item = $cache->getItem('markdown_'.md5($articleContent));
        if (!$item->isHit()) {
            $item->set($markdown->transform($articleContent));
            $cache->save($item);
        }
        $articleContent = $item->get();
}

( here the code is also called the catch service, all the markdown item has to transform first then save after cache, for catch service I will try to finger out later….)

But the goal is make the code more easy to extend and more readable,, reuseful, so that’s put this code in another service file, and create a file called MarkdownHelper.php

src/Service/MarkdownHelper.php

put a function called parse and use a string argument called $source which will return a string, also since inside the function has called the catch service and markdown service, it has to add in arguments:

<?php
namespace App\Service;
class MarkdownHelper
{
    public function parse(string $source, AdapterInterface $cache, MarkdownInterface $markdown): string
    {
        $item = $cache->getItem('markdown_'.md5($source));
        if (!$item->isHit()) {
            $item->set($markdown->transform($source));
            $cache->save($item);
        }
        return $item->get();
    }
}

Step 5 Inject your service to another Controller

go to src/Controller/ArticleController.php

here you could inject your markdownHelper class you just had created:

 $articleContent = $markdownHelper->parse(
            $articleContent,
            $cache,
            $markdown
        );

and remember to add this variable if need to show in show.html.twig:

return $this->render('article/show.html.twig', [
    'title' => ucwords(str_replace('-', ' ', $slug)),
    'comments' => $comments,
    'slug' => $slug,
    'articleContent' => $articleContent,
]);

Step 6 proper dependency injection

Whenever you have a service that depends on other services, like $cache or $markdown, instead of passing those in as arguments to the individual method, you should pass them via a constructor:

private $cache;
private $markdown;
public function __construct(AdapterInterface $cache, MarkdownInterface $markdown)
{
    $this->cache = $cache;
    $this->markdown = $markdown;
}

public function parse(string $source): string
{
    $item = $this->cache->getItem('markdown_'.md5($source));
    if (!$item->isHit()) {
        $item->set($this->markdown->transform($source));
        $this->cache->save($item);
    }
    return $item->get();
}

once done, you might notice there might be error shown:

this is because we had cache and markdown services in this controller, that’s add those alias on the header:

use Michelf\MarkdownInterface;
use Symfony\Component\Cache\Adapter\AdapterInterface;

then go back to articleController.php
you could just pass one argument instead since add the construct:

$articleContent = $markdownHelper->parse($articleContent);

Step 7 Final decor your twig template
Final, run your browser:

That’s what we want to do, those markdown syntag, here you could add twig filtre raw to make it safe:

{{ articleContent|raw }}

then refresh:

 

voila, this chapter is long, but it is very useful in the future if we need to add customise service

github commit code here