我的控制器中有这个方法,多次调用indexAction()。我应该保持原样,还是应该为它和其他可重用方法创建Helper类(服务),因为在这种情况下我可以避免传递诸如$em
之类的参数?我无法理解服务的背景以及何时使用它们很舒服。
public function getProfile($em, $username, $password) {
$dql = $em->createQuery('SELECT Profiles FROM ProjectProjectBundle:Profiles AS Profiles WHERE Profiles.email = :email AND Profiles.password = :password')
->setParameters(array(
'email' => $username,
'password' => $password
));
return $dql->getArrayResult();
}
答案 0 :(得分:5)
首先,要知道这一点:你永远不应该,永远不会在你的控制器中拥有SQL / DQL。从不。
其次,你有几个选择,但我只想概述一个。我假设你已经定义了实体,所以让我们从基于它的选项开始。
告诉doctrine实体的存储库位于哪个
<强>的src /项目/ ProjectBundle /实体/ Profiles.php 强>
/**
* @ORM\Table()
* @ORM\Entity(repositoryClass="Project\ProjectBundle\Entity\ProfilesRepository")
*/
class Profiles {}
创建 ProfilesRepository 类并使用自定义查找器
<强>的src /项目/ ProjectBundle /实体/ ProfilesRepository.php 强>
namespace Project\ProjectBundle\Entity;
use Doctrine\ORM\EntityRepository;
class ProfilesRepository extends EntityRepository
{
/**
* Find a Profiles entity with the given credentials
*
* @return \Project\ProjectBundle\Entity\Profiles|null
*/
public function findByCredentials($username, $password)
{
return $this->findBy(array('email' => $username, 'password' => $password ));
}
}
更新控制器中的便捷方法
/**
* Fetch a user's profile
*
* @return \Project\ProjectBundle\Entity\Profiles
*/
private function fetchProfile($username, $password)
{
try { // Exception-safe code is good!
$profilesRepo = $this->getDoctrine()->getEntityRepository('ProjectProjectBundle:Profiles');
return $profilesRepo->findByCredentials($username, $password);
}
catch (\Exception $e)
{
// Do whatever you want with exceptions
}
return null;
}
关于提案的一些说明
getProfile()
重命名为fetchProfile()
,因为它更好地描述了该方法的功能。我也将其设为私有,因为这只是一种良好的安全编码习惯。答案 1 :(得分:1)
使用EntityRepositories
// src/YourProjectName/BundleName/Entity/ProfileRepository.php
<?php
namespace YourProjectName\BundleName\Entity;
use Doctrine\ORM\EntityRepository;
class ProfileRepository extends EntityRepository
{
public function myGetProfile($username, $password)
{
$dql = $this->getEntityManager()->createQuery('SELECT Profiles FROM ProjectProjectBundle:Profiles AS Profiles WHERE Profiles.email = :email AND Profiles.password = :password')
->setParameters(array(
'email' => $username,
'password' => $password
));
return $dql->getArrayResult();
}
}
然后从任何控制器中你可以做到
$repository = $em->getRepository('YourBundle:Profile');
$repository->myGetProfile('username', 'password');
答案 2 :(得分:0)
我会使用实体重新定位(刚刚发布了这个并实现了Isaac刚刚发布所以请参考)
/ **存储库类** /
<?php
namespace YourProjectName\BundleName\Entity;
use Doctrine\ORM\EntityRepository;
class ProfileRepository extends EntityRepository {
public function myGetProfile($username, $password) {
return $this->getEntityManager()
->createQueryBuilder('p')
->from('ProjectProjectBundle:Profiles','p')
->where('p.email = :email')
->andWhere('p.password = :password')
->setParameters(['email' => $email, 'password' => $password])
->getQuery()
->getArrayResult();
}
}
/** In a controller **/
$results = $em->getRepository('ABundle:Profile')->myGetProfile($username, $password);
另外,不要忘记将此存储库添加到您的enity类中,否则它将无法正常工作
如果您有一个被调用的主函数,我还建议使用存储库方法使用@ParamConverter将其缩短。
答案 3 :(得分:0)
我要做的第一个区别是你将Helper Classes和Services分组为同一个东西。您可能有一个全局帮助器类来格式化字符串或使用文件路径,但这不会提供良好的服务。
重新阅读http://symfony.com/doc/current/book/service_container.html提供了与Mailer服务的良好比喻。也许在您的情况下,您需要Profiler service
来管理您的Profile objects
。
$profiler = $this->get('profile_manager');
$current_profile = $profiler->getProfile();
$other_profile = $profiler->getProfile('username','password');