Форма поиска на Symfony

03.02.2019 в 18:44
6548
+389

Теперь когда у нас есть стили и мы можем сделать наш блог красивым, сделаем форму поиска. Поиск есть почти в каждом приложении, так почему бы и нам не иметь свой?

Для начала нам нужна верстка формы поиска. Раз у нас уже есть bootstrap, возьмем готовую. Вы можете взять целое меню bootstrap и вставить в неё нашу форму или же только значения action и name у тега input.

<form class="form-inline my-2 my-lg-0" action="{{ path('blog_search') }}" method="get">
    <input class="form-control mr-sm-2" type="search" aria-label="Search" name="q">
    <button class="btn btn-default my-2 my-sm-0" type="submit">Ищем</button>
</form>

Во-первых, необязательно для поиска использовать форму Symfony, мы можем в теге action написать имя нашего экшена, который мы назвали blog_search. Туда будут уходить данные, отправленные методом get, то есть они будут такого вида:

127.0.0.1/posts/search?q=наш_запрос 

q - потому что так мы назвали наш input. search - наш будущий роут, который будет обрабатывать наш экшен blog_search, куда мы отправляем наш запрос. Поиск мы будем делать только по названию статьи. Вы же помните, что все запросы мы пишем в PostsRepository? Так что давайте откроем этот файл и напишем следующий метод:

public function searchByQuery(string $query)
{
    return $this->createQueryBuilder('p')
                ->where('p.title LIKE :query')
                ->setParameter('query', '%'. $query. '%')
                ->getQuery()
                ->getResult();
}

Все запросы в ваших репозиториях будут начинаться с метода createQueryBuilder, куда вы передаёте ссылку (alias) на вашу таблицу. Можно писать как post, так и p, при условии что у вас только одна таблица начинается на букву p. Дальше мы указываем, что хотим все данные, где название (p.title) похоже (LIKE) на наш запрос (:query). Вам это может напомнить работу с PDO - все эти плейсхолдеры и биндинги. Поскольку мы хотим, чтобы слово, которое мы ищем в названии, могло находиться и в начале, и в середине, и в конце, обрамляем знаками процент полностью наш запрос с двух сторон. Потом получаем наш результат. Теперь этот метод мы вызовем в нашем экшене в контроллере PostsController.

Переходим в PostsController и пишем метод search().

   /**
     * @Route("/posts/search", name="blog_search")
     */
    public function search(Request $request)
    {
        $query = $request->query->get('q');
        $posts = $this->postRepository->searchByQuery($query);

        return $this->render('blog/query_post.html.twig', [
            'posts' => $posts
        ]));
    }

Как мы уже договорились, запросы будут идти на роут /posts/search, а называться он будет blog_search. Определяем это в аннотациях к методу. В качестве аргумента передаем наш Request, где хранится наш запрос. Для этого мы должны вызвать метод query() и у него метод get(), куда передаем q - имя нашего инпута, откуда мы хотим брать данные. Присваиваем переменной posts результат выполнения нашего метода searchByQuery и рендерим шаблон, где в цикле перебираем наш массив (массив, потому что результатов поиска может быть много).

{% extends 'base.html.twig' %}

{% block title %}Результаты поиска{% endblock %}

{% block body %}
    {% for post in posts %}
       <div class="media text-muted pt-3">
         <p class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
           <a href="{{ path('blog_show', {id: post.id}) }}">{{ post.title }}</a><
              {{ post.body | slice(0, 255) ~ '...'  }}
         </p>
       </div>
    {% endfor %}
    <small class="d-block text-right mt-3">
        <a href="{{ path('blog_home') }}">На главную</a>
    </small>
{% endblock %}

В шаблоне мы также использовали функцию twig slice, которая обрезает исходный текст до 255 символов и проставляет многоточие. Теперь вы можете попробовать ввести что-то в поиск и получить результат!

На этом первая часть курса закончилась. Мы научились всему, чтобы перейти к более серьёзным вещам: аутентификации на сайте, комментариям к постам, сложным связям между тегами и постами и многому другому, что вас ждёт во второй части курса!

loader
03.02.2019 в 18:44
6548
+389
Логические задачи с собеседований