【问题标题】:Migrating to FOSUserBundle迁移到 FOSUserBundle
【发布时间】:2013-06-27 22:08:00
【问题描述】:

到目前为止,我们一直在 Symfony2 中使用自定义身份验证系统。我们现在正在扩展我们的功能,它已经到了 FOSUserBundle 将节省时间的阶段。

我已经用 Composer 安装了 FOSUserBundle 并将其添加到 appKernel.php。

关于实体,由于已经有一个 User 实体,我刚刚删除了 FOS 包中 AbstractUser 实体已经具有的字段并对其进行了扩展:

use FOS\UserBundle\Entity\User as BaseUser;
...
class User extends BaseUser

我去用教义更新架构:schema:update --force 并得到以下内容:

  [Doctrine\DBAL\Schema\SchemaException]                 
  The table with name 'lifemirror.user' already exists. 

嗯,是的,用户表已经存在,但该命令应该更新它。我更改了用户实体中的表名并执行--dump-sql 以查看发生了什么,它似乎保留了表但删除了结构:

ALTER TABLE user DROP email, DROP username, DROP password, DROP invitation_code, DROP picture_file;

所以我认为 User 实体可能正在其他地方使用,但我不确定在哪里。

在 Pazi 的建议下,我安装了学说迁移包并尝试创建一个迁移。它生成以下内容

/**
 * Auto-generated Migration: Please modify to your need!
 */
class Version20130701134939 extends AbstractMigration
{
    public function up(Schema $schema)
    {
        // this up() migration is autogenerated, please modify it to your needs
        $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");

        $this->addSql("CREATE TABLE film_today (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) DEFAULT NULL, description LONGTEXT DEFAULT NULL, id_user INT DEFAULT NULL, suggest_date DATE DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHA$
        $this->addSql("CREATE TABLE user1 (id INT AUTO_INCREMENT NOT NULL, firstname VARCHAR(255) DEFAULT NULL, lastname VARCHAR(255) DEFAULT NULL, country VARCHAR(255) DEFAULT NULL, birthdate DATE DEFAULT NULL, PRIMARY KEY(id)) DEFAU$
        $this->addSql("DROP TABLE cinema");
        $this->addSql("DROP INDEX id_user ON session");
        $this->addSql("ALTER TABLE job CHANGE id id INT AUTO_INCREMENT NOT NULL, CHANGE cinema cinema INT NOT NULL, CHANGE name name LONGTEXT NOT NULL, CHANGE status status VARCHAR(10) NOT NULL");
        $this->addSql("ALTER TABLE film_location CHANGE screening_description screening_description VARCHAR(255) DEFAULT NULL");
        $this->addSql("ALTER TABLE report_film CHANGE id_user id_user INT DEFAULT NULL, CHANGE id_film id_film INT DEFAULT NULL");
        $this->addSql("DROP INDEX email ON user");
        $this->addSql("ALTER TABLE user DROP email, DROP username, DROP password, DROP invitation_code, DROP picture_file");
        $this->addSql("ALTER TABLE film_today_vote CHANGE id id INT AUTO_INCREMENT NOT NULL, CHANGE id_film_today id_film_today INT DEFAULT NULL, CHANGE id_user id_user INT DEFAULT NULL, CHANGE vote_date vote_date DATE DEFAULT NULL");
        $this->addSql("ALTER TABLE video CHANGE timestamp timestamp DATETIME NOT NULL");
    }

    public function down(Schema $schema)
    {
        // this down() migration is autogenerated, please modify it to your needs
        $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");

        $this->addSql("CREATE TABLE cinema (id INT AUTO_INCREMENT NOT NULL, username LONGTEXT NOT NULL, usernameCanonical LONGTEXT NOT NULL, email LONGTEXT NOT NULL, password LONGTEXT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET u$
        $this->addSql("DROP TABLE film_today");
        $this->addSql("DROP TABLE user1");
        $this->addSql("ALTER TABLE film_location CHANGE screening_description screening_description LONGTEXT NOT NULL");
        $this->addSql("ALTER TABLE film_today_vote CHANGE id id INT NOT NULL, CHANGE id_film_today id_film_today INT NOT NULL, CHANGE id_user id_user INT NOT NULL, CHANGE vote_date vote_date DATETIME NOT NULL");
        $this->addSql("ALTER TABLE job CHANGE id id INT UNSIGNED AUTO_INCREMENT NOT NULL, CHANGE cinema cinema INT UNSIGNED NOT NULL, CHANGE name name LONGTEXT DEFAULT NULL, CHANGE status status VARCHAR(255) NOT NULL");
        $this->addSql("ALTER TABLE report_film CHANGE id_user id_user INT NOT NULL, CHANGE id_film id_film INT NOT NULL");
        $this->addSql("CREATE INDEX id_user ON session (id_user)");
        $this->addSql("ALTER TABLE user ADD email VARCHAR(255) DEFAULT NULL, ADD username VARCHAR(255) DEFAULT NULL, ADD password LONGTEXT DEFAULT NULL, ADD invitation_code VARCHAR(255) DEFAULT NULL, ADD picture_file LONGTEXT DEFAULT $
        $this->addSql("CREATE UNIQUE INDEX email ON user (email)");
        $this->addSql("ALTER TABLE video CHANGE timestamp timestamp DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL");
    }
}

我认为这突出了同样的问题 - 用户实体没有被正确扩展。

【问题讨论】:

    标签: php symfony fosuserbundle


    【解决方案1】:

    这就是为什么不建议将doctrine:schema:update 用于生产的原因。有一种更好更强大的方法:DoctrineMigrationsBundle。由于您的数据库发生了重大变化(即您的某些列只需要重命名,有些是新的,它们需要填充等)您应该自己处理它而不是自动处理它。通过 Doctrine Migrations,您可以以稳健的方式完成此步骤。您可以尝试从差异自动生成迁移类,但最后我认为您必须根据需要修改生成的类。我已经从一个全新的 symfony 安装中为您创建了一个迁移类,并使用了一个扩展 FOSUserBundle 基类的裸用户类(只有 id)。

    <?php
    // app/DoctrineMigrations/Version20130701120836.php
    
    namespace Application\Migrations;
    
    use Doctrine\DBAL\Migrations\AbstractMigration,
        Doctrine\DBAL\Schema\Schema;
    
    /**
     * Auto-generated Migration: Please modify to your need!
     */
    class Version20130701120836 extends AbstractMigration
    {
        public function up(Schema $schema)
        {
            // this up() migration is autogenerated, please modify it to your needs
            $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
    
            $this->addSql("CREATE TABLE fos_user (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(255) NOT NULL, username_canonical VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, email_canonical VARCHAR(255) NOT NULL, enabled TINYINT(1) NOT NULL, salt VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, last_login DATETIME DEFAULT NULL, locked TINYINT(1) NOT NULL, expired TINYINT(1) NOT NULL, expires_at DATETIME DEFAULT NULL, confirmation_token VARCHAR(255) DEFAULT NULL, password_requested_at DATETIME DEFAULT NULL, roles LONGTEXT NOT NULL COMMENT '(DC2Type:array)', credentials_expired TINYINT(1) NOT NULL, credentials_expire_at DATETIME DEFAULT NULL, UNIQUE INDEX UNIQ_957A647992FC23A8 (username_canonical), UNIQUE INDEX UNIQ_957A6479A0D96FBF (email_canonical), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB");
    
        }
    
        public function down(Schema $schema)
        {
            // this down() migration is autogenerated, please modify it to your needs
            $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
    
            $this->addSql("DROP TABLE fos_user");
        }
    }
    

    现在您可以将 CREATE 语句修改为更改表,修改现有列并添加新列。然后,您需要第二条语句来更新这两个规范字段。它们只是原始列的小写版本。它们对于登录很重要。

    与文档不同,如果您想保持最低稳定性以保持稳定,您需要在 composer.json 中使用这两行来安装它。

        "doctrine/migrations": "*@alpha",
        "doctrine/doctrine-migrations-bundle": "dev-master"
    

    【讨论】:

    • 谢谢你,但为什么学说:模式:更新不特别适合?你的脚本也不会删除表格的内容吗?
    • 因为它会生成一些自动 sql 语句,并且在像你这样的情况下,这些语句做错了。迁移很方便,因为您可以控制完成的步骤。我发布的类是 FOSUserBundle 基类需要的所有列的示例。您必须修改该语句以适应 ALTER TABLE 来修改您现有的用户表。
    • 那么就没有办法自动从实体生成模式了吗?
    • 确实,您阅读过链接的文档吗?有doctrine:migrations:diff 命令,它会根据实体映射和数据库中架构之间的差异自动生成一个迁移类(如doctrine:schema:update)。但它不会自动执行。您应该查看生成的类,如果出现故障,根据需要对其进行修改(并非每个自动生成的语句都是完美的),然后调用doctrine:migrations:migrate 命令。一个 3 个步骤的过程。
    • 好的,试一试。不幸的是,它的作用与--dump-sql 相同,即没有输入 FOSUserBundle 'User' 字段,尽管实体扩展了 FOSUserBundle 'User' 实体。我已经编辑了我的问题以突出问题。
    【解决方案2】:

    好的,已修复。我有一个扩展用户实体的注册实体,我在复制/粘贴后留下了一些“用户”注释,所以它认为有重复。我现在可以正常方式更新数据库了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-28
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      • 1970-01-01
      • 2012-02-01
      • 2011-01-18
      相关资源
      最近更新 更多