这是我的第一篇文章,如果有任何问题,请告诉我:)。
我正在使用Symfony构建一个网站,但我目前遇到了一个问题:
我无法在包含Twig控制器{{ render(controller("AcmeCoreBundle:Auth:index")) }}
中设置(或肯定我遗漏了一些)cookie和会话变量(此控制器必须允许来自每个网站页面的“连接”)
我使用实体WhoIsIt
和表单类型WhoIsIt
<?php
namespace Acme\CoreBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Cookie;
use Acme\CoreBundle\Form\WhoIsItType;
use Acme\CoreBundle\Entity\WhoIsIt;
class AuthController extends Controller
{
public function indexAction(Request $request)
{
$who = new WhoIsIt;
$session = $this->get('session');
$response = new Response();
$form = $this->get('form.factory')->create(WhoIsItType::class, $who);
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid()) {
$whoisit = $form->getData();
//I set Cookie and Session variables
$response->headers->setCookie(new Cookie('personality', $whoisit->getPersonality(), time() + 3600 * 24 * 3));
$session->set('personality', $whoisit->getPersonality());
$response->setContent($this->render('AcmeCoreBundle:Form:Auth.html.twig', array(
'form' => $form->createView())));
return $response;
}
}
$cookies = $request->cookies;
$who->setPersonality($this->setDefault('personality', 'personality.supporter', $cookies, $session));
$form = $this->get('form.factory')->create(WhoIsItType::class, $who);
$response->setContent($this->render('AcmeCoreBundle:Form:Auth.html.twig', array(
'form' => $form->createView())));
return $response;
}
private function setDefault($element, $default, $cookies, $session)
{
//This fonction help me to define the default value of the form
if ($session->has($element))
{
return $session->get($element);
}
elseif ($cookies->has($element))
{
return $cookies->get($element);
}
return $default;
}
}
当我在Symfony Profiler中查找响应时,我得到一个POST参数:
who_is_it [ personality => personality.supporter, validate => ], _token => 9ACFB8AO53e7M5QMoqyptVhNqOj933SoMYRfKZsNRJ4 ]
并且不要获取名为personality
我想知道是否可以在SubRequest中设置cookie / session? 如果可能,我应该在代码中更改什么?
我希望你理解我的问题:)如果你没有,或者需要更多精确度,请通过评论告诉我。
感谢您的帮助。
答案 0 :(得分:0)
这是我访问我的网站时创建会话的方式:
我需要检查网站网址以找到合适的实体。希望它会对你有所帮助。
1:注册服务
<强> 的appbundle \资源\配置\ services.yml 强>
app.session_handler:
class: SalonBundle\Services\SessionHandler
arguments:
- "@doctrine"
- "@router"
tags:
- { name: kernel.event_listener, event: kernel.request, method: setSession }
首先,我将指出我使用参数@router
,但除非您需要将响应重定向到另一个网址,否则不需要。
2:创建服务
<强> 的appbundle \事件监听\ SessionHandler.php 强>
<?php
namespace AppBundle\Services;
use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\PropertyAccess\PropertyAccess;
class SessionHandler {
private $doctrine;
private $router;
public function __construct(Registry $doctrine, Router $router) {
//Make sure to type $doctrine and $router in the constructor.
//Else some methods can't be found directly, and Symfony have to do the job for you
//I guess it would make a big project a bit slower without the types
$this->doctrine=$doctrine;
$this->router=$router;
}
public function setSession(GetResponseEvent $responseEvent) {
//This function parameter call on GetResponseEvent class
//for the same reason as above.
$accessor=PropertyAccess::createPropertyAccessor();
//accessor will be used to get a parameter from an entity stored in session.
$session=$responseEvent->getRequest()->getSession();
//Fetching the existing session
$site=$session->get('site');
//Fetching object in session, return null if doesn't exists
$url=$responseEvent->getRequest()->getSchemeAndHttpHost();
//Fetching my site current base URL
if(!$site) {
//If site isn't in session
$site=$this->doctrine->getRepository('AppBundle:Site')->findOneBy(array('url'=>$url));
//Fetch object based on site URL
if($site) {
//If found, send it to session to make sure we don't keep searching for it on each page loading
$session->clear();
$session->set('site', $site);
} else {
//Else send to dashboard and go create it
if($responseEvent->getRequest()->get('_route') != 'dashboard_site') {
$responseEvent->setResponse(new RedirectResponse($this->router->generate('dashboard_site')));
}
}
} else {
//If site is in session
if($accessor->getValue($site, 'url') != $url) {
//Use of accessor to fetch url param from site object and check if object url is same as website url
$site=$this->doctrine->getRepository('AppBundle:Site')->findOneBy(array('url'=>$url));
if($site) {
$session->clear();
$session->set('site', $site);
} else {
if($responseEvent->getRequest()->get('_route') != 'dashboard_site') {
$responseEvent->setResponse(new RedirectResponse($this->router->generate('dashboard_homepage')));
}
}
}
}
}
}
我还建议阅读此question,它与当前问题配对。
答案 1 :(得分:0)
好吧,我找到了解决问题的方法。
对于我的第一个问题,我需要将原始请求作为参数:
{{ render(controller("AcmeCoreBundle:Auth:index", {'cookies': app.request.cookies})) }}
做一些其他的黑客攻击(js重定向等......)
但是,现在我使用另一个控制器来捕获&#39; POST&#39;,为此,当我创建表单时,我需要指定一个选项:
$form = $this->get('form.factory')->create(WhoIsItType::class, $who, array(
'action' => $this->generateUrl('acme_core_auth'))
);
然后我创建了正确的动作:
public function authAction (Request $request)
{
$who = new WhoIsIt;
$session = $this->get('session');
$form = $this->get('form.factory')->create(WhoIsItType::class, $who);
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid()) {
$whoisit = $form->getData();
$response = new RedirectResponse($request->headers->get('referer')); //Here I create a redirection to the current webpage
$response->headers->setCookie(new Cookie('personality', $whoisit->getPersonality(), time() + 3600 * 48)); I set a new cookie in the response header
$session->set('personality', $whoisit->getPersonality()); // I update session var
return $response;
}
}
return $this->redirectToRoute('acme_core_homepage'); //If not in post/valid I redirect to the homepage
}
最后代码是:
Acme \ CoreBundle \ Controller \ AuthController.php
<?php
namespace Acme\CoreBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Cookie;
use Acme\CoreBundle\Form\WhoIsItType;
use Acme\CoreBundle\Entity\WhoIsIt;
class AuthController extends Controller
{
public function indexAction($cookies)
{
$who = new WhoIsIt;
$session = $this->get('session');
$who->setPersonality($this->setDefault('personality', 'eventType.All', $cookies, $session));
$form = $this->get('form.factory')->create(WhoIsItType::class, $who, array(
'action' => $this->generateUrl('acme_core_auth'))
);
return $this->render('AcmeCoreBundle:Form:Auth.html.twig', array(
'form' => $form->createView()));
}
public function authAction (Request $request)
{
$who = new WhoIsIt;
$session = $this->get('session');
$form = $this->get('form.factory')->create(WhoIsItType::class, $who);
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid()) {
$whoisit = $form->getData();
$response = new RedirectResponse($request->headers->get('referer'));
$response->headers->setCookie(new Cookie('personality', $whoisit->getPersonality(), time() + 3600 * 48));
$session->set('personality', $whoisit->getPersonality());
return $response;
}
}
return $this->redirectToRoute('acme_core_homepage');
}
//This set default according to the order session>cookies>default
private function setDefault($element, $default, $cookies, $session)
{
if ($session->has($element))
{
return $session->get($element);
}
if ($cookies->has($element))
{
$default = $cookies->get($element);
}
$session->set($element, $default);
return $default;
}
}
我希望这可以帮助其他人:)