Symfony 3 - 外包控制器代码到服务层 [英] Symfony 3 - Outsourcing Controller Code into Service Layer
问题描述
我的控制器中的业务逻辑。
到目前为止我所做的是这样的:
<?php
命名空间RestBundle\Controller;
使用RestBundle\Entity\Attribute;
使用RestBundle\Entity\DistributorProduct;
使用RestBundle\Entity\AttributeValue;
使用RestBundle\Entity\ProductToImage;
使用Symfony\Component\HttpFoundation\Request;
使用RestBundle\Entity\Product;
使用FOS\RestBundle\Controller\FOSRestController;
/ **
*产品控制器。
*
* /
class ProductController extends FOSRestController
{
/ **
*创建一个新的Product实体。
*
* /
public function createProductAction(Request $ request)
{
// Doctrine Manager
$ em = $ this-> getDoctrine( ) - > getManager();
// todo:获取登录的分发对象
$ distributor = $ em-> getRepository('RestBundle:Distributor') - > find(1);
//主要产品
$ product = new Product();
$ product-> setEan($ request-> get('ean'));
$ product-> setAsin($ request-> get('asin'));
$ em-> persist($ 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'));
//将这个分销商的产品交给分销商
$ distributorProduct-> setDistributor($ distributor);
//将此分销商的产品交给产品
$ distributorProduct-> setProduct($ product);
$ em-> persist($ distributorProduct);
//保存
$ em-> flush();
$ response = $ em-> getRepository('RestBundle:Product') - > find($ product-> getUuid());
返回数组('product'=> $ response);
}
}
}
我知道这不是好的代码,因为所有的业务逻辑都在控制器中。但是,如何以及在哪里可以将此代码(将请求设置为模型,持续并与原则冲洗等)转换为服务或使用依赖注入?还是为了这个目的而不是正确的方式服务?
我知道这个页面和教程 http://symfony.com/doc/current/best_practices/business-logic.html
但是我不清楚我在哪里放置CRUD操作。
为所有相关实体保存整个项目,执行一项服务?并使用Symfony\Component\HttpFoundation\Request;在服务?那么把整个控制器代码放在哪里我得到请求并分配给模型成一个服务?
谢谢
我将向您展示如何在公司中讲授控制器存储库解耦。
有两个简单的规则:
- 没有关于Doctrine的迹象控制器
- 控制器中没有
新
(静态,非DI方式)
我们将其应用于您的控制器
注意:这是伪代码,我还没有尝试但逻辑应该很容易理解。如果这太多变化,只需检查步骤3和4。
我们解除创建和保存过程。对于两个实体
这将导致我们进行4个服务:
#app / config / services.yml
services:
product_factory:
class:App \Domain\Product\ProductFactory
product_repository:
class:App \Repository\ProductRepository
autowire :true
distributor_product_factory:
class:App \Domain\Product\DistributorProductFactory
distributor_product_repository:
class:App\Repository\分销商产品资料库
autowire:true
1。产品工厂去除创建过程
// ProductFactory.php
命名空间App \Domain\Product;
class ProductFactory()
{
public function createFromRequest(Request $ request)
{
$ product = new Product();
$ product-> setEan($ request-> get('ean'));
$ product-> setAsin($ request-> get('asin'));
return $ product;
}
}
2。分销商产品工厂去分离创建流程
// DistributorProductFactory.php
命名空间App \Domain\Product;
class DistributorProductFactory()
{
public function createFromRequestProductAndDistributor(
请求$ request,
产品$ product,
经销商$ distributor
){
$ 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'));
//将此分销商与产品相关联
$ distributorProduct-> setProduct($ product);
//将此经销商的产品与产品相关联
$ distributorProduct-> setDistributor($ distributor);
返回$ distributor产品;
}
}
3。创建自己的ProductRepository服务
// ProductRepository.php
命名空间App\Repository;
使用RestBundle\Entity\Product;
使用Doctrine\ORM\EntityManagerInterface;
class ProductRepository
{
private $ entityManager;
public funtion __construct(EntityManagerInterface $ entityManager)
{
$ this-> entityManager = $ entityManager;
}
public function save(Product $ product)
{
$ this-> entityManager-> persist($ product);
$ this-> entityManager-> flush();
}
}
4。创建自己的DistributorProductRepository服务
// DistributorProductRepository.php
命名空间App\Repository;
使用RestBundle\Entity\DistributorProduct;
使用Doctrine\ORM\EntityManagerInterface;
class DistributorProductRepository
{
private $ entityManager;
public funtion __construct(EntityManagerInterface $ entityManager)
{
$ this-> entityManager = $ entityManager;
}
public function save(DistributorProduct $ distributorProduct)
{
$ this-> entityManager-> persist($ distributorProduct);
$ this-> entityManager-> flush();
}
}
5。我们完成了精美的控制器!
命名空间RestBundle\Controller;
使用Symfony\Component\HttpFoundation\Request;
使用FOS\RestBundle\Controller\FOSRestController;
class ProductController extends FOSRestController
{
//通过构造函数获取这些依赖项
public function createProductAction(Request $ request)
{
// todo:获取登录的分发对象
$ 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);
返回数组('product'=> $ product);
}
}
这就是全部!
I am very new in Symfony 3 and I want to avoid the business logic in my controllers. What I have done so far is this:
<?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);
}
}
}
I know that this is not good code because all the business logic is in the controller.
But how and where can I put this code (set requests into model, persist and flush with doctrine, etc) into a service or use dependency injection for it? Or is service for this purpose not the right way?
I know this page and tutorial http://symfony.com/doc/current/best_practices/business-logic.html but it is not clearify for me where to put CRUD Actions. Do ONE service for save a whole project with all the related entities? And use the Symfony\Component\HttpFoundation\Request; in a service? So put the whole controller code where I get the request and assign to the models into a service? Thanks
I will show you how I lecture controller repository decoupling in companies.
There are 2 simple rules:
- there are no signs about Doctrine in controller
- there is no
new
in the controller (static, non-DI approach)
Let's apply this to your controller
Note: this is pseudo code, I haven't tried that, but the logic should be easy to understand. If this is too many change, just check the steps 3 and 4.
We decouple create and save process. For both entities. This will lead us to 4 services:
# app/config/services.yml
services:
product_factory:
class: App\Domain\Product\ProductFactory
product_repository:
class: App\Repository\ProductRepository
autowire: true
distributor_product_factory:
class: App\Domain\Product\DistributorProductFactory
distributor_product_repository:
class: App\Repository\DistributorProductRepository
autowire: true
1. Product Factory to decouple create process
// ProductFactory.php
namespace App\Domain\Product;
class ProductFactory()
{
public function createFromRequest(Request $request)
{
$product = new Product();
$product->setEan($request->get('ean'));
$product->setAsin($request->get('asin'));
return $product;
}
}
2. Distributor Product Factory to decouple create process
// DistributorProductFactory.php
namespace App\Domain\Product;
class DistributorProductFactory()
{
public function createFromRequestProductAndDistributor(
Request $request,
Product $product,
Distributor $distributor
) {
$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;
}
}
3. Create own ProductRepository service
// ProductRepository.php
namespace App\Repository;
use RestBundle\Entity\Product;
use Doctrine\ORM\EntityManagerInterface;
class ProductRepository
{
private $entityManager;
public funtion __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function save(Product $product)
{
$this->entityManager->persist($product);
$this->entityManager->flush();
}
}
4. Create own DistributorProductRepository service
// DistributorProductRepository.php
namespace App\Repository;
use RestBundle\Entity\DistributorProduct;
use Doctrine\ORM\EntityManagerInterface;
class DistributorProductRepository
{
private $entityManager;
public funtion __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function save(DistributorProduct $distributorProduct)
{
$this->entityManager->persist($distributorProduct);
$this->entityManager->flush();
}
}
5. And we finish with nice and thin controller!
namespace RestBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use FOS\RestBundle\Controller\FOSRestController;
class ProductController extends FOSRestController
{
// get here dependencies via constructor
public function createProductAction(Request $request)
{
// 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 array('product' => $product);
}
}
That's all!
这篇关于Symfony 3 - 外包控制器代码到服务层的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!