I'm relative new to Laminas and some things still doesn't make sense to me - in terms of - it looks to me very complicated how things have to be done in laminas. in my case now I need the instance of the DB adapter.
The project is like this:
I have an IndexController (and a Factory) that creates (in case of an Post Request) an instance of an Mail Class and that Mail class is supposed to add Data in the MailQueueTable. But I don't know how to get the DB Adapter in the MailQueueTable
The Source code is as follows:
IndexControllerFactory.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')
);
}
}
IndexController.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();
}
}
}
}
Mail.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
}
}
The MailQueue Table Code is in terms of constructor etc. based on the tutorials I have read. as you can see the construct needs the Adapter. But I have no idea how to get the Adapter at this point.
As far as I have read until now, I need to inject the DB Adapter in the Index Controller Factory, then from the Action in the Index Controller to the new created Mail Instance and from there I have to inject it to the MailQueue Table ?
I don't feel that this is the right solution - before using Laminas i could just write
global $DB;
and I had my DB available.
It is quite complicated at the beginning, but when you get used to Factories (and DI), it will become easier :)
The problem is inside your controller:
You are creating an instance of
Mail
, but mail has few dependencies which must be resolved, but your controller just can't do it. To solve this problem, you should obtain theMail
instance from your DI (theContainerInterface
).Inside
IndexControllerFactory.php
This way, dependencies for
IndexController
will be resolved by its factory. Now you must adapt the controller to accept the new instance in the constructor:But then, you will have the same problem for
Mail
(since it requires an instance ofMailQueuqTable
) and forMailQueueTable
(since it requires an instance ofAdapter
).Therefore, you should supply those dependencies when constructing the object, and adding factories
Mail\Model\Mail
:its factory
Mail\Model\MailFactory
:Mail\Model\Table\MailQueueTable
is actually correct, since the constructor already requires an instance ofAdapter
. You must create its factory,Mail\Model\Table\MailQueueTableFactory
:Finally, you must tell your
DI
where to find those factories, so in the module configuration file: