سؤال

I would like to use this code as a service so I don't have repeat this in every controller. How would I go about using this as a service so that it functions as below?

I've read some documentation and set it up as a service per below but am unsure how this is supposed to work to pass in the variables into the twig template.

Am currently accessing it as $search = $this->get("search")->search(); but am getting an error as I pass in 'search' => $search into the twig.

(ContextErrorException: Catchable Fatal Error: Argument 1 passed to Acme\ProjectBundle\Services\Search::search() must be an instance of Acme\ProjectBundle\Services\Request, none given, called in /var/www/html/Project/src/Acme/ProjectBundle/Controller/PageController.php on line 30 and defined in /var/www/html/Project/src/Acme/ProjectBundle/Services/Search.php line 8)

What is the proper way to do this and call it in the controller???

Original Index controller without the service

public function indexAction(Request $request)
{

    // Search code
    $results = null;
    $query = $request->query->get('q');

    if (!empty($query)) {
        $em = $this->getDoctrine()->getManager();

        $results = $em->createQueryBuilder()
            ->from('AcmeProjectBundle:Blog', 'b')
            ->select('b')
            ->where('b.title LIKE :search')
            ->setParameter(':search', "%${query}%")
            ->getQuery()
            ->getResult();
    }

    return $this->render('AcmeProjectBundle:Default:index.html.twig', array(
        'query'        => $query,
        'results'      => $results,
    ));
}

Service Search class

class Search
{
   public function search(Request $request)
   {
      $results = null;
      $query = $request->query->get('q');

      if (!empty($query)) {
          $em = $this->getDoctrine()->getManager();
          $results = $em->createQueryBuilder()
            ->from('AcmeProjectBundle:Blog', 'b')
            ->select('b')
            ->where('b.title LIKE :search')
            ->setParameter(':search', "%${query}%")
            ->getQuery()
            ->getResult();
      }

      return array(
          'query'   => $query,
          'results' => $results,
       );
   }
}

index.html.twig

{% block search %}
<form action="{{ path('acme_project_search') }}" method="GET">
    <label><input type="search" name="q" value={{ query }}></label>
    <input type="submit" value="Search">
</form>
<br>
{% endblock %}

config.yml

services:
   search:
      class: Acme\ProjectBundle\Services\Search
هل كانت مفيدة؟

المحلول

If you are trying to inject the request service, you would be better to inject the request_stack service instead and access the current Request by calling the getCurrentRequest()

class Search
{
    protected $request;

    public function __construct(RequestStack $requestStack)
    {
        $this->request = $requestStack->getCurrentRequest();
        //Do any kinds of initializing you need
    }

    public function mySearch()
    {
       $results = null;
       $query = $this->request->query->get('q');
       //Do your search base on $query
       //I suggest to send the container instead of RequestStack because you want to do search by using EntityManger, too
       //Return the results
    }
}

and change your service.yml as below and set the scope to "request"

services:
   search:
      class:     Acme\ProjectBundle\Services\Search
      arguments: ["@request_stack"]
      scope: "request"

You also have another option to send the container as a parameter to your service and in your service use container->getRequset()

نصائح أخرى

You need to inject Request into your service:

search:
    class: Acme\ProjectBundle\Services\Search
    scope: request
    arguments: [@request]

then in your Search class:

private $request;

public function __construct(Request $request)
{
    $this->request = $request;
}

after that whenever you need to access Request inside your service just use $this->request. And remove Request $request parameter injection in your search function.

UPDATE:

Your indexAction would become like this:

public function indexAction(Request $request)
{
    return $this->render('AcmeProjectBundle:Default:index.html.twig',
        $this->get('search')->search()
    );
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top