我已经提供了一个服务来在我的模型中获取Doctrine连接(不确定它是否是一个很好的方法,但我不想每次都将连接从控制器传递给模型构造函数。)
所以我想说我想要控制器中的产品
public function getProductsAction(Request $request) {
$product_model = new ProductModel();
return $product_model->getProducts();
}
我有产品模型,它将访问帮助程序以获取“database_connection”
use AppBundle\Helper\ContainerHelper;
class ProductModel {
function getProducts() {
$helper = new ContainerHelper();
$db = $helper->getDoctrine();
$query = "SELECT * FROM customer_products;";
$statement = $db->prepare($query);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
现在这个助手在src / AppBundle / Helper / ContainerHelper.php中定义
namespace AppBundle\Helper;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
class ContainerHelper {
private $container;
public function __construct(Container $container) {
$this->container = $container;
}
public static function getDoctrine() {
$database_connection = $this->container->get('database_connection');
return $database_connection;
}
}
让我们说这个服务需要“服务容器”,所以在app / config / services.yml
services:
app.container_helper:
class: AppBundle\Helper\ContainerHelper
arguments: ['@service_container']
但它给了我错误:
捕获致命错误:参数1传递给 AppBundle \ Helper \ ContainerHelper :: __ construct()必须实现 接口Symfony \ Component \ DependencyInjection \ ContainerInterface, 没有给出,在\ src \ AppBundle \ Model \ ProductModel.php中调用 在第148行并定义
虽然我相信我已经根据http://symfony.com/doc/current/book/service_container.html和http://anjanasilva.com/blog/injecting-services-in-symfony-2/正确实施了它,但我确定我错过了一些东西或者只是得到了一个坏主意。我需要知道这是一个正确的概念还是我错过的
答案 0 :(得分:2)
虽然@pavlovich正试图修复你现有的代码,但我真的认为你使这个问题变得更加复杂。 ProductModel本身应该是一个注入数据库连接的服务。
class ProductModel {
public function __construct($conn) {
$this->conn = $conn;
}
public function getProducts() {
$stmt = $this->conn->executeQuery('SELECT * FROM customer_products');
return $stmt->fetchAll();
}
services:
product_model:
class: AppBundle\...\ProductModel
arguments: ['@database_connection']
// controller.php
$productModel = $this->get('product_model'); // Pull from container
$products = $productModel->getProducts();
答案 1 :(得分:1)
我建议使用构造函数注入和自动装配,而不是使用帮助程序。它更安全,面向未来,更容易扩展和测试。
在这种情况下,您必须创建ProductRepository
(ProductModel
的更常见和标准名称)并将其传递给控制器。
<?php
class SomeController
{
/**
* @var ProductRepository
*/
private $productRepository;
public function __construct(ProductRepository $productRepository)
{
$this->productRepository = $productRepository;
}
public function getProductsAction()
{
return $this->productRepository->getProducts();
}
}
如果您将控制器注册为服务有困难,请使用Symplify\ControllerAutowire bundle。
// src/AppBundle/Repository/ProductRepository.php
namespace AppBundle\Repository;
class ProductRepository
{
/**
* @var Doctrine\DBAL\Connection
*/
private $connection;
public function __construct(Doctrine\DBAL\Connection $connection)
{
$this->connection = $connection;
}
public function fetchAll()
{
$query = "SELECT * FROM customer_products;";
$statement = $this->connection->prepare($query);
$statement->execute();
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
}
# app/cofig/servies.yml
services:
product_repository:
class: AppBundle\Repository\ProductRepository
autowire: true
有关详情,您可以在此处看到类似的问题及答案:Symfony 3 - Outsourcing Controller Code into Service Layer
答案 2 :(得分:1)
使用新版本的Symfony 3.3,添加了一项新功能(自动连线服务依赖项)
https://symfony.com/doc/current/service_container/autowiring.html https://symfony.com/doc/current/service_container/3.3-di-changes.html
使用此功能,我通过以下方式解决了这个问题:
在此目录中添加了我的模型类
namespace AppBundle\Modal;
use Doctrine\ORM\EntityManagerInterface;
class ProductModal
{
private $em;
// We need to inject this variables later.
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}
// We need to inject this variables later.
public function getProducts()
{
$statement = $this->em->getConnection()->prepare("SELECT * FROM product WHERE 1");
$statement->execute();
$results = $statement->fetchAll();
return $results;
}
}
在我的app / config / services.yml
中添加AppBundle\Modal\:
resource: '../../src/AppBundle/Modal/*'
public: true
在我的控制器中我可以像
一样使用它$products = $this->get(ProductModal::class)->getProducts();
P.S。别忘了在控制器中添加use AppBundle\Entity\Product\Product;