我是Symfony的新手,这些问题是在最近的学习过程中提出的。
以一家商店为例,我将创建两个实体,即Product和Category,它们具有双向的多对一关系。
class Product
{
private $id;
private $name;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Category", inversedBy="products")
* @ORM\JoinColumn(name="category_id", referencedColumnName="id", nullable=false)
*/
private $category;
}
class Category
{
private $id;
private $name;
/**
* @ORM\OneToMany(targetEntity="App\Entity\Product", mappedBy="category")
*/
private $products;
}
所以我的第一个问题是:
如果要获取特定类别中的所有产品,URL应该为
/ categories?categoryId = 1&limit = 20&orderBy = name (我知道这有点愚蠢,但是类别记录是否应包含所有产品信息?)
或
/ products?categoryId = 1&limit = 20&orderBy = name
对于后一个问题,出现第二个问题:
我将ProductRepository注入到ProductController
class ProductController extends Controller
{
private $productRepository;
public function __construct(ProductRepository $productRepository)
{
$this->productRepository = $productRepository;
}
...
}
为了将所有产品归为一个类别,我编写了这样的方法:
public function findByCategory(Category $category): array
{
return $this->createQueryBuilder('p')
->andWhere('p.category = :category')
->setParameter('category', $category)
->orderBy('p.name', 'ASC')
->setMaxResults(20)
->getQuery()
->getResult()
;
}
因此,在ProductController中,如何从URL中的查询字符串'categoryId'获取Category对象?我应该同时注入CategoryRepository还是仅注入一个实体管理器对象?
答案 0 :(得分:1)
Marco Pivetta aka Ocramius(该学说的主要开发者之一)说:
避免双向关联
双向关联是开销
仅对域逻辑工作所需的代码进行编码
使用复杂的DQL查询,而不是通过双向简化它们
所以也许 you don't need bi-directional association在这里。
对于您的第一个问题,我认为第二个解决方案更好:
/ products?categoryId = 1&limit = 20&orderBy = name
对于第二个问题,是的,如果要访问Category对象,则应注入CategoryRepository,即使可能,也请避免访问控制器中的整个entityManager。
您应该在控制器中注入服务。您的服务应公开公共方法,以通过data mappers对数据库执行定制的CRUD访问。请注意,repository不是数据映射器,而是
EAA目录的充当域和数据映射层之间的中介,就像内存中的域对象集合一样。
P-马丁·福勒
Repositories are services实际上是很好的做法,可以将它们注入到控制器中。
有人捍卫这样的立场,即存储库不应包含创建,更新或删除,而只能包含 READ 。他们说这些操作使集合(可通过存储库访问)不一致。
这篇文章也可以提供帮助:How should a model be structured in MVC?
答案 1 :(得分:0)
对我来说,这里的问题是ORM在Symfony与数据库设计,建模和查询之间的作用非常明显的混淆。
在数据库中(使用PhpMyAdmin),您会注意到在产品表上有一列称为category(或category_id)的列。保持简单,要获得属于某个类别的产品,您只需要category_id。将这些知识带到Symfony,您不需要类别对象,只需使用从请求中获得的类别ID。另外,只需在控制器中使用EntityManager,不要使内容复杂化,特别是因为看来您才刚刚起步。
use Symfony\Component\HttpFoundation\Request;
class ProductController extends Controller
{
public function get_product_from_categoryAction(Request $request)
{
$category_id = (int) $request->get('category');
$limit = (int) $request->get('limit');
$orderBy = strip_tags($request->get('orderBy'));
$em = $this->getDoctrine()->getManager();
$products = $em
->getRepository('AppBundle:Products')
->queryProductsByCategoryId($category_id, $limit, $orderBy);
}
...
}
还有回购
public function queryProductsByCategoryId(int $category_id, int $limit = 10, string $orderBy = 'name')
{
return $this->createQueryBuilder('p')
->andWhere('p.category = :category')
->setParameter('category', $category_id)
->orderBy('p.name', 'ASC')
->setMaxResults($limit)
->getQuery()
->getResult()
;
}
保持简单,然后,当您变得更高级时,请尝试一些更高级的东西。