我对Laminas相对陌生,有些事情对我来说仍然没有意义——在我看来,如何在Laminas中完成任务非常复杂。在我的情况下,现在我需要DB适配器的实例。
这个项目是这样的:
我有一个IndexController(和一个工厂(,它创建(在发布请求的情况下(邮件类的实例并且该Mail类应该在MailQueueTable中添加Data。但我不知道如何在MailQueueTable 中获取DB适配器
源代码如下:
IndexControllerFactory.php
<?php
declare(strict_types=1);
namespace TestControllerFactory;
use InteropContainerContainerInterface;
use LaminasServiceManagerFactoryFactoryInterface;
use TestControllerIndexController;
class IndexControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestName, array $options = null)
{
return new IndexController(
$container->get('ApplicationConfig')
);
}
}
IndexController.php
<?php
declare(strict_types=1);
namespace TestController;
use LaminasConfigConfig;
use LaminasMvcControllerAbstractActionController;
use LaminasViewModelViewModel;
use MailModelMail;
class IndexController extends AbstractActionController
{
private $config;
public function __construct(array $config)
{
$this->config = $config;
}
public function indexAction()
{
$request = $this->getRequest();
if ($request->isPost()) {
$Mail = new Mail();
$Mail->send();
}
}
}
}
Mail.php
<?php
namespace MailModel;
use LaminasViewModelViewModel;
use MailModelTableMailQueueTable;
class Mail {
public function send()
{
$MailQueueTable = new MailQueueTable();
$MailQueueTable->add();
}
}
MailQueueTable.php
<?php
declare(strict_types=1);
namespace MailModelTable;
use LaminasDbAdapterAdapter;
use MailModelMail;
class MailQueueTable extends AbstractTableGateway
{
protected $adapter;
protected $table = 'mail_queue';
public function __construct(Adapter $adapter)
{
// Here starts the problem...
// As far as I understand, I have to inject
// the DB Adapter in the Construct of the
// AbstractTableGateway Class...
// But no idea how to get it here...
$this->adapter = $adapter;
$this->initialize();
}
public function add()
{
// SQL Insert Statement would be here
}
}
MailQueue表代码是基于我读过的教程中的构造函数等。正如您所看到的,构造需要适配器。但我现在不知道如何获得适配器。
到目前为止,我所读到的内容是,我需要在索引控制器工厂中注入DB适配器,然后从索引控制器中的Action注入到新创建的邮件实例,然后从那里注入到MailQueue表?
我觉得这不是正确的解决方案-在使用Laminas之前,我可以只写
global $DB;
我的数据库可用。
一开始很复杂,但当你习惯了工厂(和DI(时,它会变得更容易:(
问题出在你的控制器内部:
public function indexAction()
{
$request = $this->getRequest();
if ($request->isPost()) {
// !! wrong !!
$Mail = new Mail();
// !! wrong !!
$Mail->send();
}
}
}
您正在创建Mail
的实例,但邮件几乎没有必须解决的依赖项,但您的控制器无法做到这一点。要解决此问题,您应该从DI(ContainerInterface
(中获取Mail
实例。
IndexControllerFactory.php
内部
public function __invoke(ContainerInterface $container, $requestName, array $options = null)
{
$applicationConfig = $container->get('ApplicationConfig');
$mail = $container->get(MailModelMail::class);
return new IndexController($applicationConfig, $mail);
}
这样,IndexController
的依赖关系将由其工厂解决。现在,您必须调整控制器以接受构造函数中的新实例:
class IndexController extends AbstractActionController
{
private $config;
private $mail;
public function __construct(array $config, Mail $mail)
{
$this->config = $config;
$this->mail = $mail;
}
public function indexAction()
{
$request = $this->getRequest();
if ($request->isPost()) {
$this->mail->send();
}
}
}
}
但是,对于Mail
(因为它需要MailQueuqTable
的实例(和MailQueueTable
(因为它要求Adapter
的实例(,您将遇到相同的问题。
因此,在构造对象和添加工厂时,应该提供这些依赖项MailModelMail
:
class Mail {
private $mailQueueTable;
public function __construct(MailQueueTable $mailQueueTable)
{
$this->mailQueueTable = $mailQueueTable;
}
public function send()
{
$this->mailQueueTable->add();
}
}
其工厂MailModelMailFactory
:
class MailFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestName, array $options = null)
{
return new Mail(
$container->get(MailModelTableMailQueueTable::class)
);
}
}
MailModelTableMailQueueTable
实际上是正确的,因为构造函数已经需要Adapter
的实例。您必须创建其工厂MailModelTableMailQueueTableFactory
:
class MailQueueTableFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestName, array $options = null)
{
// Create the DB adapter
$dbConfig = [
'driver' => 'PDO',
'pdodriver' => '...',
'dbname' => '...',
'host' => '...',
'username' => '...',
'password' => '...'
];
$adapter = new Adapter($dbConfig);
return new MailQueueTable($adapter);
}
}
最后,您必须告诉DI
在哪里可以找到这些工厂,因此在模块配置文件中:
'service_manager' => [
'factories' => [
MailModelMail::class => MailModelMailFactory::class,
MailModelTableMailQueueTable::class => MailModelTableMailQueueTableFactory::class
]
]
非常感谢您的精彩回答。
这意味着,对于每一个类;i可能需要"/";i可能创建";在我的控制器中,我必须在ControllerFactory中声明它?
哇。Laminas真的需要大量的代码来实现这一点;简单的";实例
即使你的答案很好,它也会导致新的问题:
- 如果我在CCD_ 18中获得CCD_,我不能将变量传递给
Mail
类的构造函数(即电子邮件地址、电子邮件内容等,这些都是在IndexController中创建的(,因为Mail
类的构造函数将是:
public function __construct(MailQueueTable $mailQueueTable)
{
$this->mailQueueTable = $mailQueueTable;
}
我认为正确吗?
- 我一直在关注蜡泥工作室的laminats youtube教程-DB教程在这里:https://www.youtube.com/watch?v=07h3OBIF9kc
它将数据库凭据、数据库名称等保存在配置文件中。我如何访问它们,而不是像您提到的那样将它们再次放在MailQueueTableFactory
中?从IndexControllerFactory
获取DB适配器的实例,将其传递到IndexController
,然后从那里我将其传递给Mail
?
- 我还没有弄清楚的一件奇怪的事情是,如果我在
IndexControllerFactory
中注入MailQueueTable
,即:
class IndexControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestName, array $options = null)
{
return new IndexController(
$container->get(MailQueue::class)
);
}
}
我不必创建MailQueueTableFactory
,也不必通过DB凭据等。不知何故,MailQueueTable
似乎得到了适配器?!