Symfony response-> send () возвращает ошибку 500

В symfony3 я пытаюсь сохранить cookie. Но когда cookie создается в первый раз, он возвращает ошибку 500.

Это код для создания файла cookie:

protected function checkForCartId(Request $request)
{
    if (!empty($this->uniqueCartId)) {
        return $this->uniqueCartId;
    }

    $response = new Response();
    if (!$request->cookies->has('uniqueCartId')) {
        $this->uniqueCartId = uniqid();
        $response->headers->setCookie(new Cookie('uniqueCartId', $this->uniqueCartId));
        $response->send();

        return $this->uniqueCartId;
    }

    return $request->cookies->get('uniqueCartId');
}

Когда я удаляю строку $response->send(), ошибка исчезает, но файл cookie не сохраняется.

Любые идеи?

=========== РЕДАКТИРОВАТЬ =============

Файл журнала (после повторного получения ошибки)

[2018-04-22 14:47:26] request.INFO: Matched route "homepage". {"route":"homepage","route_parameters":{"_controller":"AppBundle\\Controller\\DefaultController::indexAction","_route":"homepage"},"request_uri":"http://127.0.0.1:8000/","method":"GET"} []
[2018-04-22 14:47:26] security.DEBUG: Checking for guard authentication credentials. {"firewall_key":"main","authenticators":1} []
[2018-04-22 14:47:26] security.DEBUG: Calling getCredentials() on guard configurator. {"firewall_key":"main","authenticator":"AppBundle\\Security\\LoginFormAuthenticator"} []
[2018-04-22 14:47:26] security.INFO: Populated the TokenStorage with an anonymous Token. [] []
[2018-04-22 14:47:26] doctrine.DEBUG: SELECT t0.id AS id_1, t0.url AS url_2, t0.title AS title_3, t0.content AS content_4, t0.seo_title AS seo_title_5, t0.seo_description AS seo_description_6, t0.published AS published_7 FROM pages t0 WHERE t0.url = ? LIMIT 1 ["/"] []
[2018-04-22 14:47:26] doctrine.DEBUG: SELECT p0_.id AS id_0, p0_.slug AS slug_1, p0_.name AS name_2, p0_.is_published AS is_published_3, p0_.description AS description_4, p0_.price AS price_5, p0_.discount_price AS discount_price_6, p0_.page_title AS page_title_7, p0_.seo_title AS seo_title_8, p0_.seo_description AS seo_description_9 FROM product p0_ WHERE p0_.discount_price > 0 AND p0_.is_published = ? [1] []
[2018-04-22 14:47:26] doctrine.DEBUG: SELECT h0_.id AS id_0, h0_.title AS title_1, h0_.subtitle AS subtitle_2, h0_.image AS image_3, h0_.button_text AS button_text_4, h0_.button_link AS button_link_5, h0_.active AS active_6 FROM homepage_banner h0_ WHERE h0_.active = ? [1] []
[2018-04-22 14:47:26] doctrine.DEBUG: SELECT c0_.id AS id_0, c0_.name AS name_1, c0_.slug AS slug_2, c0_.page_title AS page_title_3, c0_.description AS description_4, c0_.parent_id AS parent_id_5, c0_.created_by AS created_by_6 FROM category c0_ WHERE c0_.parent_id IS NULL [] []
[2018-04-22 14:47:26] doctrine.DEBUG: SELECT t0.id AS id_1, t0.name AS name_2, t0.slug AS slug_3, t0.page_title AS page_title_4, t0.description AS description_5, t0.parent_id AS parent_id_6, t0.created_by AS created_by_7 FROM category t0 WHERE t0.parent_id = ? [1] []
[2018-04-22 14:47:26] doctrine.DEBUG: SELECT t0.id AS id_1, t0.name AS name_2, t0.slug AS slug_3, t0.page_title AS page_title_4, t0.description AS description_5, t0.parent_id AS parent_id_6, t0.created_by AS created_by_7 FROM category t0 WHERE t0.parent_id = ? [2] []
[2018-04-22 14:47:26] doctrine.DEBUG: SELECT s0_.id AS id_0, s0_.cart_id AS cart_id_1, s0_.quantity AS quantity_2, s0_.price AS price_3, s0_.discount_price AS discount_price_4, s0_.ordered AS ordered_5, s0_.created_at AS created_at_6, s0_.product_id AS product_id_7, s0_.user_id AS user_id_8 FROM shopping_cart s0_ WHERE s0_.cart_id = ? ["5adc845e728a9"] []
[2018-04-22 14:47:26] request.CRITICAL: Uncaught PHP Exception UnexpectedValueException: "The Response content must be a string or object implementing __toString(), "boolean" given." at H:\Websites\CMS\vendor\symfony\symfony\src\Symfony\Component\HttpFoundation\Response.php line 406 {"exception":"[object] (UnexpectedValueException(code: 0): The Response content must be a string or object implementing __toString(), \"boolean\" given. at H:\\Websites\\CMS\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\HttpFoundation\\Response.php:406)"} []
[2018-04-22 14:47:27] request.INFO: Matched route "_wdt". {"route":"_wdt","route_parameters":{"_controller":"web_profiler.controller.profiler:toolbarAction","token":"49bddb","_route":"_wdt"},"request_uri":"http://127.0.0.1:8000/_wdt/49bddb","method":"GET"} []

================= РЕДАКТИРОВАТЬ =============== Действие контроллера:

public function getCartItems(Request $request)
{
    $shoppingCartRepository = $this->em->getRepository(ShoppingCart::class);

    return $this->render('checkout/cart.html.twig', [
        'cartItems' => $shoppingCartRepository->findAllProductsInCart($this->getUser(), $this->checkForCartId($request))
    ]);
}

================= РЕДАКТИРОВАТЬ ===============

Моя новая функция getCartItems:

public function getCartItems(Request $request)
{
    $shoppingCartRepository = $this->em->getRepository(ShoppingCart::class);

    if (!$request->cookies->has('uniqueCartId')) {
        $this->checkForCartId($request);
    }

    $response = $this->render('checkout/cart.html.twig', [
        'cartItems' => $shoppingCartRepository->findAllProductsInCart($this->getUser(), $this->checkForCartId($request))
    ]);

    $response->headers->setCookie(new Cookie('uniqueCartId', $this->checkForCartId($request)));
    return $response;
}

============= РЕШЕНИЕ =============

public function getCartItems(Request $request)
{
    $shoppingCartRepository = $this->em->getRepository(ShoppingCart::class);

    $response = new Response();
    if (!$request->cookies->has('uniqueCartId')) {
        $response->headers->setCookie(new Cookie('uniqueCartId', $this->checkForCartId($request)));
        $response->sendHeaders();
    }

    return $this->render('checkout/cart.html.twig', [
        'cartItems' => $shoppingCartRepository->findAllProductsInCart($this->getUser(), $this->checkForCartId($request))
    ], $response);
}

В вашем файле журнала в var / log / должна быть дополнительная информация, можете ли вы добавить ее к вопросу? Я подозреваю, что где-то вы увидите сообщение «Невозможно изменить информацию заголовка - заголовки уже отправлены».

Daniel Alexandrov 22.04.2018 14:41

@DanielAlexandrov Я вставил файл журнала.

Refilon 22.04.2018 14:48

Попробуй найти ошибку, поставив блок try...catch ...

Yash Parekh 22.04.2018 14:59

Вы отправляете логическое значение в качестве полезной нагрузки ответа где-то (строка перед последней в вашем журнале). Я не могу вычесть поток вашего приложения только из этого метода, но вы не должны отправлять ответ из этой функции, потому что я предполагаю, что позже вы будете делать это снова. Как правило, если вы ожидаете результата от метода / функции, избегайте в нем побочных эффектов (например, отправки запроса в вашем случае), потому что это часто приводит к таким ошибкам.

Daniel Alexandrov 22.04.2018 15:12

@DanielAlexandrov Когда я удаляю строку $ response-> send (), она не вызывает ошибку. Я просто хочу знать, как сохранить файл cookie без этой ошибки. Не знаю, как по другому настроить. Я могу попробовать это в javascript, но это опасно?

Refilon 22.04.2018 23:42

Откуда вы вызываете этот метод? Что происходит после проверки? Если вы можете вернуть значение cookie и установить его в существующем запросе позже, он будет работать нормально. Однако, не видя кода вашего контроллера, будет сложно дать вам более конкретную информацию.

Daniel Alexandrov 22.04.2018 23:53

Обновите свой вопрос кодом контроллера. Поскольку контроллер Symfony требует возврата объекта ответа и неявно вызывает метод send возвращаемого объекта ответа, вам следует избегать этого в службе, поскольку заголовки уже были бы отправлены им, когда Symfony попытается это сделать.

Will B. 23.04.2018 08:27

@fyrye обновлен кодом контроллера

Refilon 24.04.2018 10:25

@DanielAlexandrov Я вызываю этот метод из контроллера (см. Обновленный пост). А getCartItems() я вызываю прямо в моем шаблоне веточки.

Refilon 24.04.2018 10:25
Стоит ли изучать 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
9
826
1

Ответы 1

Вам необходимо установить cookie для объекта Response, который в вашем случае является визуализированным шаблоном веточки. После небольшого рефакторинга ваш код может выглядеть так:

protected function getCardId(Request $request)
{
    if (!$request->cookies->has('uniqueCartId')) {
        $this->uniqueCartId = uniqid();
        return ['is_new' => true, 'unique_id' => $this->uniqueCartId];
    } 

    $this->uniqueId = $request->cookies->get('uniqueCartId');
    return ['is_new' => false, 'unique_id' => $request->cookies->get('uniqueCartId')];
}

...

public function getCartItems(Request $request)
{
    $shoppingCartRepository = $this->em->getRepository(ShoppingCart::class);

    $cartId = $this->getCardId($request);

    $response = $this->render('checkout/cart.html.twig', [
        'cartItems' => $shoppingCartRepository->findAllProductsInCart($this->getUser(), $cartId['uniqueId'])
    ]);

    if ($cartId['is_new']) {
        $response->headers->setCookie(new Cookie('uniqueCartId', $this->uniqueCartId));
    }
    return $response;
}

Важно отметить, что ответ возвращается только один раз, вы не можете вернуть два ответа на один запрос.

Привет, Даниэль, спасибо за ответ. Я уже пробовал это, но при этом cookie не создается.

Refilon 24.04.2018 13:28

Уверены ли вы? Вы удалили $ response-> send (); из вашего метода checkForCartId? Можете ли вы попробовать код из моего примера, включая измененный checkForCartId / getCardId?

Daniel Alexandrov 24.04.2018 15:08

Я использовал ваш код, и это дамп с app.request.cookiesParameterBag {#71 ▼ #parameters: array:1 [▼ "PHPSESSID" => "nljafbnff634j9vl69cvd07bm3" ] }. Как видите, cookie не установлен. Ошибка исчезла.

Refilon 24.04.2018 15:46

Ой, подождите, я вижу uniqueCartId в Google Chrome, но не в режиме инкогнито Google Chrome. Есть ли способ установить файлы cookie в режиме инкогнито?

Refilon 24.04.2018 15:50

@Refilon chrome в основном устанавливает кеш во временный каталог, который очищается при закрытии браузера и отключает файлы cookie и файлы cookie Flash. Таким образом, вы не можете сохранять данные cookie в режиме инкогнито. См .: Что именно делает режим инкогнито в Chrome? и en.wikipedia.org/wiki/Privacy_mode

Will B. 24.04.2018 17:24

@fyrye Это не совсем так. Потому что, когда я использую метод $response->send(), он устанавливает cookie в режиме инкогнито. В режиме инкогнито используются файлы cookie, и они также помещаются во временную папку. Поэтому, когда вы закрываете браузер, он также удаляет файлы cookie из временной папки.

Refilon 25.04.2018 08:37

@Refilon Пожалуйста, прочтите статьи, на которые я ссылался, которые объясняют то, что я упомянул. «Сохранение» данных cookie, в отличие от использования данных cookie, заставляет их функционировать так же, как сеанс.

Will B. 25.04.2018 14:41

@fyrye Да, это должно быть так. Но когда я пробую этот метод, он не сохраняет cookie во временную папку. Когда я использую $response->send(), он сохраняет cookie во временной папке. Так что мне интересно, почему он это делает?

Refilon 25.04.2018 16:41

@Refilon Покажите нам код, который вы используете сейчас, чтобы мы могли воспроизвести проблему. На моем сервере apache dev состояние cookie для приведенного выше ответа работает нормально в режиме инкогнито, протестировано путем комментирования вызова setCookie и многократного обновления страницы в Symfony 3.4.8.

Will B. 25.04.2018 17:51

@fyrye Я только что добавил новую функцию. Это не работает и не устанавливает cookie. Ни в обычном Google Chrome, ни в Google Chrome инкогнито

Refilon 27.04.2018 16:02

@Refilon в отношении вашего решения, имейте в виду, что ваш ответ ветки НЕ сможет отправлять свои собственные заголовки, так как заголовки уже были отправлены вашим ответом cookie. См .: github.com/symfony/http-foundation/blob/v3.4.8/…. Вы можете проверить это, изменив свой render на redirectToRoute, хотя обычно он также добавляет мета-тег обновления.

Will B. 27.04.2018 17:50

@fyrye Спасибо. Я думаю, он отправляет заголовки? Потому что он сохраняет файл cookie. Но теперь все работает

Refilon 29.04.2018 13:16

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