ZF3 unable to populate select field from db - zend-framework

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 ]] )

Related

Access translator in Shopware 6 Plugin

I am developing my first Shopware 6 plugin and was wondering how to access snippets in the Plugin class. I checked the Developer Guide but could not make it work.
I want to use the plugin translation as label in customField select options.
myfirstplugin.en-GB.json
{
"myfirstplugin": {
"my_custom_field_option_1": "Option 1",
"my_custom_field_option_2": "Option 2",
}
}
MyFirstPlugin.php
class MyFirstPlugin extends Plugin
{
// ....
private function createCustomFields(Context $context): void
{
if ($this->customFieldSetExists($context)) {
return;
}
$customFieldSetRepository = $this->container->get('custom_field_set.repository');
$customFieldSetRepository->create([
[
'id' => '294865e5c81b434d8349db9ea6b4e135',
'name' => 'my_custom_field_set',
'customFields' => [
[
'name' => 'my_custom_field',
'type' => CustomFieldTypes::SELECT,
'config' => [
'label' => [ 'en-GB' => 'My custom field'],
'options' => [
[
'value' => '294865e5c81b434d8349db9ea6b4e487',
// Access my_custom_field_option_1 of snippet myfirstplugin.en-GB.json
'label' => 'my_custom_field_option_1',
],
[
'value' => '1ce5abe719a04346930c7e43514ed4f1',
// Access my_custom_field_option_2 of snippet myfirstplugin.en-GB.json
'label' => 'my_custom_field_option_2',
],
],
'customFieldType' => 'select',
'componentName' => 'sw-single-select',
'customFieldPosition' => 1,
],
],
]
],
], $context);
}
}
You can inject an argument of type Translator to your service
in services.xml
<argument type="service" id="translator"/>
in your service
use Shopware\Core\Framework\Adapter\Translation\Translator;
/**
* #var Translator
*/
private $translator;
public function __construct($translator)
{
$this->translator = $translator;
}
then down the way you can use this pretty much the same as in a twig template:
$translated = $this->translator
->trans(
'myfirstplugin.product.detail.294865e5c81b434d8349db9ea6b4e487');
I think you can use the snippet repository and search the label as you want in the Plugin class like
$sRepo = $this->container->get('snippet.repository');
$labels = $sRepo->search((new Criteria())
->addFilter(
new MultiFilter(
MultiFilter::CONNECTION_OR,
[
new ContainsFilter('translationKey', 'my_custom_field_option_1'),
new ContainsFilter('translationKey', 'my_custom_field_option_2')
]
)
), $context)->getElements();
When you create the custom field you don't have to reference a translation snippet. Instead you can just provide the translations in the payload directly.
'config' => [
'label' => ['en-GB' => 'Label english', 'de-DE' => 'Label german'],
'type' => CustomFieldTypes::SELECT,
'options' => [
[
'value' => '294865e5c81b434d8349db9ea6b4e487',
'label' => ['en-GB' => 'Option english', 'de-DE' => 'Option german'],
],
[
'value' => '1ce5abe719a04346930c7e43514ed4f1',
'label' => ['en-GB' => 'Option english', 'de-DE' => 'Option german'],
],
],
],

Unable to resolve service "Zend\Db\Adapter\AdapterInterface" to a factory

I am a newbie to zf.I downloaded the album project from github and started working on it . I did all the configuration as been written in the tutorial .
But i am getting this error continuously .
Unable to resolve service "Zend\Db\Adapter\AdapterInterface" to a factory; are you certain you provided it during configuration?
I started looking for some solutions and found same issue posted in Stack Overflow and went through them but none of the solution worked for me . Below i am pasting the pages code , pls assist i am stuck here for 2 days now. I am working on my local system . I have windows 10 and xampp installed.
Module.php
<?php
namespace Album;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
class Module implements ConfigProviderInterface
{
public function getConfig()
{
echo "Module.php";
return include __DIR__ . '/config/module.config.php';
}
public function getServiceConfig()
{
return [
'factories' => [
Model\AlbumTable::class => function ($container) {
$tableGateway = $container->get('Model\AlbumTableGateway');
return new Model\AlbumTable($tableGateway);
},
'Model\AlbumTableGateway' => function ($container) {
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Album());
return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
},
],
];
}
public function getControllerConfig()
{
return [
'factories' => [
Controller\AlbumController::class => function ($container) {
return new Controller\AlbumController(
$container->get(Model\AlbumTable::class)
);
},
],
];
}
}
module.config.php
namespace Album;
use Zend\Router\Http\Segment;
return [
'router' => [
'routes' => [
'album' => [
'type' => Segment::class,
'options' => [
'route' => '/album[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\AlbumController::class,
'action' => 'index',
],
],
],
],
],
'view_manager' => [
'template_path_stack' => [
'album' => __DIR__ . '/../view',
],
],
];
composer.json
{
"name": "zendframework/skeleton-application",
"description": "Skeleton Application for Zend Framework zend-mvc applications",
"type": "project",
"license": "BSD-3-Clause",
"keywords": [
"framework",
"mvc",
"zf"
],
"homepage": "http://framework.zend.com/",
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": "^5.6 || ^7.0",
"zendframework/zend-component-installer": "^1.0 || ^0.7 || ^1.0.0-dev#dev",
"zendframework/zend-mvc": "^3.0.1",
"zfcampus/zf-development-mode": "^3.0"
},
"autoload": {
"psr-4": {
"Application\\": "module/Application/src/",
"Album\\": "module/Album/src/"
}
},
"autoload-dev": {
"psr-4": {
"ApplicationTest\\": "module/Application/test/",
"Album\\": "module/Album/src/"
}
},
"extra": [],
"scripts": {
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"development-disable": "zf-development-mode disable",
"development-enable": "zf-development-mode enable",
"development-status": "zf-development-mode status",
"post-create-project-cmd": [
"#development-enable"
],
"serve": "php -S 0.0.0.0:8080 -t public public/index.php",
"test": "phpunit"
}
}
global.php
return array(
'db' => array(
'driver' => 'Pdo',
'adapters' => array(
'default_db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2tutorial;host=localhost',
'username' => 'root',
'password' => '',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' // optional
),
),
),
),
);
AlbumController.php
<?php
namespace Album\Controller;
use Album\Form\AlbumForm;
use Album\Model\Album;
use Album\Model\AlbumTable;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class AlbumController extends AbstractActionController
{
private $table;
public function __construct(AlbumTable $table)
{
$this->table = $table;
}
public function indexAction()
{
// Grab the paginator from the AlbumTable:
$paginator = $this->table->fetchAll(true);
// Set the current page to what has been passed in query string,
// or to 1 if none is set, or the page is invalid:
$page = (int) $this->params()->fromQuery('page', 1);
$page = ($page < 1) ? 1 : $page;
$paginator->setCurrentPageNumber($page);
// Set the number of items per page to 10:
$paginator->setItemCountPerPage(10);
return new ViewModel(['paginator' => $paginator]);
}
public function addAction()
{
$form = new AlbumForm();
$form->get('submit')->setValue('Add');
$request = $this->getRequest();
if (!$request->isPost()) {
return ['form' => $form];
}
$album = new Album();
$form->setInputFilter($album->getInputFilter());
$form->setData($request->getPost());
if (!$form->isValid()) {
return ['form' => $form];
}
$album->exchangeArray($form->getData());
$this->table->saveAlbum($album);
return $this->redirect()->toRoute('album');
}
public function editAction()
{
$id = (int) $this->params()->fromRoute('id', 0);
if (0 === $id) {
return $this->redirect()->toRoute('album', ['action' => 'add']);
}
// Retrieve the album with the specified id. Doing so raises
// an exception if the album is not found, which should result
// in redirecting to the landing page.
try {
$album = $this->table->getAlbum($id);
} catch (\Exception $e) {
return $this->redirect()->toRoute('album', ['action' => 'index']);
}
$form = new AlbumForm();
$form->bind($album);
$form->get('submit')->setAttribute('value', 'Edit');
$request = $this->getRequest();
$viewData = ['id' => $id, 'form' => $form];
if (!$request->isPost()) {
return $viewData;
}
$form->setInputFilter($album->getInputFilter());
$form->setData($request->getPost());
if (!$form->isValid()) {
return $viewData;
}
$this->table->saveAlbum($album);
// Redirect to album list
return $this->redirect()->toRoute('album', ['action' => 'index']);
}
public function deleteAction()
{
$id = (int) $this->params()->fromRoute('id', 0);
if (!$id) {
return $this->redirect()->toRoute('album');
}
$request = $this->getRequest();
if ($request->isPost()) {
$del = $request->getPost('del', 'No');
if ($del == 'Yes') {
$id = (int) $request->getPost('id');
$this->table->deleteAlbum($id);
}
// Redirect to list of albums
return $this->redirect()->toRoute('album');
}
return [
'id' => $id,
'album' => $this->table->getAlbum($id),
];
}
}
configure your "config/autoload/local.php" Or "config/autoload/global.php",
return array(
'db' => array(
'driver' => 'Pdo',
'adapters' => array(
'default_db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=YOURDBNAME;host=localhost',
'username' => 'xxx',
'password' => 'xxx',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' // optional
),
),
),
),
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
),
'abstract_factories' => array(
'Zend\Db\Adapter\AdapterAbstractServiceFactory',
),
),
);
You can set your credential on "config/autoload/local.php".
public function getServiceConfig()
{
return [
'factories' => [
Model\AlbumTable::class => function ($container) {
$tableGateway = $container->get('Model\AlbumTableGateway');
return new Model\AlbumTable($tableGateway);
},
'Model\AlbumTableGateway' => function ($container) {
$dbAdapter = $container->get('default_db'); // return driver instance
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Album());
return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
},
],
];
}
In config/application.config.php,
return array(
'modules' => array(
'Zend\Db', // make sure you have `'Zend\Db'` to top
update your composer.json file as below,
"require": {
"php": "^5.6 || ^7.0",
"zendframework/zend-component-installer": "^1.0 || ^0.7 || ^1.0.0-dev#dev",
"zendframework/zend-mvc": "^3.0.1",
"zfcampus/zf-development-mode": "^3.0",
"zendframework/zendframework": "^3.0",
"zendframework/zend-db": "^2.8.2",
},
for rendering update "module.config.php" with below,
'view_manager' => array(
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
I have also faced the same problem. I used minimal installation of zend framework.
Check the composer.json whether you have installed the zend-db.
If zend-db doesn't exist, install zend-db via composer,
composer require zendframework/zend-db
During installation, it will ask for configuration file injection, choose 1 for config.modules.php.

zf3 __construct() not working

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)
);
},
],
],

ZF3 - Set field in fieldset required depnding on form

I have a fieldset with a field called "company" which is not required by default. Now there is a form which adds this fieldset and now "company" should be required. Is there a way to do this in e. g. the form factory? Or can I rewrite the input filters of the fieldset in my inputfilter class binded to the form?
Thanks for any response!
Fieldset
class MyFieldset extends Fieldset implements InputFilterProviderInterface {
public function init() {
$this->add([
'name' => 'company',
'options' => [
'label' => 'Firma'
],
'attributes' => [
'id' => 'address-company'
]
]);
}
public function getInputFilterSpecification() {
return [
'company' => [
'required' => false,
'filters' => [
['name' => 'StripTags'],
['name' => 'StringTrim'],
['name' => 'ToNull']
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'encoding' => 'UTF-8',
'min' => 1,
'max' => 128
]
]
]
],
];
}
}
Form
class MyForm extends Form {
public function init() {
$this->add([
'type' => MyFieldset::class,
'name' => 'test',
'options' => [
'use_as_base_fieldset' => true
]
]);
}
}
Form Factory
class MyFormFactory implements FactoryInterface {
public function __invoke(ContainerInterface $container, $requestedName, array $options = null) {
$hydratorManager = $container->get('HydratorManager');
$inputFilterManager = $container->get('InputFilterManager');
$form = new MyForm();
$form->setHydrator($hydratorManager->get(DoctrineObject::class));
$form->setInputFilter($inputFilterManager->get(MyInputFilter::class));
$form->bind(new Entity());
return $form;
}
}
The only way I can think of doing it is.
In your fieldset use:
private $companyRequired = FALSE;
public function setCompanyRequired($companyRequired)
{
$this->companyRequired = (bool) $companyRequired;
}
public function getInputFilterSpecification()
{
return [
'company' => [
'required' => $this->companyRequired,
'filters' => [
['name' => 'StripTags'],
['name' => 'StringTrim'],
['name' => 'ToNull']
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'encoding' => 'UTF-8',
'min' => 1,
'max' => 128
]
]
]
],
];
}
in the form where the company is required place this in your init() method after adding the fieldset:
$this->get('test')->setCompanyRequired(TRUE);
As the getInputFilterSpecification() method is not read until you validate your form this should work.
I have previously answered a similar question relating to over loading the default input filter options of a nested fieldset.
You can do the same inside the form using the Zend\InputFilter\InputFilterProviderInterface
class MyForm extends Form implements InputFilterProviderInterface
{
public function init()
{
//..
}
public function getInputFilterSpecification()
{
return [
'test' => [
'type' => 'Zend\\InputFilter\\InputFilter',
'company' => [
'required' => true,
],
],
];
}
}
Or alternately, you can achieve the same by manually configuring the fieldset's input filter inside MyFormFactory;
class MyFormFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
//.. same code
$form->getInputFilter() // fetch the input filter you just attached.
->get('test') // the name of the neseted fieldset (another input filter)
->get('company') // the name of the input
->setRequired(true); // set required to true :)
return $form;
}
}

Yii2 backend url manager rules for module

I have created a module in Yii2 using Gii code generator. My new generated module location is
backend/modules/cms
cms is new generated module name.
backend/config/main.php after setting module configuration looks as following
return [
'id' => 'app-backend',
'basePath' => dirname(__DIR__),
'controllerNamespace' => 'backend\controllers',
'bootstrap' => ['log'],
'modules' => [
'gii' => [
'class' => 'yii\gii\Module', //adding gii module
'allowedIPs' => ['127.0.0.1', '::1'] //allowing ip's
],
'cms' => [
'class' => 'backend\modules\cms\Cms',
],
],
'components' => [
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => true,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'urlManager' => [
'class' => 'yii\web\UrlManager',
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<controller:\w+>/<action:\w+>/<id:\w+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
'<module:\w+>/<controller:\w+>/<action:\w+>' => '<module>/<controller>/<action>',
'<module:\w+><controller:\w+>/<action:update|delete>/<id:\d+>' => '<module>/<controller>/<action>',
]
],
'assetManager' => [
'bundles' => [
'yii\web\JqueryAsset' => [
'js' => []
],
],
],
],
'params' => $params,
];
behaviors function in controller looks as after setting access rules
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index', 'create', 'update', 'delete'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
],
],
];
}
Only index action of my controller is accessible. when i access any other action in controller url changes but shows index action contents.
How can i access all actions in controller?
It will be appreciable if someone help me resolving this issue.
my controller
namespace backend\modules\cms\controllers;
use Yii;
use yii\filters\AccessControl;
use backend\modules\cms\models\Pages;
use backend\modules\cms\models\PagesSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* PagesController implements the CRUD actions for Pages model.
*/
class PagesController extends Controller
{
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index', 'create', 'update', 'delete'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
// 'delete' => ['post'],
],
],
];
}
/**
* Lists all Pages models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new PagesSearch();
$dataProvider = $searchModel->search(Yii::$app->request->post());
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Pages model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Pages model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
echo "here";
exit;
$model = new Pages();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['index']);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Pages model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Pages model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Pages model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Pages the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Pages::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
I am using Url as follows:
http://localhost/yii2-demo/backend/cms/pages/index
http://localhost/yii2-demo/backend/cms/pages/create
What Url(s) are you using?
For a module it should be:
?r=cms/pages/index,
?r=cms/pages/create
etc...
The only problem I can spot is on your $matchCallback attribute on the second AccessControl rule. It should use this signature
function ($rule, $action)
And it should return a boolean that indicates wheter this rule should be applied or not. In your case, you're saying that it should be applied to users that are not guests and that have the role '0'. You're also calling a redirect inside the function, and it doesn't return a boolean. See more info here http://www.yiiframework.com/doc-2.0/yii-filters-accessrule.html#$matchCallback-detail
Try to remove this attribute completely and see if you get a different result.