zf3 __construct() not working - zend-framework

I've created a module with name Commerce in zend 3 which is working fine. Now when I inject a dependency through __construct() it throws error
Too few arguments to function
Commerce\Controller\IndexController::__construct(), 0 passed in
/var/www/html/zf3/vendor/zendframework/zend-servicemanager/src/Factory/InvokableFactory.php
on line 30 and exactly 1 expected
Here is the controller code.
<?php
namespace Commerce\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Commerce\Model\Commerce;
class IndexController extends AbstractActionController
{
private $commerce;
/**
* IndexController constructor.
* #param Commerce $commerce
*/
public function __construct(Commerce $commerce)
{
$this->commerceModel = $commerce;
}
public function indexAction()
{
return new ViewModel();
}
}
module.config.php code
<?php
namespace Commerce;
use Zend\Router\Http\Literal;
use Zend\Router\Http\Segment;
use Zend\ServiceManager\Factory\InvokableFactory;
return [
'router' => [
'routes' => [
'home' => [
'type' => Literal::class,
'options' => [
'route' => '/',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
'commerce' => [
'type' => Segment::class,
'options' => [
'route' => '/commerce[/:action][/:id]',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
],
],
'controllers' => [
'factories' => [
Controller\IndexController::class => InvokableFactory::class
],
],
'view_manager' => [
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => [
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
'commerce/index/index' => __DIR__ . '/../view/commerce/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
],
'template_path_stack' => [
__DIR__ . '/../view',
],
],
];
Where is the issue? zend-di is already installed.

Your error is caused in line
Controller\IndexController::class => InvokableFactory::class
this does not provide a "Commerce\Model\Commerce" to the constructor of your IndexController. You need to change this to provide the dependency:
'controllers' => [
'factories' => [
Controller\IndexController::class => function($container) {
return new Controller\IndexController(
$container->get(\Commerce\Model\Commerce::class)
);
},
],
],
'service_manager' => [
'factories' => [
\Commerce\Model\Commerce::class => function($sm) {
/* provide any dependencies if needed */
/* Create the model here. */
return new \Commerce\Model\Commerce($dependencies);
},
]
],
The best approach is to provide its own factory for your Commerce\Model\Commerce class, as seen above in the setting 'factories' of 'service_manager'.
EDIT: as request, if you want to do everything inside the controller Factory, here is a simple example:
'controllers' => [
'factories' => [
Controller\IndexController::class => function($container) {
$dbAdapter = $container->get('Zend\Db\Adapter\Adapter');
$resultSetPrototype = new ResultSet();
$tableGateway = new TableGateway('commerceTableName', $dbAdapter, null, $resultSetPrototype);
return new Controller\IndexController(
new \Commerce\Model\Commerce($tableGateway)
);
},
],
],

Related

Zend move translator configuration from module.config.php to Module.php

I'm pretty new to ZF and have a question regarding translator configuration. I have an application with the following translator configuration inside the module.cofig file:
'translator' => [
'locale' => 'ru_RU',
'translation_file_patterns' => [
[
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
],
[
'type' => 'phparray',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.php',
],
],
'cache' => \Zend\Cache\StorageFactory::factory(
[
'adapter' => [
'name' => 'Filesystem',
'options' => [
'cache_dir' => APPLICATION_LOAD_PATH . '/data/cache',
'ttl' => '3600',
],
],
'plugins' => [
[
'name' => 'serializer',
'options' => [],
],
'exception_handler' => [
'throw_exceptions' => true,
],
],
]
),
],
This configuration works fine, but I want to know if is it possible to move this code inside Module.php trough the getTranslatorPluginConfig() . What I've tried is to use this method and return this same config:
public function getTranslatorPluginConfig(){
return [
'translator' => [
'locale' => 'ru_RU',
'translation_file_patterns' => [
[
'type' => 'gettext',
'base_dir' => __DIR__ . '/language',
'pattern' => '%s.mo',
],
[
'type' => 'phparray',
'base_dir' => __DIR__ . '/language',
'pattern' => '%s.php',
],
],
'cache' => \Zend\Cache\StorageFactory::factory(
[
'adapter' => [
'name' => Filesystem::class,
'options' => [
'cache_dir' => APPLICATION_LOAD_PATH . '/data/cache',
'ttl' => '3600',
],
],
'plugins' => [
[
'name' => 'serializer',
'options' => [],
],
'exception_handler' => [
'throw_exceptions' => true,
],
],
]
),
],
];
}
As you can see I haven't changed anything (except base_dir path). I don't get any errors, but the translator is not working at all. If you can tell me what are the steps I need to take to make this configuration work from the Module file and if this is possible at all, I'll be grateful. I don't expect plain code, but just a guidance/suggestion of what could be done, since all I find in the Zend documentation is related with making this configuration inside module.config. Thanks in advance.

Zend routing issue

I'm working on converting a (quite sloppily put together) zend expressive website to a zend framework 3 website for a local restaurant. When I set up the routing on the expressive website I would load a location based on a query parameter looking like this.
website.com/location?location=xxx
On my new website the routing looks like this
website.com/locations/view/xxx
I need to set up a route that redirects the old url to the new url. So far I have set up a route that looks for the
/location?location=[/:location]
hoping that it would recognize this 'Segment' route and load the appropriate LocationsController. Right now it is giving me a route not found error.
My code looks like below.
module.config.php
namespace Application;
use Zend\Router\Http\Literal;
use Zend\Router\Http\Segment;
use Zend\ServiceManager\Factory\InvokableFactory;
return [
'router' => [
'routes' => [
'home' => [
'type' => Literal::class,
'options' => [
'route' => '/',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
'locations-old' => [
'type' => Segment::class,
'options' => [
'route' => '/location?location=[/:location]',
'defaults' => [
'controller' => Controller\LocationController::class,
'action' => 'index',
],
],
],
'locations' => [
'type' => Segment::class,
'options' => [
'route' => '/locations[/:action[/:location]]',
'constraints' => [
'action' => '[a-zA-Z]*',
'location' => '[a-zA-Z]*',
],
'defaults' => [
'controller' => Controller\LocationController::class,
'action' => 'index',
],
],
],
'locations.html' => [
'type' => Literal::class,
'options' => [
'route' => '/locations.html',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'location' => '[a-zA-Z][a-zA-Z0-9_-]*',
],
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
'about' => [
'type' => Literal::class,
'options' => [
'route' => '/about',
'defaults' => [
'controller' => Controller\AboutController::class,
'action' => 'index',
],
],
],
'employ' => [
'type' => Literal::class,
'options' => [
'route' => '/employ',
'defaults' => [
'controller' => Controller\EmployController::class,
'action' => 'index',
],
],
],
'news' => [
'type' => Literal::class,
'options' => [
'route' => '/news',
'defaults' => [
'controller' => Controller\NewsController::class,
'action' => 'index',
],
],
],
],
],
'view_manager' => [
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => [
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
'application/index/index' => __DIR__ . '/../view/application/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
],
'template_path_stack' => [
__DIR__ . '/../view',
],
],
];
LocationController.php
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Application\Model\StoreTable;
use Zend\View\Model\ViewModel;
class LocationController extends AbstractActionController
{
private $table;
public function __construct(StoreTable $table)
{
$this->table = $table;
}
public function indexAction()
{
if($_GET['location'] && $this->table->doesExist($_GET['location'])) {
$location = $_GET['location'];
$this->redirect()->toRoute('locations', ['action' => 'view', 'location' => $location])->setStatusCode(302);
} else {
$this->redirect()->toUrl('/#locations')->setStatusCode(301);
}
}
public function viewAction()
{
$location = (string) $this->params()->fromRoute('location');
$store = $this->table->getStore($location);
return new ViewModel([
'store' => $store,
]);
}
}
Any help would be greatly appreciated and I can provide more info if needed.
Thanks!
configure your route as following, this will be handle query based url as you given "website.com/location?location=xxx",
In below route ":key" variable implies ?location=xxx
'locations-old' => [
'type' => Segment::class,
'options' => [
'route' => '/location/:key',
'defaults' => [
'controller' => Controller\LocationController::class,
'action' => 'index',
],
'constraints' => [
'key' => '[a-z0-9]+',
],
],
'child_routes' => [
'query' => ['type' => 'query'],
],
]

Method not allowed(#405)

following code throws out error like this:
"Method Not Allowed (#405)
Method Not Allowed. This url can only handle the following request methods: ."
Any ideas,how to fix this?
['label' => 'Logout', 'url' => ['/site/logout'], 'linkOptions' => ['data' => ['method' => 'post']]],
Here is still method in SiteController:
public function actionLogout() {
Yii::$app->user->logout();
return $this->goHome();
}
use data-method in linkOptions
['label' => 'logOut',
'url' => ['/site/logout'],
'linkOptions' => ['data-method' => 'post']
],
notice:check behavior in sitecontroller
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['logout', 'dashboard'],
'rules' => [
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}

routing after authentication doesn't work properly

I probably have an understanding issue how the routing works. I tried a bit with zend-authentication, you can see the controllercode below.
If the authentication is valide I want a routing to another controller index action. Should be quite simple, but the routing doesn't work I stay at the loginform. I added an echo just to see where I am after authentication and the authentication is valide. Here is the code:
$form = new LoginForm();
//return ['form' => $form];
$form->get('submit')->setValue('Login');
//echo "hier";
//$this->layout()->setTemplate('layout/login-layout');
$request = $this->getRequest();
if (! $request->isPost()) {
return ['form' => $form];
}
else {
$username=$request->getPost('accessname');
$password=$request->getPost('passwort');
//echo $password;
$adapter = $this->authService->getAdapter();
$adapter->setIdentity($request->getPost('accessname'));
$adapter->setCredential($request->getPost('passwort'));
$result = $this->authService->authenticate();
if ($result->isValid()){
echo "valide";
//return $this->redirect()->toRoute('import');
return $this->redirect()->toRoute('import', ['action' => 'index']);
}
else{
return ['form' => $form, 'messages' => $result->getMessages()];
}
}
as you can see I tried several possibilities. The other controller is placed in the same module.
Here additional the index action of the destinationcontroller.
I'm not finished there, because of the false routing I toggled everything else, so it just shows the echotext when I land there.
public function indexAction()
{
echo "importcontroller";
// $result = $this->authService->has
// $auth=Zend_Auth::getInstance();
// $adapter = $this->authService->getAdapter();
// if(!$this->authService->hasIdentity())
// {
// return $this->redirect()->toRoute('./index/index');
// }
// else {
// return new ViewModel([
// 'projects' => $this->projectTable->fetchAll(),
// ]);
// }
}
EDIT1: Add module.confg.php
'router' => [
'routes' => [
'import' => [
'type' => Segment::class,
'options' => [
'route' => '/import[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\ImportController::class,
'action' => 'index',
],
],
],
'project' => [
'type' => Segment::class,
'options' => [
'route' => '/project[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\ProjectController::class,
'action' => 'index',
],
],
],
'unit' => [
'type' => Segment::class,
'options' => [
'route' => '/unit[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\UnitController::class,
'action' => 'index',
],
],
],
'index' => [
'type' => Segment::class,
'options' => [
'route' => '/index[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
'user' => [
'type' => Segment::class,
'options' => [
'route' => '/user[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\UserController::class,
'action' => 'index',
],
],
],
'followup' => [
'type' => Segment::class,
'options' => [
'route' => '/followup[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\FollowupController::class,
'action' => 'index',
],
],
],
Can you show contents of module.config.php with routing configuration?
Maybe your routing was wrong and redirect to the same page where you are before correct authentication?
P.s. I think, You should always filternig data from form and get it by $form->getDate() function. Of course before you should apply appropriate filters.
this concept is described in zend framework tutorial:
https://docs.zendframework.com/tutorials/getting-started/forms-and-actions/

ZF3 unable to populate select field from db

Can anyone explain me the easiest way to populate select field in form from db?
ChartsForm.php
<pre>
<?php
namespace Charts\Form;
use Zend\Form\Form;
use Charts\Model\PostRepositoryInterface;
class ChartsForm extends Form
{
private $postRepository;
public function __construct(PostRepositoryInterface $postRepository)
{
$this->postRepository = $postRepository;
// We will ignore the name provided to the constructor
parent::__construct('album');
$this->add([
'name' => 'id',
'type' => 'hidden',
]);
$this->add([
'name' => 'title',
'type' => 'text',
'options' => [
'label' => 'Title',
],
]);
$this->add(array(
'type' => 'Radio',
'name' => 'select',
'options' => array(
'label' => 'select type',
'value_options' => array(
'1' => 'Index',
'2' => 'Security',
),
),
'attributes' => array(
'value' => '1'
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'gender',
'options' => array(
'value_options' => $this->postRepository->findAllPosts(),
),
'attributes' => array(
'value' => '1'
)
));
$this->add([
'name' => 'submit',
'type' => 'submit',
'attributes' => [
'value' => 'Go',
'id' => 'submitbutton',
],
]);
}
}
</pre>
module.config.php
<pre>
<?php
namespace Charts;
use Zend\ServiceManager\Factory\InvokableFactory;
use Zend\Db\Adapter\AdapterAbstractServiceFactory;
return [
'controllers' => [
'factories' => [
Model\ChartSqlRepository::class => Factory\ChartSqlRepositoryFactory::class,
],
],
'service_manager' => [
'aliases' => [
Model\PostRepositoryInterface::class => Model\PostRepository::class,
],
'factories' => [
Model\PostRepository::class => InvokableFactory::class,
],
],
'view_manager' => [
'template_path_stack' => [
'charts' => __DIR__ . '/../view',
],
],
'router' => [
'routes' => [
'charts' => [
'type' => 'segment',
'options' => [
'route' => '/charts[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\ChartsController::class,
'action' => 'index',
],
],
],
],
],
// 'service_manager' => [
// 'factories' => [
// 'Zend\Db\Adapter\Adapter' => AdapterAbstractServiceFactory::class,
// ],
// ],
];
</pre>
module.php
<pre>
<?php
namespace Charts;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
class Module implements ConfigProviderInterface
{
public function getConfig()
{
return include __DIR__ . '/../config/module.config.php';
}
public function getServiceConfig()
{
return [
'factories' => [
Model\BKPagesTable::class => function($container) {
$tableGateway = $container->get(Model\BKPagesTableGateway::class);
return new Model\BKPagesTable($tableGateway);
},
Model\BKPagesTableGateway::class => function ($container) {
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\BKPages());
return new TableGateway('bkpages', $dbAdapter, null, $resultSetPrototype);
},
Model\BuyOrdersTable::class => function($container) {
$tableGateway = $container->get(Model\BuyOrdersTableGateway::class);
return new Model\BuyOrdersTable($tableGateway);
},
Model\BuyOrdersTableGateway::class => function($container) {
$dbAdapter2 = $container->get('api2web');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\BuyOrders());
return new TableGateway('BuyOrders', $dbAdapter2, null, $resultSetPrototype);
},
//Stocklist Table
Model\StockListTable::class => function($container) {
$tableGateway = $container->get(Model\StockListTableGateway::class);
return new Model\StockListTable($tableGateway);
},
Model\StockListTableGateway::class => function($container) {
$dbAdapter2 = $container->get('api2web');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\StockList());
return new TableGateway('StockList', $dbAdapter2, null, $resultSetPrototype);
},
//Fulldayquot Table
Model\FulldayquotTable::class => function($container) {
$tableGateway = $container->get(Model\FulldayquotTableGateway::class);
return new Model\FulldayquotTable($tableGateway);
},
Model\FulldayquotTableGateway::class => function($container) {
$dbAdapter2 = $container->get('api2web');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Fulldayquot());
return new TableGateway('fulldayquot', $dbAdapter2, null, $resultSetPrototype);
},
],
];
}
public function getControllerConfig()
{
return [
'factories' => [
Controller\ChartsController::class => function($container) {
return new Controller\ChartsController(
$container->get(Model\BKPagesTable::class)
);
},
],
];
}
}
</pre>
ChartSqlRepositoryFactory.php
<pre>
<?php
namespace Charts\Factory;
use Charts\Model\ChartSqlRepository;
use Zend\Db\Adapter\AdapterInterface;
use Blog\Model\PostRepositoryInterface;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class ChartSqlRepositoryFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new ChartSqlRepository(
$container->get($container->get(PostRepositoryInterface::class)
);
}
}
</pre>
ChartSqlRepository.php
<pre>
<?php
namespace Charts\Model;
use InvalidArgumentException;
use RuntimeException;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\Adapter\Driver\ResultInterface;
use Zend\Db\ResultSet\ResultSet;
class ChartSqlRepository implements PostRepositoryInterface
{
private $db;
private $repository;
public function __construct( ChartSqlRepository $repository)
{
$this->repository = $repository;
}
public function findAllPosts()
{
$sql = new Sql($this->db);
$select = $sql->select('BKPages');
$stmt = $sql->prepareStatementForSqlObject($select);
$result = $stmt->execute();
var_export($result);
die();
}
public function IndexesOptions()
{
$sql = new Sql($this->db);
$select = $sql->select('BKPages');
$stmt = $sql->prepareStatementForSqlObject($select);
$result = $stmt->execute();
$selectData = array();
foreach ($result as $res) {
$selectData[$res['MenuID']] = $res['MenuID'];
}
return $selectData;
}
public function findPost($id)
{
}
}
</pre>
I am trying to populate select field in ChartsForm.php from db and created a factory, maybe some error in module.config.php it's says.
Catchable fatal error: Argument 1 passed to Charts\Form\ChartsForm::__construct() must be an instance of Charts\Model\PostRepositoryInterface, none given, called in C:\wamp\www\bw\module\Charts\src\Controller\ChartsController.php on line 60 and defined in C:\wamp\www\bw\module\Charts\src\Form\ChartsForm.php on line 24
Help me out please.
Can you be more specific? What type of database?
You have two options: PDO (For all driver) and MySQLy (for MySQL).
Look here for a greater response:
https://stackoverflow.com/a/8255054/6784143
UPDATE:
You can connect your Sql Server with this line code (running good on .php).
resource mssql_connect ([ string $servername [, string $username [, string $password [, bool $new_link = false ]]]] )
You can execute a query with this line code.
mixed sqlsrv_query ( resource $conn , string $sql [, array $params [, array $options ]] )