I'm using Zendframework (2.3), I'm struggling to understand what I'm doing wrong when attempting to create a new action and view on an existing controller. I've read some relevant documentation but still fail to see what I'm missing.
Currently the controller basically defaults to a single action (main), I would like to add an additional one.
EG:
/list-item/main => // Existing Route
/list-item/add => // New Route I would like to add.
This is how my module.config.php looks:
return array(
'router' => array(
'routes' => array(
'list-item' => array(
'type' => 'segment',
'options' => array(
'route' => '/list-item[/:action][/:id][/:id1][/:id2][/:id3][/:id4][/:id5]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*'
),
'defaults' => array(
'controller' => 'ListItem',
'action' => 'main',
),
),
),
),
),
'controllers' => array(
'invokables' => array(
'ListItem' => 'ListItem\Controller\ListItemController',
),
),
'view_manager' => array(
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
);
If I can read this configuration correctly, the actual action name is optional, but the module will default to the main action. Yet it is flexible to allow for any action to be attempted.
So, I proceeded to add a new public function into the ListItemController, assumed this is how the convention works:
public function addAction() {
return new ViewModel();
}
And with it a new view file into the module's views folder, in fact right next to main.phtml but called add.phtml.
But when I attempt to access the route /list-item/add I only get a permission denied. Funny, because the actual status is 200. But I have no other information. I honestly don't even know if this is a ZF thing, I can only assume.
Also, I'm using php -S 0.0.0.0:8080 -t public/ in case the web server might have something to do.
Thanks in advance, any help will be greatly appreciated.
Related
So I've been following the fairly straightforward zend 2 skeleton example "album". I followed every step to the teeth and yet I cannot escape the 404 Error - requested URL could not be matched by routing whenever I input http://hostname/album for indexing, or http://hostname/album/add for adding, etc.
Naturally I looked into the routing found in the module.config.php file:
<?php
return array(
'controllers' => array(
'invokables' => array(
'Album\Controller\Album' => 'Album\Controller\AlbumController',
),
),
'router' => array(
'routes' => array(
'album' => array(
'type' => 'segment',
'options' => array(
'route' => '/album[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Album\Controller\Album',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view',
),
),
);
Everything here looked fine, so I looked into the Module.php where the module.config.php is getting loaded from:
<?php
namespace Album;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
class Module implements AutoloaderProviderInterface, ConfigProviderInterface
{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php',
),
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
}
Again, everything looks fine here. Now I thought maybe the problem is that I didn't include the Album module in the application.config.php file (comments removed):
<?php
return array(
'modules' => array(
'Application',
'Album',
),
'module_listener_options' => array(
'module_paths' => array(
'./module',
'./vendor',
),
'config_glob_paths' => array(
'config/autoload/{{,*.}global,{,*.}local}.php',
),
);
However it is included. I also have the AlbumController.php and the view (.phtml) files exactly where they should be. I double checked the paths multiple times yet the routes still do not work. Any ideas? Any suggestion would be appreciated.
PS - I am using a Ubuntu 14.04 Virtual Box.
EDIT
Here's the directory structure for the application: (I'm just listing the relevant files/folders to make it more readable)
ZendSkel
public
index.php
config
application.config.php
module
Application
Album
Module.php
config
module.config.php
src
Album
Controller
AlbumController.php
Model
Form
view
album
album
index.phtml
add.phtml
edit.phtml
delete.phtml
Also, I am using virtual host with apache2.2.
For anyone, who is still looking for solution of this problem,
Clearing the data/cache folder, allowed routing to work as expected.
Like #Mayank Awasthi said:
Clearing the data/cache folder, allowed routing to work as
expected.
This applies to Zend AND Laminas.
If the issue is not cache related, check your config and routing files!
If you follwoing the tutorial in the official page step by step and it shows 404. make sure 1- stop the serve,
2- enter "composer development-enable".
3- enter "composer serve"
and then it should work. The tutorial does mention "composer development-enable" but it doesnt mention it in the right order, reason why a lot of people keep getting the 404
I'm just starting off with Zend Framework, and I'm not quite sure what I'm doing wrong with the URI routing.
I'm starting with an initial Zend Framework project in Zend Studio based in my htdocs folder (I'm using Zend Server as well on Windows 7). Everything up to there seems to be working fine getting the index page up (it's running out of the /public/ subdirectory).
But when I try to add a module though, in this case called Users with a controller called Index, and following the instructions in getting that configured, I'm not sure what I should be putting in the URI to get it to route to it's view. I've tried just about every configuration of URI combinations that I can think of (localhost:80/public/users, localhost:80/public/users/index, localhost:80/users, etc)
I'm not getting a routing error, but just a plain 404 page.
Do I need to set the public folder as the root? Or is there something else I need to do to get the routing to work?
~edit in response to bitWorking
It looks like it does automatically add it to the application.config.php. But here is the module.config.php of the Users module
'router' => array(
'routes' => array(
'users' => array(
'type' => 'Literal',
'options' => array(
// Change this to something specific to your module
'route' => '/index',
'defaults' => array(
// Change this value to reflect the namespace in which
// the controllers for your module are found
'__NAMESPACE__' => 'Users\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
// This route is a sane default when developing a module;
// as you solidify the routes for your module, however,
// you may want to remove it and replace it with more
// specific routes.
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
),
),
Now I do see where it's guiding you to customize the routes. I've experimented with this as well, but still am not sure what I should set them to. Much closer though.
If you want to call the Index controller in your Users module with /users you have to name the route accordingly:
...
'users' => array(
'type' => 'Literal',
'options' => array(
// Change this to something specific to your module
'route' => '/users',
---------
...
Else please control the application.config.php. It should look like:
return array(
'modules' => array(
'Application',
'Users',
),
...
So the Url's should look like:
localhost/public/users -> Users/Controller/IndexController/indexAction
localhost/public/users/foo -> Users/Controller/FooController/indexAction
localhost/public/users/foo/bar -> Users/Controller/FooController/barAction
I implemented a form for placing new orders in Zend Framework 2 and after submitting the form I should redirect to another route and take the orders.id variable in another controller.
I tried using $this->redirect()->toRoute('confirm', array('param'=>$orderId)); but it is not working at all.
Maybe I do not know how to get that parameter in another confirmAction controller.
Please give me some examples. Thank you very much.
1) Since this is a routing issue, show what you have for the route in the module.config.php file. You might not have the "param" constraint configured properly in your config if I had to guess.
It should look something like this:
'confirm' => array(
'type' => 'segment',
'options' => array(
'route' => '/controller_name/confirm[/][:param][/]',
'constraints' => array(
'param' => '[0-9]*'
),
'defaults' => array(
'__NAMESPACE__' => 'your_namespace', // ex. Application\Controller
'action' => 'confirm', // or whatever action you're calling
'controller' => 'controller_name' // ex.
),
),
),
I added zfcUser module to my project via Composer and overrided it in the module ZfcUserOverride. I want trailing slash work, so I added route in overrided module.
zfcUserOverride file module.config.php contents below:
<?php
$config = array(
'view_manager' => array(
'template_path_stack' => array(
'zfcuser' => __DIR__ . '/../view',
),
),
'controllers' => array(
'invokables' => array(
'zfcuser' => 'ZfcUserOverride\Controller\UserController',
),
)
);
$config['router']['routes']['zfcuser']['child_routes']['trailing_slash'] = array(
'type' => 'Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'zfcuser',
'action' => 'index',
),
),
);
return $config;
I added new path, everythin is working correct.
But what if I want remove route? How to do this? I need somethink like:
$config['router']['routes']['zfcuser']['child_routes']['login'] = null;
Help please. Thank you.
In zfcUserOverride you will need to override the route config rather than add a new one.
This can easily be done by using the same array key when defining the routes.
For example; should I wish to modify the login route to allow the extra slash I would use this:
// zfcUserOverride/config/module.config.php
'router' => array(
'routes' => array(
'zfcuser' => array(
'child_routes' => array(
'login' => array(
'type' => 'Segment',
'options' => array(
'route' => '/login[/]',
),
),
),
),
),
);
Internally ZF2 will combine/merge all module configuration into one complete array using array_replace_recursive(). Matching configuration keys will therefore be replaced by modules that have loaded after.
So you will also need to ensure that you have it correctly configured in application.config.php
array(
'modules' => array(
//...
'ZfcUser',
'ZfcUserOverride', // Loads after
// ...
),
);
Here the answer.
#Sharikov Vladislav, I want to say something to you.
In this question I answered to your question and you choose the correct answer to somebody that just update his answer with my content 10 hours later.
I do not want to start a flame war, what I ask is just to be correct to whom used its time to help you.
And also I think you must use search engines prior to post here, you are asking a question for every single step of your development process and it is clear you are putting no effort on searching a solution by yourself.
Just sayin..
Hi I am trying to write a user registration form using ZfcUser module for Zend Framwork 2 and would like some advice on best practices when adding more user fields.
So far I have created my own module called "WbxUser" and as outlined in the modules wiki pages I have added a custom field called "userlastname" to ZfcUser's registration form by using the Event Manager in my modules bootstrap function like so.
Code:
//WbxUser.Module.php
namespace WbxUser;
use Zend\Mvc\MvcEvent;
class Module {
public function onBootstrap(MvcEvent $e){
$events = $e->getApplication()->getEventManager()->getSharedManager();
$events->attach('ZfcUser\Form\Register','init', function($e) {
$form = $e->getTarget();
$form->add(array(
'name' => 'userlastname',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Last Name',
),
));
// Do what you please with the form instance ($form)
});
$events->attach('ZfcUser\Form\RegisterFilter','init', function($e) {
$filter = $e->getTarget();
$filter->add(array(
'name' => 'userlastname',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'min' => 3,
'max' => 255,
),
),
),
));
});
}
public function getConfig(){
return array();
}
public function getAutoloaderConfig(){
return array();
}
}
But after this I have got a bit lost on where/how to write the code to save the extra data that my new fields are gathering.
Is this the event where I can fire off save routines for the additional fields https://github.com/ZF-Commons/ZfcUser/wiki/How-to-perform-a-custom-action-when-a-new-user-account-is-created
Should I be writing my own WbxUser model that extends ZfcUser\Entity\User.php to add my new fields
I am a bit of a ZF and MVC noob so would be very great-full for a nudge in the write direction.
this one seems to be a bit more intuitive
http://juriansluiman.nl/en/article/117/use-3rd-party-modules-in-zend-framework-2
You can override the module configurations. The most elegant way is to use the zfcuser.global.php.dist in the autoload folder. Copy this file to your appliction autoload folder and change the filename to zfcuser.global.php. In here you're able to change whatever option you can find in here. This option can be used to override the zfcUser entity: 'user_entity_class' => 'ZfcUser\Entity\User'.
Then again, you may find yourself in a situation where you need to change things that cannot be changed in the configuration file. In this case you could create your own user module ( You may want to just clone the entire zfcuser module until you're sure about what files you want to replace.
After cloning the user module (and changed the namespaces accordingly) add your module to application.config.php. Make sure your module is loaded after zfcuser. Or alternatively you could remove zfcuser from the config file and put the following in module.php:
public function init($moduleManager)
{
$moduleManager->loadModule('ZfcUser');
}
Now you can override ZfcUser module configurations.
The following snippet could be used to override the template folder and UserController.
<?php
// Note most routes are managed in zfcUser config file.
// All settings here either overrides or extend that functionality.
return array(
'view_manager' => array(
'template_path_stack' => array(
// 'zfcuser' => __DIR__ . '/../view', Override template path
),
'template_map' => array(
// You may want to use templates from the original module without having to copy - paste all of them.
),
),
'controllers' => array(
'invokables' => array(
// 'zfcuser' => 'YourModule\Controller\IndexController', // Override ZfcUser controller.
),
),
'router' => array(
'routes' => array(
'zfcuser' => array(
'type' => 'Literal',
'priority' => 2500,
'options' => array(
'route' => '/user',
'defaults' => array(
// Use original ZfcUser controller.
// It may be a good idea to use original code where possible
'controller' => 'ZfcUser\Controller\UserController',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'authenticate' => array(
'type' => 'Literal',
'options' => array(
'route' => '/authenticate',
'defaults' => array(
// Invoke YourModule\Controller\IndexController
'controller' => 'zfcuser',
'action' => 'authenticate',
),
),
),
),
),
),
),
);
Also you can override ZfcUser services in module.php. ;-)
Altering a third party module don't really appeal to me because at times it unsettle a lot of functionality. I always try do something outside the module because if there is an update in the module i easily incorporate into my application without haven to rewrite anything.
To do something like you are trying to do I would create another table in my application and add a foreign key that extend the zfcuser table that way i can relate the information to each zf2user in my application.
It just a suggestion as i am also new in zf2.