Symfony test app.user имеет значение null в ветке

Я использую app.user в ветке. Когда я пишу тест, у меня есть авторизованный пользователь, и он отлично работает в контроллере. Но в twig при доступе к app.user он равен нулю.

Вот как я регистрирую пользователя в тестовом модуле:

    $user = new User;
    $user->setRole('ROLE_ADMIN');
    $user->setUsername('admin');
    $firewallContext = 'main';
    $token = new UsernamePasswordToken(serialize($user), null, $firewallContext, array('ROLE_ADMIN'));
    $session->set('_security_'.$firewallContext, serialize($token));
    $session->save();

    $cookie = new Cookie($session->getName(), $session->getId());
    $this->client->getCookieJar()->set($cookie);

Что мне не хватает, чтобы заставить его работать в ветке?

скопируйте полную функцию вашего контроллера, пожалуйста ... В этом коде нет рендера.

Preciel 12.05.2018 23:06

Это часть контроллера, в которой выполняется рендеринг. Приведенный выше код находится в тестовом модуле. code return $ this-> render ('admin / listeutilisateurs.html.twig', array ('users' => $ Users, 'roles' => $ tab, 'equipes' => $ equipes,)); code

atcCoder 12.05.2018 23:32

в вашем контроллере вы передаете users в качестве параметров вашему представлению ветки, а не app. Так что app.user работать не будет. app не определен, поэтому не существует в представлении ветки тура.

Preciel 13.05.2018 00:12

Нет, переменная приложения существует в twig как глобальная переменная, и она работает. Только в тесте эта переменная (app.user) имеет значение NULL.

atcCoder 13.05.2018 10:01

Зарегистрированный пользователь не установлен для сеанса, потому что serialize () не считает все необходимые поля.

Theva 23.11.2019 15:27

ссылка: symfony.com/doc/4.0/security/…

Theva 23.11.2019 15:44
Стоит ли изучать 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 и хотите разрабатывать...
2
6
984
2

Ответы 2

У меня была аналогичная проблема (вход в систему правильно), что в конечном итоге решило для меня изменение способа входа в систему, это мой авторизованный клиент, и вы могли адаптировать его для своих целей. (версия Symfony: 2.8)

private function createAuthorizedClient() 
{
      $client = static::createClient();
      $container = static::$kernel->getContainer();
      $session = $container->get('session');
      $token = new UsernamePasswordToken('john.doe', null, 'main', array('ROLE_ADMIN'));
      $session->set('_security_main', serialize($token));
      $session->save();
      $client->getCookieJar()->set(new Cookie($session->getName(), $session->getId()));
      return $client;
}

Спасибо, это примерно то же самое, что и у меня, но я все равно попробовал. И тот же результат, он отлично работает в контроллере, но не в ветке для app.user.

atcCoder 16.05.2018 09:08

Я не могу сказать вам, как настроить Twig в тестовой среде для предоставления app.user, но я сделал обходной путь, чтобы получить почти ту же функциональность.

В двух словах:

  • Создайте расширение Twig, чтобы получить текущего пользователя в шаблоне Twig (например, get_user()).
  • get_user(): он проверяет, работает ли он в тесте APP_ENV ==. Если да, то он получает экземпляр User из экземпляра UsernamePasswordToken, в противном случае он возвращает сохраненного пользователя из текущего экземпляра Twig Environment.

Следующий код должен запускаться из коробки для Symfony 4.3+, но не протестирован.


Приложение / TwigExtensions / SecurityExtension.php

Следующее расширение предоставляет get_user() внутри шаблона Twig.

<?php

namespace App\TwigExtension;

use App\Entity\User;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Twig\Environment;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class SecurityExtension extends AbstractExtension
{
    protected $currentUser;
    protected $session;
    protected $twigEnvironment;

    public function __construct(
        Environment $twigEnvironment,
        SessionInterface $session
    ) {
        $this->session = $session;
        $this->twigEnvironment = $twigEnvironment;
    }

    public function getUser(): User
    {
        if (null !== $this->currentUser) {
            return $this->currentUser;
        }

        /*
         * if env == test
         */
        if ('test' == $_SERVER['APP_ENV']) {
            $token = \unserialize($this->session->get('_security_main'));
            if ($token instanceof UsernamePasswordToken && true === $token->isAuthenticated()) {
                $this->currentUser = $token->getUser();
            }
        } else {
            /*
             * normal way
             */
            $this->currentUser = $this->twigEnvironment->getGlobals()['app']->getToken()->getUser();
        }

        return $this->currentUser;
    }

    /**
     * @return array
     */
    public function getFunctions(): array
    {
        return [
            new TwigFunction('get_user', [$this, 'getUser']),
        ];
    }
}

Тестовая среда

В следующем полном тестовом примере, как вызвать действие контроллера, которое использует Twig.

<?php

use App\Entity\User;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

class OrderControllerTest extends WebTestCase
{
    public function testEdit(): void
    {
        $client = static::createClient();

        $user = new User();
        // ... adapt it if you want

        $this->authenticateClientInstance($client, $user);

        // make the request
        $crawler = $client->request('GET', '/admin/order/');

        $response = $client->getResponse();

        // check the response
        $this->assertEquals(200, $response->getStatusCode());
    }

    protected function authenticateClientInstance(KernelBrowser $client, User $user): void
    {
        $session = $client->getContainer()->get('session');

        $token = new UsernamePasswordToken($user, null, 'main', ['ROLE_USER']);
        $session->set('_security_main', \serialize($token));
        $session->save();

        $cookie = new Cookie($session->getName(), $session->getId());
        $client->getCookieJar()->set($cookie);
    }
}

Доступ через Twig

Например:

{% set user = get_user() %}

Резюме

Решение считается не лучшим. Проблема в том, что вам необходимо использовать множество компонентов Symfony, которые могут не подходить для использования из компонентов, отличных от Symfony. Вы также можете столкнуться с проблемами, если они изменят API.

Я закрепил этот подход с помощью дальнейших тестов, чтобы убедиться, что он работает. Вы также должны сделать это, если Symfony 5.0+ что-то сломает.

Кто может быть таким добрым и объяснить причину?

k00ni 11.10.2019 09:16

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