现在,让我们的用户有一个电子邮件的字段,让它能够使用邮件或者用户登录。
给User一个email
让我们开始吧。添加这个属性到User类并使用annotation方式:
1 2 3 4 5 6 7 |
// src/Yoda/UserBundle/Entity/User.php // ... /** * @ORM\Column(type="string", length=255) */ private $email; |
下一步,为属性生成getter和setter。提醒一下:我们可以使用doctrine:generate:entities命令去生成:
1 |
php app/console doctrine:generate:entities UserBundle --no-backup |
–no-backup阻止命令去创建一个备份文件。当你正在使用版本控制的时候。
下一步,更新数据库
1 |
php app/console doctrine:schema:update --force |
最后,更新fixtures,使每个用户都有一个email:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// src/Yoda/UserBundle/DataFixtures/ORM/LoadUsers.php // ... public function load(ObjectManager $manager) { // ... $user->setEmail('darth@deathstar.com'); // ... $admin->setEmail('wayne@deathstar.com'); // ... } |
重新加载并刷新数据库
1 |
php app/console doctrine:fixtures:load |
Doctrine Repositories
当有一个用户登录,我们的Security系统会使用username字段。因为我们的Security.yml之前配置过。我想改成email登录,现在我们没有办法控制email和username。如果想让它更加灵活,首先,我们需要了解一下Doctrine repositories。
找到并打开UserRepository:
1 2 3 4 5 6 7 8 |
// src/Yoda/UserBundle/Entity/UserRepository.php namespace Yoda\UserBundle\Entity; use Doctrine\ORM\EntityRepository; class UserRepository extends EntityRepository { } |
这就是一个Doctrine repository并且他是我们生成的。每个entity都有一个,通过在user类指定annotation就知道这个repository类了。
1 2 3 4 5 6 |
/** * ... * * @ORM\Entity(repositoryClass="Yoda\UserBundle\Entity\UserRepository") */ class User implements AdvancedUserInterface, Serializable |
注意,如果你不去配置repository类,Doctrine就只给你一个entity。
Repositories是放至查询逻辑的地方。我们可以创建findActiveUsers之类的方法,从数据库中查询用户的isActive字段为1的数据。
使用Repositories
实际上,我们已经在项目中使用repositories了。打开EventController,并查看indexAction方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// src/Yoda/EventBundle/Controller/EventController.php // ... public function indexAction() { $em = $this->getDoctrine()->getManager(); $entities = $em->getRepository('EventBundle:Event')->findAll(); return array( 'entities' => $entities, ); } |
基础的EntityRepository
我们调用entity管理里的getRepository方法来获得EventRepository。当我们打开这个类发现他是空的:
1 2 3 4 5 6 7 8 9 |
// src/Yoda/EventBundle/Entity/EventRepository.php namespace Yoda\EventBundle\Entity; use Doctrine\ORM\EntityRepository; class EventRepository extends EntityRepository { // nothing here... boring! } |
请问findAll方法在哪里呢?答案在基础的EntityRepository类里。如果我们打开它,你会发现很多有用的方法包括findAll().所以说每一个repository类都可以使用这些附带方法。
让getRepository返回我们自己的EventRepository,让我们来继承父类的findAll()方法,方法里只是输入die来看看我们的代码:
1 2 3 4 5 6 7 8 9 10 |
// src/Yoda/EventBundle/Entity/EventRepository.php // ... class EventRepository extends EntityRepository { public function findAll() { die('NOOOOOOOOO!!!!!!!!!!'); } } |
当我们调用这个页面,页面会给我们一个呐喊。
repositoryClass配置
现在打开Event entity。类的上面,你会看到一个@ORM\Entity注释:
1 2 3 4 5 6 7 |
// src/Yoda/EventBundle/Entity/Event.php // ... /** * @ORM\Entity(repositoryClass="Yoda\EventBundle\Entity\EventRepository") */ class Event |
这个repositoryClass是什么?是告诉Doctrine使用这个EventRepository。让我们删除这部分,看看会发生什么:
1 2 3 4 5 6 7 8 9 |
// src/Yoda/EventBundle/Entity/Event.php // ... /** * ... * * @ORM\Entity() */ class Event |
我们再刷新,就看不到呐喊声了。实际上,每个工作都很完美!我们并没有告诉Doctrine自定义的Repository,所以当我们在控制器调用getRepository时,他仅仅给我们一个实例化的EntityRepository类。
让我们还原刚才删除的部分并移除这个findAll假方法:
1 2 3 4 5 6 7 |
// src/Yoda/EventBundle/Entity/Event.php // ... /** * @ORM\Entity(repositoryClass="Yoda\EventBundle\Entity\EventRepository") */ class Event |
1 2 3 4 5 6 7 8 9 10 |
// src/Yoda/EventBundle/Entity/EventRepository.php // ... class EventRepository extends EntityRepository { public function findAll() { die('NOOOOOOOOO!!!!!!!!!!'); } } |
所以每一个entity都有一个Repository和一些辅助方法例如findAll。并且当我们的快捷方法无法满足你的工作时,你还可以自己定义自己的方法。我们所有的查询逻辑都应该放在这里-他会使你的生活更加有序。