如何使用搜索表单中的术语过滤结果? (Symfony 6.0.2)

问题描述 投票:0回答:1

我正在尝试向搜索表单添加一个输入,用户可以在其中指定“术语”以根据事件的标题查找事件。所以我在 SearchEventType.php 文件中添加了“标题”字段。

因为这个提交不是强制性的,所以我在SearchEventController.php和EventController.php中添加了一些条件。我可能添加了很多不必要的行。

但我没有成功实现目的:仅显示标题看起来像用户在搜索表单中输入的“术语”的事件。我尝试使用 EventRepository.php 中的函数来过滤它。目前,即使在标题字段中指定了一些“术语”,也会根据其类别和大城市显示所有事件。

你能帮我找到解决方案吗?

谢谢您的帮助。

搜索事件类型.php

<?php

namespace App\Form\Front;

use App\Entity\BigCity;
use App\Entity\Category;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SearchType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

class SearchEventType extends AbstractType
{
    private EntityManagerInterface $entityManager;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $bigcity = $options['searchFormData'] !== null ? $options['searchFormData']['bigcity'] : '';
        $category = $options['searchFormData'] !== null ? $options['searchFormData']['category'] : '';

        $builder
            ->add('title', SearchType::class, [
                'attr' => ['placeholder' => 'Search by a keyword'] 
            ])
            ->add('bigcity', EntityType::class, [
                'class' => BigCity::class,
                'choice_label' => 'cityandcountry',
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('bc')
                        ->orderBy('bc.name', 'ASC');
                },
                'placeholder' => 'big.city.selection',
                'data'=> $bigcity !== null ? $this->entityManager->getRepository(BigCity::class)->find($bigcity) : '',
            ])
            ->add('category', EntityType::class, [
                'class' => Category::class,
                'choice_label' => 'title',
                'expanded' => false,
                'multiple' => false,
                'data'=> $category !== null ? $this->entityManager->getRepository(Category::class)->find($category) : '',
            ])
            ->add('save', SubmitType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'searchFormData' => null,
            'translation_domain' => 'locationform'
        ]);
    }
}

SearchEventController.php

<?php

namespace App\Controller\Front;

use App\Form\Front\SearchEventType;
use App\Repository\EventRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class SearchEventController extends AbstractController
{
    #[Route(path: [
        'fr' => '/recherche',
        'en' => '/search'
    ], name: 'search')]
    public function search(
        Request $request,
        SessionInterface $sessionInterface,
        EventRepository $eventRepository,
    ) {
        $searchFormData  = $sessionInterface->get('searchFormData');

        $form = $this->createForm(SearchEventType::class, ['data' => $searchFormData]);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $data = $form->getData();
            $sessionInterface->set('searchFormData', $data);

            if ($request->query->get('search_event[title]')) {
                $title = $request->query->get('search_event[title]');
                $events = $eventRepository->findBy(['title' => '%'.$title.'%']);

                return $this->redirectToRoute("events", [
                    'bigcity'=> $form->get('bigcity')->getData()->getId(),
                    'category'=> $form->get('category')->getData()->getId(),
                    'title' => $form->get('title')->getData(),
                    'events' => $events
                ]);
            } else {
                $events = $eventRepository->findAll();

                return $this->redirectToRoute("events", [
                    'bigcity'=> $form->get('bigcity')->getData()->getId(),
                    'category'=> $form->get('category')->getData()->getId(),
                    'events' => $events
                ]);
            }

        }
        return $this->renderForm('front/event/search.html.twig', [
            'form' => $form,
        ]);
    }
}

EventController.php

<?php

namespace App\Controller\Front;

use App\Repository\EventRepository;
use App\Repository\BigCityRepository;
use App\Repository\CategoryRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class EventController extends AbstractController
{
    #[Route(path: [
        'fr' => '/evenements',
        'en' => '/events'
    ], name: 'events')]
    public function eventsList(
        Request $request,
        EventRepository $eventRepository,
        CategoryRepository $categoryRepository,
        BigCityRepository $bigcityRepository
    ){
        $category = $categoryRepository->findOneById($request->query->get('category'));
        $bigcity = $bigcityRepository->findOneById($request->query->get('bigcity'));
        
        if  ($request->query->get('title')){
            $title = $request->query->get('title');
            $events = $eventRepository->comingEventsWithTitleList($title, $category, $bigcity);

            return $this->render("front/event/list.html.twig", [
                'events' => $events,
                'title' => $title,
                'category' => $category,
                'bigcity' => $bigcity
            ]);
            
        } else {

            $events = $eventRepository->comingEventsList($category, $bigcity);
            
            return $this->render("front/event/list.html.twig", [
                'events' => $events,
                'category' => $category,
                'bigcity' => $bigcity
            ]);
        }
    }
}

EventRepository.php

<?php

namespace App\Repository;

use App\Entity\Event;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

/**
 * @extends ServiceEntityRepository<Event>
 *
 * @method Event|null find($id, $lockMode = null, $lockVersion = null)
 * @method Event|null findOneBy(array $criteria, array $orderBy = null)
 * @method Event[]    findAll()
 * @method Event[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class EventRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Event::class);
    }

    public function save(Event $entity, bool $flush = false): void
    {
        $this->getEntityManager()->persist($entity);

        if ($flush) {
            $this->getEntityManager()->flush();
        }
    }

    public function remove(Event $entity, bool $flush = false): void
    {
        $this->getEntityManager()->remove($entity);

        if ($flush) {
            $this->getEntityManager()->flush();
        }
    }

    public function comingEventsList($category, $bigcity): array
    {
        return $this->createQueryBuilder('e')
            ->leftJoin('e.address', 'a')
            ->andWhere('e.start >= :now')
            ->andWhere('e.category = :category')
            ->andWhere('a.bigcity = :bigcity')
            ->setParameter('now', new \DateTime())
            ->setParameter('category', $category)
            ->setParameter('bigcity', $bigcity)
            ->orderBy('e.start', 'ASC')
            ->getQuery()
            ->getResult()
        ;
    }

    public function comingEventsWithTitleList($title, $category, $bigcity): array
    {
        return $this->createQueryBuilder('e')
            ->leftJoin('e.address', 'a')
            ->andWhere('e.start >= :now')
            ->andWhere('e.title LIKE :title')
            ->andWhere('e.category = :category')
            ->andWhere('a.bigcity = :bigcity')
            ->setParameter('now', new \DateTime())
            ->setParameter('title', '%'.$title.'%')
            ->setParameter('category', $category)
            ->setParameter('bigcity', $bigcity)
            ->orderBy('e.start', 'ASC')
            ->getQuery()
            ->getResult()
        ;
    }
forms symfony search
1个回答
0
投票

可以使用各种方法和技术来实现在搜索表单中使用特定术语过滤搜索结果,具体取决于您的应用程序或网站。以下是有关如何实现此类过滤的一般指南:

设置您的搜索表单:

创建一个 HTML 表单,其中包含一个输入字段,用户可以在其中输入搜索词。 使用提交按钮或使用 JavaScript 实现实时搜索以获得即时结果。 服务器端处理:

提交表单后,搜索查询将发送到您的服务器进行处理。服务器可以使用 PHP、Node.js、Python 等多种技术来实现。 数据库查询:

您的服务器端代码应该接受搜索查询并使用它来查询您的数据库。该数据库可以是关系数据库(如 MySQL)、NoSQL 数据库(如 MongoDB)或搜索引擎(如 Elasticsearch),具体取决于搜索需求的复杂性。 过滤搜索结果:

从数据库收到结果后,您可以根据搜索词对其进行过滤。具体实现取决于您的数据库技术,但通常,您将使用 SQL 查询或 NoSQL 查询来过滤和细化结果。 对于更高级的过滤,您可以使用全文搜索或特定于搜索的库和工具来提高相关性。 显示过滤结果:

将过滤后的结果渲染为 HTML 以显示给用户。这可以是项目、卡片或适合您的应用程序的任何格式的列表。 客户端交互(可选):

您可以实现客户端交互,以允许用户进一步过滤或排序结果。例如,使用 JavaScript,您可以添加其他过滤器、排序选项或分页。

© www.soinside.com 2019 - 2024. All rights reserved.