0

全部!有人可以帮我解决 Symfony2 的问题吗?我想将有关用户登录 [成功、失败] 和注销 [成功] 的所有事件(请求相关数据)保存到数据库中。下面的实现和异常。

这是 config.yml

services:

login_success_handler:
    class:  Boomster\LibraryBundle\Handler\LoginSuccessHandler
    arguments:  [@security.context, @doctrine]

login_failure_handler:
    class:  Boomster\LibraryBundle\Handler\LoginFailureHandler
    arguments:  [@security.context, @doctrine]

logout_success_handler:
    class:  Boomster\LibraryBundle\Handler\LogoutSuccessHandler
    arguments:  [@security.context, @doctrine]

这是防火墙security.yml

firewalls:
    secured_area:
        pattern: ^/.*
        form_login:
            check_path: auth_check
            login_path: auth_login
            success_handler: login_success_handler
            failure_handler: login_failure_handler
        logout:
            path:   auth_logout
            target: site_index
            success_handler: logout_success_handler
        anonymous: ~

这是 LoginSuccessHandler 处理程序:

<?php

namespace Boomster\LibraryBundle\Handler;

use Boomster\LibraryBundle\Entity\Visit;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Doctrine\Bundle\DoctrineBundle\Registry as Doctrine;

class LoginSuccessHandler implements AuthenticationSuccessHandlerInterface
{
private $doctrine;
private $securityContext;

public function __construct(SecurityContext $securityContext, Doctrine $doctrine)
{
    $this->doctrine = $doctrine;
    $this->securityContext = $securityContext;
}

public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
    $session = $request->getSession();

    if ($session->has('referer')) {
        if ($session->get('referer') !== null && $session->get('referer') !== '')
        {
            $response = new RedirectResponse($session->get('referer'));
        } else {
            $response = new RedirectResponse($request->getBasePath() . '/');
        }
    } else {
        $response = new RedirectResponse($request->getBasePath() . '/');
    }

    if ($request->isXmlHttpRequest() || $request->request->get('_format') === 'json') {
        $response = new Response(json_encode(array('status' => 'success')));
        $response->headers->set('Content-Type', 'application/json');
    }


    $em = $this->doctrine->getManager();
    $repository = $em->getRepository('BoomsterLibraryBundle:User');
    $user = $repository->findOneByUsername($token->getUsername());

    $visit = new Visit();
    $visit->setFormat($request->request->get('_format', 'none'));
    $visit->setClientIp($request->request->get('client-ip', '0.0.0.0'));
    $visit->setStatus(Visit::SUCCESS);

    // ...
    $user->addVisit($visit);

    $em->persist($visit);
    $em->flush();

    return $response;
}
}

最后,实体之间的关系:Entity User

class User .....
/**
 * @var \Doctrine\Common\Collections\Collection
 *
 * @ORM\OneToMany(targetEntity="Visit", mappedBy="user", cascade={"remove"})
 *
 * @var ArrayCollection $visits;
 **/
private $visits;

/**
 * @param Visit $visit
 * @return User $user
 */
public function addVisit($visit)
{
    $this->visits[] = $visit;
    $visit->setUser($this);

    return $this;
}

/**
 * Remove visits
 *
 * @param Visit $visit
 * @return void param \Boomster\LibraryBundle\Entity\Visit $visits
 */
public function removeVisit(Visit $visit)
{
    $this->visits->removeElement($visit);
}

/**
 * @return \Doctrine\Common\Collections\Collection
 */
public function getVisits()
{
    return $this->visits->toArray();
}
}

实体访问

class Visit ...
/**
 * @var User $user;
 *
 * @ORM\ManyToOne(targetEntity="User", inversedBy="visits")
 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
 *
 */
private $user;

// getters & setters for the $user skipped

所以,例外:

执行 'UPDATE users SET password = ?, salt = ?, updated = ? 哪里 id = ?带参数 [null,null,“2013-10-18 16:56:48”,“141736”]:

SQLSTATE [23502]:非空违规:7 错误:“密码”列中的空值违反非空约束

据我了解,Doctrine 试图更新用户表,但字段密码和盐为空......

这是日志文件:

[2013-10-18 20:47:32] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\Security\Http\Firewall::onKernelRequest". [] []
[2013-10-18 20:47:32] doctrine.DEBUG: SELECT t0.id AS id1, t0.nickname AS nickname2, t0.username AS username3, t0.password AS password4, t0.email AS email5, t0.gender AS gender6, t0.website AS website7, t0.skype AS skype8, t0.salt AS salt9, t0.code AS code10, t0.status AS status11, t0.created AS created12, t0.updated AS updated13, t0.expired AS expired14 FROM users t0 WHERE t0.username = ? LIMIT 1 ["admin"] []
[2013-10-18 20:47:32] doctrine.DEBUG: SELECT t0.id AS id1, t0.name AS name2, t0.role AS role3, t0.created AS created4, t0.updated AS updated5 FROM roles t0 INNER JOIN role_user ON t0.id = role_user.role_id WHERE role_user.user_id = ? ["141736"] []
[2013-10-18 20:47:32] security.INFO: User "admin" has been authenticated successfully [] []
[2013-10-18 20:47:32] doctrine.DEBUG: SELECT t0.id AS id1, t0.nickname AS nickname2, t0.username AS username3, t0.password AS password4, t0.email AS email5, t0.gender AS gender6, t0.website AS website7, t0.skype AS skype8, t0.salt AS salt9, t0.code AS code10, t0.status AS status11, t0.created AS created12, t0.updated AS updated13, t0.expired AS expired14 FROM users t0 WHERE t0.username = ? LIMIT 1 ["admin"] []
[2013-10-18 20:47:32] doctrine.DEBUG: SELECT NEXTVAL('seq_visit') [] []
[2013-10-18 20:47:32] doctrine.DEBUG: "START TRANSACTION" [] []
[2013-10-18 20:47:32] doctrine.DEBUG: INSERT INTO visit (id, format, client_ip, status, created, user_id) VALUES (?, ?, ?, ?, ?, ?) {"1":18,"2":"none","3":"0.0.0.0","4":"SUCCESS","5":"2013-10-18 20:47:32","6":"141736"} []
[2013-10-18 20:47:32] doctrine.DEBUG: UPDATE users SET password = ?, salt = ?, updated = ? WHERE id = ? ["NULL","NULL","2013-10-18 20:47:32","141736"] []
[2013-10-18 20:47:32] doctrine.DEBUG: "ROLLBACK" [] []
[2013-10-18 20:47:32] event.DEBUG: Notified event "kernel.exception" to listener "Symfony\Component\Security\Http\Firewall\ExceptionListener::onKernelException". [] []
[2013-10-18 20:47:32] event.DEBUG: Notified event "kernel.exception" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelException". [] []
[2013-10-18 20:47:32] event.DEBUG: Notified event "kernel.exception" to listener "Symfony\Component\HttpKernel\EventListener\ExceptionListener::onKernelException". [] []
[2013-10-18 20:47:32] request.CRITICAL: Uncaught PHP Exception Doctrine\DBAL\DBALException: "An exception occurred while executing 'UPDATE users SET password = ?, salt = ?, updated = ? WHERE id = ?' with params [null, null, "2013-10-18 20:47:32", "141736"]:

SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column "password" violates not-null constraint" at /data/system/webhosts/boomster.lo/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php line 47 {"exception":"[object] (Doctrine\\DBAL\\DBALException: An exception occurred while executing 'UPDATE users SET password = ?, salt = ?, updated = ? WHERE id = ?' with params [null, null, \"2013-10-18 20:47:32\", \"141736\"]:\n\nSQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column \"password\" violates not-null constraint at /data/system/webhosts/boomster.lo/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php:47, PDOException: SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column \"password\" violates not-null constraint at /data/system/webhosts/boomster.lo/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:784)"} []

关键点:

[2013-10-18 20:47:32] doctrine.DEBUG: UPDATE users SET password = ?, salt = ?, updated = ? WHERE id = ? ["NULL","NULL","2013-10-18 20:47:32","141736"] []

…………???

此外,我将 $user->addVisit() 更改为 $visit->setUser($user)。没有任何改变......这是详细的日志:

[2013-10-18 21:11:33] doctrine.DEBUG: SELECT t0.id AS id1, t0.nickname AS nickname2, t0.username AS username3, t0.password AS password4, t0.email AS email5, t0.gender AS gender6, t0.website AS website7, t0.skype AS skype8, t0.salt AS salt9, t0.code AS code10, t0.status AS status11, t0.created AS created12, t0.updated AS updated13, t0.expired AS expired14 FROM users t0 WHERE t0.username = ? LIMIT 1 ["admin"] []
[2013-10-18 21:11:33] doctrine.DEBUG: SELECT t0.id AS id1, t0.name AS name2, t0.role AS role3, t0.created AS created4, t0.updated AS updated5 FROM roles t0 INNER JOIN role_user ON t0.id = role_user.role_id WHERE role_user.user_id = ? ["141736"] []
[2013-10-18 21:11:33] security.INFO: User "admin" has been authenticated successfully [] []
[2013-10-18 21:11:33] doctrine.DEBUG: SELECT t0.id AS id1, t0.nickname AS nickname2, t0.username AS username3, t0.password AS password4, t0.email AS email5, t0.gender AS gender6, t0.website AS website7, t0.skype AS skype8, t0.salt AS salt9, t0.code AS code10, t0.status AS status11, t0.created AS created12, t0.updated AS updated13, t0.expired AS expired14 FROM users t0 WHERE t0.username = ? LIMIT 1 ["admin"] []
[2013-10-18 21:11:33] doctrine.DEBUG: SELECT NEXTVAL('seq_visit') [] []
[2013-10-18 21:11:33] doctrine.DEBUG: "START TRANSACTION" [] []
[2013-10-18 21:11:33] doctrine.DEBUG: INSERT INTO visit (id, format, client_ip, status, created, user_id) VALUES (?, ?, ?, ?, ?, ?) {"1":19,"2":"none","3":"0.0.0.0","4":"SUCCESS","5":"2013-10-18 21:11:33","6":"141736"} []
[2013-10-18 21:11:33] doctrine.DEBUG: UPDATE users SET password = ?, salt = ?, updated = ? WHERE id = ? ["NULL","NULL","2013-10-18 21:11:33","141736"] []
[2013-10-18 21:11:33] doctrine.DEBUG: "ROLLBACK" [] []
[2013-10-18 21:11:33] event.DEBUG: Notified event "kernel.exception" to listener "Symfony\Component\Security\Http\Firewall\ExceptionListener::onKernelException". [] []
[2013-10-18 21:11:33] event.DEBUG: Notified event "kernel.exception" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelException". [] []
[2013-10-18 21:11:33] event.DEBUG: Notified event "kernel.exception" to listener "Symfony\Component\HttpKernel\EventListener\ExceptionListener::onKernelException". [] []
[2013-10-18 21:11:33] request.CRITICAL: Uncaught PHP Exception Doctrine\DBAL\DBALException: "An exception occurred while executing 'UPDATE users SET password = ?, salt = ?, updated = ? WHERE id = ?' with params [null, null, "2013-10-18 21:11:33", "141736"]:

SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column "password" violates not-null constraint" at /data/system/webhosts/boomster.lo/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php line 47 {"exception":"[object] (Doctrine\\DBAL\\DBALException: An exception occurred while executing 'UPDATE users SET password = ?, salt = ?, updated = ? WHERE id = ?' with params [null, null, \"2013-10-18 21:11:33\", \"141736\"]:\n\nSQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column \"password\" violates not-null constraint at /data/system/webhosts/boomster.lo/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php:47, PDOException: SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column \"password\" violates not-null constraint at /data/system/webhosts/boomster.lo/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:784)"} []

不明白发生了什么......想法?

4

1 回答 1

1

大家好,非常感谢 joe42 和 Thomas Potaire。

实际上,这个异常的关键点在于 UserInterface/AdvancedUserInterface 方法的实现,如下所述……

class User implements AdvancedUserInterface .... {
/**
 * Removes sensitive data from the user.
 *
 * This is important if, at any given point, sensitive information like
 * the plain-text password is stored on this object.
 */
public function eraseCredentials()
{
    //$this->salt = $this->password = null;
}

当我评论了eraseCredentials方法的行时,问题已经解决了......无论如何,为什么Doctrine2即使在这种情况下也试图更新用户表:

    $em = $this->doctrine->getManager();
    //$repository = $em->getRepository('BoomsterLibraryBundle:User');
    //$user = $repository->findOneByUsername($token->getUsername());

    $visit = new Visit();
    $visit->setFormat($request->request->get('_format', 'none'));
    $visit->setClientIp($request->request->get('client-ip', '0.0.0.0'));
    $visit->setStatus(Visit::SUCCESS);
    $visit->setUser($token->getUser());

    $em->persist($visit);
    $em->flush();

再次感谢大家的进步和想法!

于 2013-10-19T05:03:43.897 回答