Symfony2:保持功能还是创建服务?

时间:2014-09-26 15:52:48

标签: php class symfony helper

我的控制器中有这个方法,多次调用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();
}

4 个答案:

答案 0 :(得分:5)

首先,要知道这一点:你永远不应该,永远不会在你的控制器中拥有SQL / DQL。从不。

其次,你有几个选择,但我只想概述一个。我假设你已经定义了实体,所以让我们从基于它的选项开始。

  1. 告诉doctrine实体的存储库位于哪个

    <强>的src /项目/ ProjectBundle /实体/ Profiles.php

    /**
     * @ORM\Table()
     * @ORM\Entity(repositoryClass="Project\ProjectBundle\Entity\ProfilesRepository")
     */
    class Profiles {}
    
  2. 创建 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 ));
      }
    }
    
  3. 更新控制器中的便捷方法

    /**
     * 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;
    }
    
  4. 关于提案的一些说明

    • 我放弃了DQL,转而使用Repository finders
    • 我抛弃了行的数组表示,转而使用实体表示。只要您实际使用实体,这是更可取的。
    • 我将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');