gol*_*ife 5 php dependency-injection symfony doctrine-orm
我是Symfony 3中的新手,我想避免控制器中的业务逻辑.到目前为止我所做的是:
<?php
namespace RestBundle\Controller;
use RestBundle\Entity\Attribute;
use RestBundle\Entity\DistributorProduct;
use RestBundle\Entity\AttributeValue;
use RestBundle\Entity\ProductToImage;
use Symfony\Component\HttpFoundation\Request;
use RestBundle\Entity\Product;
use FOS\RestBundle\Controller\FOSRestController;
/**
* Product controller.
*
*/
class ProductController extends FOSRestController
{
/**
* Creates a new Product entity.
*
*/
public function createProductAction(Request $request)
{
// Doctrine Manager
$em = $this->getDoctrine()->getManager();
// todo: get the logged in distributor object
$distributor = $em->getRepository('RestBundle:Distributor')->find(1);
// Main Product
$product = new Product();
$product->setEan($request->get('ean'));
$product->setAsin($request->get('asin'));
$em->persist($product);
// New Distributor Product
$distributorProduct = new DistributorProduct();
$distributorProduct->setDTitle($request->get('title'));
$distributorProduct->setDDescription($request->get('description'));
$distributorProduct->setDPrice($request->get('price'));
$distributorProduct->setDProductId($request->get('product_id'));
$distributorProduct->setDStock($request->get('stock'));
// Relate this distributorProduct to the distributor
$distributorProduct->setDistributor($distributor);
// Relate this distributorProduct to the product
$distributorProduct->setProduct($product);
$em->persist($distributorProduct);
// Save it
$em->flush();
$response = $em->getRepository('RestBundle:Product')->find($product->getUuid());
return array('product' => $response);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我知道这不是好代码,因为所有业务逻辑都在控制器中.
但是我如何以及在哪里可以将这些代码(将请求设置为模型,持久化并与规则等同化)到服务中或使用依赖注入?或者为此目的的服务不是正确的方式?
我知道这个页面和教程http://symfony.com/doc/current/best_practices/business-logic.html 但我不清楚在哪里放置CRUD操作.使用所有相关实体保存整个项目的一项服务?并使用Symfony\Component\HttpFoundation\Request; 在服务?那么把整个控制器代码放在我收到请求的地方并将模型分配到服务中?谢谢
更新2:我在一篇文章中扩展了这个答案.一定要检查一下!
更新:使用Symfony 3.3(2017年5月)与PSR-4服务自动发现和PHP 7.1类型.
我将向您展示我如何在公司中进行控制器存储库解耦.
有两个简单的规则:
new在控制器中没有(静态,非DI方法)(现在还有Sniff)注意:这是伪代码,我没试过,但逻辑应该很容易理解.如果更改太多,只需检查步骤3和4.
我们解耦创建和保存过程.对于这两个实体.这将引导我们提供4项服务:
# app/config/services.yml
services:
_defaults:
autowire: true
App\Domain\:
resource: ../../App/Domain
App\Repository\:
resource: ../../App/Repository
Run Code Online (Sandbox Code Playgroud)
// ProductFactory.php
namespace App\Domain\Product;
final class ProductFactory
{
public function createFromRequest(Request $request): Product
{
$product = new Product();
$product->setEan($request->get('ean'));
$product->setAsin($request->get('asin'));
return $product;
}
}
Run Code Online (Sandbox Code Playgroud)
// DistributorProductFactory.php
namespace App\Domain\Product;
final class DistributorProductFactory
{
public function createFromRequestProductAndDistributor(
Request $request,
Product $product,
Distributor $distributor
): DistributorProduct {
$distributorProduct = new DistributorProduct();
$distributorProduct->setDTitle($request->get('title'));
$distributorProduct->setDDescription($request->get('description'));
$distributorProduct->setDPrice($request->get('price'));
$distributorProduct->setDProductId($request->get('product_id'));
$distributorProduct->setDStock($request->get('stock'));
// Relate this distributorProduct to the product
$distributorProduct->setProduct($product);
// Relate this distributorProduct to the product
$distributorProduct->setDistributor($distributor);
return $distributorProduct;
}
}
Run Code Online (Sandbox Code Playgroud)
// ProductRepository.php
namespace App\Repository;
use RestBundle\Entity\Product;
use Doctrine\ORM\EntityManagerInterface;
final class ProductRepository
{
/**
* @var EntityManagerInterface
*/
private $entityManager;
public funtion __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function save(Product $product): void
{
$this->entityManager->persist($product);
$this->entityManager->flush();
}
}
Run Code Online (Sandbox Code Playgroud)
// DistributorProductRepository.php
namespace App\Repository;
use RestBundle\Entity\DistributorProduct;
use Doctrine\ORM\EntityManagerInterface;
final class DistributorProductRepository
{
/**
* @var EntityManagerInterface
*/
private $entityManager;
public funtion __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function save(DistributorProduct $distributorProduct): void
{
$this->entityManager->persist($distributorProduct);
$this->entityManager->flush();
}
}
Run Code Online (Sandbox Code Playgroud)
namespace RestBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use FOS\RestBundle\Controller\FOSRestController;
final class ProductController extends FOSRestController
{
// get here dependencies via constructor
public function createProductAction(Request $request): array
{
// todo: get the logged in distributor object
$distributor = $em->getRepository('RestBundle:Distributor')->find(1);
$product = $this->productFactory->createFromRequest($request);
$distributorProduct = $this->distributorProductFactory->createFromRequestProductAndDistributor(
$request,
$product,
$distributor
);
$this->productRepository->save($product);
$this->distributorProductRepository->save($product);
return [
'product' => $product
];
}
}
Run Code Online (Sandbox Code Playgroud)
就这样!