Понимание проблемы Doctrine 2 ORM Query Builder в Symfony 4

Я надеюсь, что есть несколько полезных и предпочитаемых немецких экспертов по Symfony. Я много лет работаю с PHP и сейчас попробовал во фреймворке. Сейчас я выбрал Symfony, потому что мне больше всего нравятся компоненты. Мы с QueryBuilder стоим на ногах войны - я просто этого не понимаю. Хранение значений пока работает очень хорошо, хотя я сомневаюсь, что делаю это в смысле фреймворка. Я действительно беспомощен. В настоящее время я справляюсь с этим, гоняясь за всем в необработанном формате, но я не очень доволен этим.

Как я могу реализовать следующее с помощью Doctrine?

use App\Entity\Questions;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Doctrine\ORM\EntityManager;

class QuestionsController extends AbstractController
{
/**
 * @Route("/addquestion", methods = {"POST","HEAD"})
 */
public function addQuestion()
{
    $entityManager = $this->getDoctrine()->getManager();

    $RAW_QUERY = 'SELECT COUNT(*) AS c FROM questions WHERE questToID = '.$_POST['u'].' AND  questFrom = '.$this->getUser()->getId().';';


    $statement = $entityManager->getConnection()->prepare($RAW_QUERY);
    $statement->execute();

    $total = $statement->fetchAll();

    if ($total[0]['c'] >= 3)
    {
        return new Response('error|Du kannst der selben Person maximal drei Fragen stellen.');  
    }
 [...]

Я уже пытался реализовать это и многое другое (безрезультатно): Подсчет строк в Doctrine QueryBuilder

Поскольку я плохо говорю по-английски, я очень надеюсь, что вы меня понимаете…

Будьте осторожны с этим $_POST['u'] ;)

Tarasovych 27.05.2019 08:01

Спасибо за подсказку, но что я могу сделать?

user11560373 27.05.2019 08:07

Возможно, вы сможете получить параметры POST из экземпляра Symfony\Component\HttpFoundation\Request

Tarasovych 27.05.2019 08:08

Вы имеете в виду что-то вроде этого? публичная функция addQuestion (запрос $ request)

user11560373 27.05.2019 08:13

Да, может быть что-то подобное с DI

Tarasovych 27.05.2019 08:14

Спасибо, я уже сделал это в других контроллерах. Но Query Builder меня не любит. :(

user11560373 27.05.2019 08:19

Итак, вы хотите перейти от необработанного запроса к ORM-подобному пути?

Tarasovych 27.05.2019 08:20

да, это было бы очень здорово. Я читал бесконечные учебники, но мне ничего не помогло

user11560373 27.05.2019 08:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
8
169
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Один простой способ сделать это будет примерно так (с предположением, что у вас есть объект «Вопрос» и что определенные там поля совпадают с именами столбцов из вашего необработанного запроса).

$em = $this->getDoctrine()->getManager();
$userQuestions = $em->getRepository(Question:class)->findAll(['questToID' => $_POST['u'], 'questFrom ' => $this->getUser()->getId()]);

$total = count($userQuestion);

Или, если вы предпочитаете иметь только подсчет из запроса вместо того, чтобы извлекать все совпадающие объекты и подсчитывать их, вы можете написать часть построителя запросов примерно так (в этом формате это предназначено для записи в вашем контроллере, как у вас с ваш необработанный запрос - в общем случае "правильным" местом будет класс QuestionRepository.php, откуда это будет просто вызываться в контроллере):

$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder('q');
$qb->select('count(q)');
$qb->andWhere('q.questToID = :questToID');
$qb->andWhere('q.questFrom = :questFrom');

$qb->setParameter('questToID', $_POST['u']);
$qb->setParameter('questFrom ', $this->getUser()->getId());

$total = $qb->getQuery()->getSingleScalarResult();

оба как-то не работают. Последнее предложение заканчивается: Uncaught PHP Exception Doctrine\ORM\Query\QueryException: "[Синтаксическая ошибка] строка 0, столбец 24: Ошибка: ожидаемая Doctrine\ORM\Query\Lexer::T_FROM, получено "ГДЕ"" в C: \xampp\htdocs...

user11560373 27.05.2019 13:05

Можете ли вы попробовать с обновленной версией? В общем, оба ответа работают на основе некоторого предположения, потому что ваш вопрос не содержит всей необходимой информации для точного ответа. А именно, как ваш класс сущности Вопроса определен для связанных частей (имя класса, два поля поиска).

ejuhjav 27.05.2019 14:55

действительно, это работает после того, как я добавил @ORM \ Entity (repositoryClass = "App \ Repository \ RequestsRepository"). Я очень рад этому. :-) Огромное спасибо. Это почти как изучение нового языка программирования

user11560373 27.05.2019 15:13
Ответ принят как подходящий

поэтому получение значения с помощью $_POST['u'] не рекомендуется, вы можете либо передать значение с маршрутом, либо получить его как параметр для функции:

/**
 * @Route("/addquestion/{u}", methods = {"POST","HEAD"})
 */
public function addQuestion($u)

или вы можете получить его из самого запроса:

/**
 * @Route("/addquestion", methods = {"POST","HEAD"})
 */
public function addQuestion(Request $request)

если вы хотите использовать построитель запросов, лучше всего создать репозиторий для вашей сущности и сделать там запрос:

namespace App\Repository;

use App\Entity\Questions;
use Doctrine\ORM\EntityRepository;

class QuestionsRepository extends EntityRepository
{
    public function findUserQuestions($user, $u)
    {
          $queryBuilder = $this->createQueryBuilder('c')
            ->where('c.questToID = :questToID')
            ->andWhere('c.questFrom = :questFrom')
            ->setParameters(['questToID'=>$u,'questFrom'=>$user]);
            return $queryBuilder->getQuery()->getResult();
    } 

и в вашем контроллере вы можете получить результат:

$userQuestions = $this->getDoctrine()->getRepository(Questions::class)->findUserQuestions($this->getUser(), $u);

count($userQuestions);

я надеюсь, что это будет полезно в вашем случае и немного объяснит вам, как это делается в symfony

Спасибо, но у меня это не работает :( Это заканчивается сообщением об ошибке: Неопределенный метод 'findUserQuestions'. Имя метода должно начинаться с findBy, findOneBy или countBy! Я пытался переименовать его в findBy... но потом он говорит: Uncaught PHP Exception Doctrine \ ORM \ ORMException: «Сущность «App \ Entity \ Questions» не имеет поля «userQuestions». Вы не можете вызывать «findByUserQuestions» в репозитории сущностей». Я не могу справиться с ошибками Symfony: - (

user11560373 27.05.2019 13:21

вы не можете переименовать его в findBy, потому что он уже существует, и вы получаете ошибку, потому что он не может найти репозиторий из-за использования, которое я только что отредактировал, попробуйте, пожалуйста, использовать App\Entity\Questions; и дайте мне знать, если это сработало, я обновил ответ, попробуйте сейчас, пожалуйста

Ali Mhanna 27.05.2019 13:31

хорошо, спасибо, это работает. В моем классе сущности отсутствовало: /** * @ORM\Entity (repositoryClass = "App\Repository\QuestionsRepository") */class questions {...} Но теперь у меня новая ошибка: Возвращаемое значение App\Repository\ QuestionsRepository::findUserQuestions() нужно возвращать в массив типов, возвращать объект Это действительно проклятая Symfony и я, наверное, не подходят друг другу :-D

user11560373 27.05.2019 14:47

просто возьмите :array после функции репозитория и попробуйте сбросить результат, чтобы увидеть, что вы получаете от функции ... вам просто нужно некоторое время, чтобы привыкнуть к Symfony;)

Ali Mhanna 27.05.2019 15:15

До сих пор, несмотря на все трудности, я нахожу Symfony совершенно отличным, но, к сожалению, удалить ": array" недостаточно. Я уже пробовал это.

user11560373 27.05.2019 15:25

я работаю с symfony некоторое время, и это становится только интереснее... может быть, мы передали объект пользователя вместо идентификатора пользователя $user->getId() внутри функции

Ali Mhanna 27.05.2019 15:31

Замечал такое и раньше, но не могу получить никакого результата: $userQuestion = $this->getDoctrine() -> getRepository(Questions::class) -> findUserQuestions($this->getUser() -> getId(), $ запрос-> запрос-> получить ('u')); var_dump(count($ вопрос пользователя)) die(); Предупреждение: count(): параметр должен быть массивом или объектом, реализующим исчисляемый

user11560373 27.05.2019 16:02

о, извините, я совсем забыл получить результат в конце запроса :: $queryBuilder->getQuery()->getResult();

Ali Mhanna 27.05.2019 16:08

Определенно привел к новой ошибке :-D [Семантическая ошибка] строка 0, столбец 45 рядом с 'questToID =: questToID': Ошибка: Класс App \ Entity \ Questions не имеет поля или ассоциации с именем questToID ... хотя это существует .. . `/** * @var int * * @ORM \ Column (name = "questToID", type = "integer", nullable = false) * / private $ questtoid;`

user11560373 27.05.2019 16:19

есть разница между именем переменной и определенным именем внутри формы (private $ questtoid) и (name = "questToID"), и это неправильно, вы можете взять имя внутри формы, оно вам не нужно, просто используйте его так : /** * @var integer $questToID * * @ORM\Column(type = "integer", nullable=true) */ private $questToID;

Ali Mhanna 27.05.2019 16:40

будет лучше опубликовать весь класс сущности, чтобы проверить его

Ali Mhanna 27.05.2019 16:42

Я только что сделал это. Невероятно, я этого не понимаю. Таблицу я импортировал из существующей и сгенерированной. Теперь я снова создал таблицу, и она работает. :-D Большое спасибо

user11560373 27.05.2019 16:47

Не за что :). это может стать немного сложным, удачи и получайте удовольствие от symfony

Ali Mhanna 27.05.2019 16:52

Спасибо, надеюсь, вы останетесь здесь надолго :)

user11560373 27.05.2019 16:56

Я работаю в Германии, но я не немец. mein deutsch ist nicht genug solche Sachen zum erklären ;)

Ali Mhanna 27.05.2019 20:19

Забавно, потому что мой английский недостаточно хорош, чтобы понять symfony. Вы мне очень помогли. Спасибо еще раз :)

user11560373 28.05.2019 04:16

Другие вопросы по теме