symfony4 数据库查询
从数据库中取回对象更加容易。例如,假设您已配置路由以Product根据其id值显示特定的路径:
public function showAction($productId)
{
// $productId 为传递的参数
$product = $this->getDoctrine()
->getRepository(Product::class)
->find($productId);
if (!$product) {
throw $this->createNotFoundException(
'No product found for id '.$productId
);
}
// ... do something, like pass the $product object into a template
}
查询特定类型的对象时,始终使用所谓的“存储库”。您可以将存储库视为PHP类,其唯一的工作是帮助您获取某个类的实体。您可以通过以下方式访问实体类的存储库对象:
// Product 为数据库名称
$repository = $this->getDoctrine()
->getRepository(Product::class);
当获取到实例之后就可以通过以下方法进行查询数据库:
$repository = $this->getDoctrine()->getRepository(Product::class);
// looks for a single product by its primary key (usually "id")
$product = $repository->find($productId);
// dynamic method names to find a single product based on a column value
$product = $repository->findOneById($productId);
$product = $repository->findOneByName('Keyboard');
// dynamic method names to find a group of products based on a column value
$products = $repository->findByPrice(19.99);
// finds *all* products
$products = $repository->findAll();
您还可以利用有用的findBy()和findOneBy()方法设置多个条件,以方便获取数据对象:
$repository = $this->getDoctrine()->getRepository(Product::class);
// looks for a single product matching the given name and price
$product = $repository->findOneBy(
array('name' => 'Keyboard', 'price' => 19.99)
);
// looks for multiple products matching the given name, ordered by price
$products = $repository->findBy(
array('name' => 'Keyboard'),
array('price' => 'ASC')
);
查询到的数据是对象,而非数组,在return到页面上的时候数据是空的,是由于 syfmony 的安全机制,可以使用getArrayResult()
方法进行转换,继续看下文,会有介绍。
更新数据对象
从Doctrine中获取对象后,更新它很容易。假设您有一条路径将产品ID映射到控制器中的更新操作:
use AppBundle\Entity\Product;
// ...
public function updateAction($productId)
{
$entityManager = $this->getDoctrine()->getManager();
$product = $entityManager->getRepository(Product::class)->find($productId);
if (!$product) {
throw $this->createNotFoundException(
'No product found for id '.$productId
);
}
$product->setName('New product name!');
$entityManager->flush();
return $this->redirectToRoute('homepage');
}
更新对象只需三个步骤:
1.从Doctrine中获取对象;
2.修改数据对象;
3.从数据库实体中调用 flush() 方法并执行。
请注意,调用$entityManager->persist($product)
不是必需的。回想一下,这种方法只是告诉Doctrine管理或“观察” $product对象。在这种情况下,由于您\$product
从 Doctrine
中获取了对象,因此它已经被管理。
删除数据对象
删除对象的方法与上面的也非常相似,但需要调用 remove() 实体管理器的方法:
$entityManager->remove($product);
$entityManager->flush();
查询数据
您已经了解了数据库对象如何允许您在没有任何工作的情况下运行基本查询:
$repository = $this->getDoctrine()->getRepository(Product::class);
$product = $repository->find($productId);
$product = $repository->findOneByName('Keyboard');
当然,Doctrine还允许您使用Doctrine查询语言(DQL)编写更复杂的查询。DQL类似于SQL,除了您应该想象您正在查询实体类的一个或多个对象(例如Product)而不是查询表上的行(例如product)。
在Doctrine中查询时,您有两个主要选项:编写纯DQL查询或使用Doctrine的Query Builder。
使用DQL查询对象
想象一下,您想查询价格高于19.99最低价格的产品。您可以使用DQL(Doctrine的本机SQL语言)为此方案构建查询:
$entityManager = $this->getDoctrine()->getManager();
$query = $entityManager->createQuery(
'SELECT p
FROM AppBundle:Product p
WHERE p.price > :price
ORDER BY p.price ASC'
)->setParameter('price', 19.99);
$products = $query->getResult();
如果您对SQL感到满意,那么DQL应该感觉非常自然。最大的区别在于您需要考虑选择PHP对象而不是数据库中的行。出于这个原因,你选择从该 AppBundle:Product 实体(为一个可选的快捷方式 AppBundle\Entity\Product类),起个别名叫p。
注意setParameter()方法。使用Doctrine时,将任何外部值设置为“占位符”(:price在上面的示例中)始终是一个好主意,因为它可以防止SQL注入攻击。
该getResult()方法返回一组结果。要获得一个结果,您可以使用getOneOrNullResult():
$product = $query->setMaxResults(1)->getOneOrNullResult();
DQL语法非常强大,允许您轻松地在实体之间加入(关系主题将在稍后介绍),组等。有关更多信息,请参阅官方的 Doctrine查询语言文档。
使用Doctrine的查询生成器查询对象
您可以使用一个名为the的有用对象QueryBuilder来代替编写DQL字符串 。当实际查询依赖于动态条件时,这很有用,因为当您开始连接字符串时,很快就会难以用DQL读取代码:
$repository = $this->getDoctrine()
->getRepository(Product::class);
// createQueryBuilder() automatically selects FROM AppBundle:Product
// and aliases it to "p"
$query = $repository->createQueryBuilder('p')
->where('p.price > :price')
->setParameter('price', '19.99')
->orderBy('p.price', 'ASC')
->getQuery();
$products = $query->getResult();
// to get just one result:
// $product = $query->setMaxResults(1)->getOneOrNullResult();
该QueryBuilder对象包含构建查询所需的每种方法。通过调用该getQuery()方法,查询构建器返回一个普通Query对象,该对象可用于获取查询结果。
有关Doctrine的Query Builder的更多信息,请参阅Doctrine的 Query Builder文档。
将自定义查询组织到数据库类中
前面部分中的所有查询都直接写在您的控制器中。但是对于组织,Doctrine提供了特殊的存储库类,允许您将所有查询逻辑保存在一个中心位置。
推荐方式-可以直接得到json数组
public function collectionAll()
{
// 访问实体类的数据库对象
$repository = $this->getDoctrine()
->getRepository(Collection::class);
$query = $repository->createQueryBuilder('p')
->where('p.id > :id')
->setParameter('id', '5')
->orderBy('p.id', 'desc')
->getQuery();
// $result = $query->getResult();
$result = $query->getArrayResult();
$data = array(
'code' => 200,
'msg' => '请求成功',
'data' => $result
);
return new JsonResponse($data, Response::HTTP_OK);
}
参考文档:Symfony-Doctrine