мои объекты: реклама - это отношение OneToMany к адресу, а адрес - это отношение OneToMany с городом. В City у меня есть около 200 городов, которые пользователь может выбрать 1 из EntityType. Я пытаюсь создать поисковую систему (?), В которой пользователь может фильтровать рекламу по городу. Я не уверен, что знаю, как это сделать, мой searchController имеет 1 действие:
/**
* @Route("/search/city", name = "search_city")
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
public function searchCityAction(Request $request)
{
$search = new City();
$form = $this->createForm(CityType::class, $search)
->add('submit', SubmitType::class, ["label" => "Szukaj"]);
$entityManager = $this->getDoctrine()->getManager();
if ($request->isMethod(Request::METHOD_POST))
{
$form->handleRequest($request);
$selectedCity = ($_REQUEST['city']['city']);
$address = $entityManager->getRepository(Address::class)->findBy(["city" => $selectedCity]);
$searched = $entityManager->getRepository(Advert::class)->findBy(["address" => $address]);
return $this->render("Search/searched.html.twig", ["searched" => $searched]);
}
return $this->render("Search/index.html.twig", ["form" => $form->createView()]);
}
index.html.twig:
{% extends 'base.html.twig' %}
{% block body %}
{{ form(form) }}
{% endblock %}
search.html.twig:
{% extends 'base.html.twig' %}
{% block body %}
{% for search in searched %}
{{ search.title }}
{% endfor %}
{% endblock %}
В контроллере в $ selectedCity я получил хороший идентификатор города. Но позже почему-то параметр отсутствует. В объекте Advert я получил переменную $ address, в адресе я получил переменную $ city, и я попытался взять ее из БД в этих двух строках:
$address = $entityManager->getRepository(Address::class)->findBy(["city" => $selectedCity]);
$searched = $entityManager->getRepository(Advert::class)->findBy(["address" => $address]);
но в любом случае это не работает, и я думаю, что я много совмещал и заблудился здесь
Я попытался сделать это первое решение, но оно не работает. Я изменил свой код примерно так:
if ($request->isMethod(Request::METHOD_POST))
{
$form->handleRequest($request);
$selectedCity = ($_REQUEST['city']['city']);
$address = $entityManager->getRepository(Address::class)->findBy(["city" => $selectedCity]);
$addressIds = $address->map(function($single_address) {
return $single_address->id;
});
$searched = $entityManager->getRepository(Advert::class)->findBy(["address" => $addressIds]);
return $this->render("Search/searched.html.twig", ["searched" => $searched]);
}
method "map" not found in array...
Ошибка на сайте:
Call to a member function map() on array
Вот код переменных определения из моих сущностей:
Класс рекламы:
/**
* @var Address
*
* @ORM\ManyToOne(targetEntity = "Address", inversedBy = "adverts", cascade = {"persist"})
*/
private $address;
Класс адреса:
/**
* @var Advert[]|ArrayCollection
*
* @ORM\OneToMany(targetEntity = "Advert", mappedBy = "address")
* @ORM\JoinColumn(name = "address_id", referencedColumnName = "id")
*/
private $adverts;
/**
* @var City
*
* @ORM\ManyToOne(targetEntity = "City", inversedBy = "addresses")
*/
private $city;
Класс города:
/**
* @var Address[]|ArrayCollection
*
* @ORM\OneToMany(targetEntity = "Address", mappedBy = "city")
* @ORM\JoinColumn(name = "city_id", referencedColumnName = "id")
*/
private $addresses;
Или (например) вы можете объединить критерии (как в примере Knp), чтобы расширить параметры поиска: $this->addrRepo->searchByCriteria($criteria), где $criteria представляет собой массив объектов Criteria для применения.
можешь пошагово объяснить, как это сделать на моем примере? Я действительно потерялся здесь






Когда вы запрашиваете сущности из базы данных с помощью метода Doctrine Entity Manager findBy, данные будут возвращены как ArrayCollection объектов Entity. Следовательно, вы не можете передавать их напрямую как параметр другой функции findBy.
В примере, который вы публикуете, $address представляет собой коллекцию экземпляров Address. Вы можете извлечь массив идентификаторов из коллекции и запросить их у Advert. Например:
$searched = $entityManager->getRepository(Advert::class)->findBy(["address" => $addressIds]);
Предположим, что класс Address имеет свойство ключа по умолчанию, называемое id, вы можете извлечь список идентификаторов адресов с помощью функции ArrayCollection.map:
$addressIds = $addresses->map(function($single_address) {
return $single_address->id;
})
Это единственный способ добиться того, что вы пытаетесь сделать. Но не единственный и лучший способ.
В основном, если вы устанавливаете связь bi-directional (2 способа) между Address и сущностью Advert. Вы можете просто получить доступ к списку сущностей Advert, связанных с сущностью Address, используя:
$address->adverts
Я предполагаю, что ваш adverts является свойством класса Address, сопоставленного с классом Advert.
Еще один запрос и установление отношений с Doctrine и Symfony можно найти здесь: https://symfony.com/doc/current/doctrine.html
Да, наконец, это работает. Мне пришлось немного изменить ваш код, например: $ addressIds = array_map (function ($ single_address) {return $ single_address-> id;}, $ address);
Рад слышать, что это помогает, код, который я опубликовал, является просто примером, основанным на предположении, что ваша версия Symfony ArrayCollection поддерживает вспомогательную функцию, такую как map. Если вы сочтете это полезным, не могли бы вы проголосовать за него или отметить ответ как принятый.
Я думаю, вам лучше создать репозиторий, чтобы у вас был метод поиска по каждому из них. Затем используйте
Criteriaшаблон (это показывает еще один интересный вариант использования) с параметрами для частей поиска и вызовите его из метода вашего контроллера:$results = $this->addrRepo->searchByCity($cityName);