Completion of posts

Дорабатываем новости, часть 1

Сейчас новости выводятся из массива, который расположен в PostController. Давайте исправим это недоразумение и заполним таблицу. Конечно можно сделать все руками, но мы воспользуемся библиотекой, которая сделает все за нас. Подключим composer require fzaninotto/faker.

Далее, в PostController добавим свойство public $fake_post, а так же обновим метод index этого же контроллера добавив немного кода:

        
    $this->fake_post = Factory::create();

    $manager = $this->getDoctrine()->getManager();
    for ($i = 1; $i < 20; $i++) {
        $post = new Post();
        $post->setTitle($this->fake_post->text(100));
        $post->setBody($this->fake_post->text(500));
        $post->setLikes(rand(100, 500));
        $manager->persist($post);
    }

    $manager->flush();
        
    

Обратите внимание на use App\Entity\Post и use Faker\Factory. Массив с постами можно пока оставить.

Вот что получилось: Local server run

Что здесь происходит?

  • - с помощью $manager = $this->getDoctrine()->getManager() мы инициировали менеджер объекта для конкретной сущности, в нашем случае это Post. Он отвечает за сохранение объектов и выборку объектов из базы данных;
  • - метод persist() в контексте $manager->persist($post) выполняет подготовку запроса;
  • - метод flush() в $manager->flush() записывает в базу.

Осталось только обновить страницу, тем самым вызвав код на исполнение. Запустим сервер, перейдем по маршруту /post и проверим БД: Local server run


Вывод всех новостей

Когда мы генерировали сущность Post, вместе с ней был создан репозиторий PostRepository. Представляет он из себя класс, с помощью которого мы будем общаться с БД. В нем уже заложены стандартные методы для выборки, такие как findBy, findAll, findOneBy и прочие, которые покроют наши нужды с лихвой.

PostController наследуется от AbstractController, и не сразу можно заметить откуда у него метод getDoctrine(). И это отличный пример для демонстрации использования трейтов в php, которые лично мне на практике приходится видеть не часто.

Теперь массив с новостями и код faker'a нам больше не нужны, вместо этого напишем $repository = $this->getDoctrine()->getRepository(Post::class). Собственно, применим findAll() к репозиторию и выведем на страницу посты. Добавляем в код $posts = $repository->findAll(). Local server run Обновляем страницу и наблюдаем свежесгенерированные новости.

$this->getDoctine()->getRepository(Post::class) и $this->getDoctine()->getManager()->getRepository(Post::class) равносильны.

Просмотр одной новости

Ранее, с помощью фильтра "truncate" мы сократили отображаемое количество символов у новости в общем списке. Для детального просмотра выведем каждую новость на отдельной странице. Создадим еще один метод в PostController, назовем его post.

        
    /**
    * @param Post $post
    * @return \Symfony\Component\HttpFoundation\Response
    * @Route("/post/{id}", name="post")
    */
    public function post(Post $post)
    {
        return $this->render('post/show.html.twig', [
            'post' => $post
        ]);
    }
        
    

Сначала обратим внимание на аннотации, а конкретно на @Route. После /post добавился параметр {id}, а в выражении public function post(Post $post) мы получаем конкретный пост. Ну и это все, остается только немного поработать над шаблонами.

В папке templates => post создадим шаблон show.html.twig. Код можно взять здесь. Local server run Теперь обновим ссылки с текстом Read more в шаблоне index.html.twig. Добавим в аттрибут href следующий код - {{ path('post', {'id': post.id}) }}. Запускаем сервер и проверяем. Local server run