0

我对 Laminas 比较陌生,有些事情对我来说仍然没有意义 - 就 - 在我看来,如何在 laminas 中完成事情非常复杂。就我而言,现在我需要数据库适配器的实例。

项目是这样的:

我有一个 IndexController(和一个工厂),它创建(在 Post 请求的情况下)一个 Mail 类的实例,并且该 Mail 类应该在 MailQueueTable 中添加数据。但我不知道如何在 MailQueueTable 中获取 DB Adapter

源代码如下:

索引控制器工厂.php

<?php

declare(strict_types=1);

namespace Test\Controller\Factory;

use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Test\Controller\IndexController;


class IndexControllerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestName, array $options = null)
    {
        return new IndexController(
            $container->get('ApplicationConfig')
        );
    }
}

索引控制器.php

<?php

declare(strict_types=1);

namespace Test\Controller;

use Laminas\Config\Config;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
use Mail\Model\Mail;


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();
            }
        }
    }
}

邮件.php

<?php

namespace Mail\Model;

use Laminas\View\Model\ViewModel;
use Mail\Model\Table\MailQueueTable;


class Mail {

    public function send()
    {
        $MailQueueTable = new MailQueueTable();
        $MailQueueTable->add();
    }

}

MailQueueTable.php

<?php

declare(strict_types=1);

namespace Mail\Model\Table;

use Laminas\Db\Adapter\Adapter;
use Mail\Model\Mail;

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 表代码是基于我阅读的教程的构造函数等。如您所见,构造需要适配器。但我现在不知道如何获得适配器。

据我到目前为止所阅读的,我需要在索引控制器工厂中注入数据库适配器,然后从索引控制器中的操作到新创建的邮件实例,然后我必须将它注入到 MailQueue 表中?

我不觉得这是正确的解决方案 - 在使用 Laminas 之前我可以写

global $DB;

我有我的数据库可用。

4

2 回答 2

0

非常感谢您的出色回答。

所以这意味着,对于每个“我可能需要”/“我可能在我的控制器中创建一个实例”的类,我必须在 ControllerFactory 中声明它?

哇。对于这个“简单”示例,Laminas 确实需要大量代码。

即使您的答案很好,它也会导致新的问题:

  1. 如果我获得Mail里面的实例,IndexControllerFactory.php这会导致问题,我不能将变量传递给Mail类的构造函数(即电子邮件地址、电子邮件的内容等,它们是在 IndexController 中创建的),因为Mail类的构造函数会是:
    public function __construct(MailQueueTable $mailQueueTable)
    {
        $this->mailQueueTable = $mailQueueTable;
    }

我看对了吗?

  1. 我正在关注蜡泥工作室的 laminas youtube 教程 - DB 教程在这里: https ://www.youtube.com/watch?v=07h3OBIF9kc

它将数据库凭证、数据库名称等保存在配置文件中。我怎样才能访问它们而不是MailQueueTableFactory像你提到的那样将它们再次放入?获取数据库适配器的实例,将其IndexControllerFactory传递给IndexController并从那里将其传递给Mail

  1. 我还没有弄清楚的奇怪的事情是,如果我在MailQueueTable中注入IndexControllerFactory,即:
class IndexControllerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestName, array $options = null)
    {
        return new IndexController(
            $container->get(MailQueue::class)
        );
    }
}

不必创建一个MailQueueTableFactory也不必传递数据库凭据等。不知何故,MailQueueTable它似​​乎获得了适配器......?!

于 2020-10-23T14:00:09.720 回答
0

一开始很复杂,但是当你习惯了工厂(和 DI)时,它会变得更容易:)

问题出在您的控制器内部:

public function indexAction()
{
    $request = $this->getRequest();
    
    if ($request->isPost()) {
            // !! wrong !!
            $Mail = new Mail();
            // !! wrong !!

            $Mail->send();
        }
    }
}

您正在创建 的实例Mail,但 mail 几乎没有必须解决的依赖项,但您的控制器无法做到这一点。要解决这个问题,您应该从您的 DI (the )获取Mail实例。ContainerInterface

里面IndexControllerFactory.php

public function __invoke(ContainerInterface $container, $requestName, array $options = null)
{
    $applicationConfig = $container->get('ApplicationConfig');
    $mail = $container->get(\Mail\Model\Mail::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)和 for MailQueueTable(因为它需要 的​​实例Adapter),您将遇到同样的问题。

因此,您应该在构造对象并添加工厂时提供这些依赖项 Mail\Model\Mail

class Mail {
    private $mailQueueTable;

    public function __construct(MailQueueTable $mailQueueTable)
    {
        $this->mailQueueTable = $mailQueueTable;
    }

    public function send()
    {
        $this->mailQueueTable->add();
    }
}

它的工厂Mail\Model\MailFactory

class MailFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestName, array $options = null)
    {
        return new Mail(
            $container->get(\Mail\Model\Table\MailQueueTable::class)
        );
    }
}

Mail\Model\Table\MailQueueTable实际上是正确的,因为构造函数已经需要Adapter. 您必须创建它的工厂,Mail\Model\Table\MailQueueTableFactory

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' => [
        \Mail\Model\Mail::class => Mail\Model\MailFactory::class,
        \Mail\Model\Table\MailQueueTable::class => Mail\Model\Table\MailQueueTableFactory::class
    ]
]
于 2020-10-23T08:34:54.757 回答