我写了一个代码,应该收到一个参数,数字(字符串)..
我的控制器。
/**
* @Route("/activate", name="activate")
* @return \Symfony\Component\HttpFoundation\JsonResponse
*/
public function getActivate()
{
$data = array(
'number' => '123456'
);
return $this->success($data);
}
我不知道在我的服务中编写查询函数是一种更好的方法,而不是将其调用到我的控制器,或者这是正确的方法。如果查询更好,那么我应该如何开始?像:
public function getNumber($data)
{
$number = $this->getRepository()
->createQueryBuilder('n')
->select('n')
->where('n.data = :data').....
答案 0 :(得分:1)
不,将查询置于服务范围内并不好。
一般来说,遵循以下三条规则:
1)不要在控制器中放置任何业务逻辑和查询。控制器只应调用服务功能
2)从第一点开始,服务应该与存储库进行通信。
3)查询应该位于存储库中。
So Controller-> Service-> Repository
请记住,有时从控制器调用一些存储库函数可能很有用(如果你不需要使用存储库函数的结果进行额外的工作,你可以直接返回它)
我的工作方式示例。
在以下示例中实现此目的
1)使用Dependency Injection获取控制器中的服务 2)称之为
<?php
namespace AppBundle\Controller;
use AppBundle\Service\MapService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Class MainPageController
* @package AppBundle\Controller
*/
class MainPageController extends Controller
{
/**
* @var EntityManagerInterface
*/
private $em;
/**
* @var MapService
*/
private $mapService;
/**
* MainPageController constructor.
* @param EntityManagerInterface $em
* @param MapService $ms
*/
public function __construct(EntityManagerInterface $em, MapService $ms)
{
$this->em = $em;
$this->mapService = $ms;
}
/**
* @param Request $request
* @return Response
*/
public function indexAction(Request $request)
{
$mapData = $this->mapService->prepareMapInformation();
return $this->render('@App/pages/index.html.twig', [
'mapData' => $mapData,
]);
}
}
第二个例子 - 服务。
1)注入您需要的存储库或在服务中注入实体管理器并通过它获取存储库 2)调用所需的rep函数 3)做一些工作并返回
public function prepareMapInformation(): array
{
$result = [];
$activeCities = $this->cityRepository->getAllActiveCities();
$companyInformation = $this->companyRepository
->getInformationForMap();
foreach ($activeCities as $oneCity) {
/** @var City $oneCity */
$push = [];
$push['latitude'] = $oneCity->getLatitude();
$push['longitude'] = $oneCity->getLongitude();
$push['nameLocation'] = $this->determineNameLocation($oneCity-
>getNameLocation());
$push['companies'] = $this->getCompanies($companyInformation,
$oneCity);
if (!empty($push['companies'])) {
$result[$oneCity->getName()] = $push;
}
}
return $result;
}
第三个例子 - 存储库。
<?php
namespace AppBundle\Repository;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr\Join;
/**
* Class CityRepository
* @package AppBundle\Repository
*/
class CityRepository extends EntityRepository
{
/**
* @return array
*/
public function getAllCitiesAssoc(): array
{
return $this->_em->createQueryBuilder()
->select('c')
->from('AppBundle:City', 'c', 'c.name') // third param is index by (it creates assoc array with keys of city names)
->getQuery()
->getResult();
}
/**
* @return array
*/
public function getAllActiveCities(): array
{
return $this->findBy(['active' => 1]);
}
}
编辑@Alister Bulman回答。
是的,你可以使用ParamConverter,如果你不需要你的实体的额外逻辑,只是不想返回它的数据来查看。但是这种情况不太好,你需要对数据做额外的逻辑,因为那时你必须在控制器中执行它或者将实体传递给服务。
答案 1 :(得分:1)
@revengeance的答案是可靠的,但我还要补充一点,它还取决于$ number的来源。如果它是静态的,就像你的例子一样,那么将它传递给服务是完全合理的。
但是,如果它来自URL参数:
ParamConverter
然后您可以使用/**
* @Route("/activate/{id}", name="activate")
* @return \Symfony\Component\HttpFoundation\JsonResponse
*/
public function activateAction(Post $post)
{
// other security checks - do we have permission to activate this?
// ....
return $this->activatePost($post); // do something to turn on the entity
}
public function activatePost(Post $post)
{
$post->setActive(true);
$post->persist(true);
return $post;
}
键入提示实体,并且已经存在一对自动执行某些操作(您也可以编写自己的其他任务)。
then
这里,Post实体通过它的主键 - post.id找到 - 并作为对象完全形成传递给控制器动作,在那里可以使用它。如果没有这样的项目,框架会为您抛出404-Not Found错误。