Я использую 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);
Что мне не хватает, чтобы заставить его работать в ветке?
Это часть контроллера, в которой выполняется рендеринг. Приведенный выше код находится в тестовом модуле. code return $ this-> render ('admin / listeutilisateurs.html.twig', array ('users' => $ Users, 'roles' => $ tab, 'equipes' => $ equipes,)); code
в вашем контроллере вы передаете users в качестве параметров вашему представлению ветки, а не app. Так что app.user работать не будет. app не определен, поэтому не существует в представлении ветки тура.
Нет, переменная приложения существует в twig как глобальная переменная, и она работает. Только в тесте эта переменная (app.user) имеет значение NULL.
Зарегистрированный пользователь не установлен для сеанса, потому что serialize () не считает все необходимые поля.
ссылка: symfony.com/doc/4.0/security/…






У меня была аналогичная проблема (вход в систему правильно), что в конечном итоге решило для меня изменение способа входа в систему, это мой авторизованный клиент, и вы могли адаптировать его для своих целей. (версия 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.
Я не могу сказать вам, как настроить Twig в тестовой среде для предоставления app.user, но я сделал обходной путь, чтобы получить почти ту же функциональность.
В двух словах:
get_user()).get_user(): он проверяет, работает ли он в тесте APP_ENV ==. Если да, то он получает экземпляр User из экземпляра UsernamePasswordToken, в противном случае он возвращает сохраненного пользователя из текущего экземпляра Twig Environment.Следующий код должен запускаться из коробки для Symfony 4.3+, но не протестирован.
Следующее расширение предоставляет 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);
}
}
Например:
{% set user = get_user() %}
Решение считается не лучшим. Проблема в том, что вам необходимо использовать множество компонентов Symfony, которые могут не подходить для использования из компонентов, отличных от Symfony. Вы также можете столкнуться с проблемами, если они изменят API.
Я закрепил этот подход с помощью дальнейших тестов, чтобы убедиться, что он работает. Вы также должны сделать это, если Symfony 5.0+ что-то сломает.
Кто может быть таким добрым и объяснить причину?
скопируйте полную функцию вашего контроллера, пожалуйста ... В этом коде нет рендера.