Zend: Issues setting up editAction(), please advise - php

I am experiencing some difficulty setting up the functionality for an admin to edit an items values. I have created the editAction() function in the AdminItemController class. This is contained within a module called catalog. My routing is configured as the following:
resources.router.routes.admin-catalog-edit.route = "/admin/catalog/item/edit/:id"
resources.router.routes.admin-catalog-edit.defaults.module = "catalog"
resources.router.routes.admin-catalog-edit.defaults.controller = "admin.item"
resources.router.routes.admin-catalog-edit.defaults.action = "edit"
I have created a custom Zend_Form class and within this class I set the action and method for the form:
class My_Form_ItemAdd extends Zend_Form
{
public function init()
{
$this->setAction('/admin/catalog/item/edit')
->setMethod('post');
...
Within my controller action I have instantiated the form and pass it to the view to be rendered. I also test if it's a POST (if so validate and save to database), otherwise, test for GET (if so, extract ID and populate()):
class Catalog_AdminItemController extends Zend_Controller_Action
{
...
public function editAction()
{
$form = new My_Form_ItemEdit();
$this->view->form = $form;
...
The form loads just fine in the browser when I supply an ID at the end for GET request... however, when I submit the form an exception is thrown with the following request parameters:
array (
'controller' => 'admin',
'action' => 'catalog',
'item' => 'edit',
'module' => 'default',
...
I have no idea why the it would be doing this... is there something I'm not seeing??? Any advice would be much appreciated!

The problem lies in your route. The default behavior for /admin/catalog/item/edit/:id is to process it like /controller/action/:param/:param/:param which puts both item and edit as parameters instead of your intended purpose. Try adding something like this to your bootstrap:
protected function _initRoutes()
{
// Get front controller
$front = Zend_Controller_Front::getInstance();
// Get router
$router = $front->getRouter();
// Add route
$router->addRoute(
'admin_item_edit',
new Zend_Controller_Router_Route('admin/catalog/item/edit/:id',
array('controller' => 'item',
'action' => 'edit'))
);
}
This allows you to define the specific controller and action from the route.

Related

Rendering Zend Form in Slim3

I am using Slim3 with Zend Forms 2.6 (https://packagist.org/packages/zendframework/zend-form). I am trying to render the form but I get an error:
Fatal error: Call to undefined method QuizApp\Forms\QuizForm::render() in /var/www/QuizApp/Routes/SurveyRoutes.php on line 25
I have added my form as a service within Slim3:
$container['QuizForm'] = function() use ($app) {
return new \QuizApp\Forms\QuizForm($app->SurveyServices);
};
Here is my form:
class QuizForm extends \Zend\Form\Form
{
private $survey_services;
public function __construct(SurveyServices $survey_services, $name = null)
{
$this->survey_services = $survey_services;
parent::__construct($name);
}
public function init()
{
/*
* Set form method to POST
*/
$this->setMethod('POST');
/*
* Add submit button to the form
*/
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Get Quiz Results'
),
));
}
}
I am attempting to render the form within one of my routes (eventually I will pass this to my view, but I'm testing):
$form = $this->QuizForm;
# Doesn't work
print $form;
# Doesn't work
print $form->render()
What's confusing me is the docs say printing the form should work: http://framework.zend.com/manual/1.12/en/zend.form.quickstart.html#zend.form.quickstart.render
I am not using the Zend Framework. I am only using the Form component.
How do I render the form?
You're looking at wrong place. That's documentation for Zend's version 1.12.
You are using newest version, so take a look here.
According to that doc resource, before rendering, you should call
$form->prepare();
Also you probably should use Form View Helpers if you want to make rendering forms easy.
It looks like you don't have a proper DI setup, if you can't dump the form like so...
php
var_dump($this->QuizForm);
Then that object is not in the context of this.
I suspect that you might be missing injecting it into the class where you are calling this. But your problem currently is that you need to inject the quiz into your object where you are trying to render it.

How check if action exsist in Controller Plugin preDispatch

I have two modules (default and mobile) the module mobile is a rewrite the default portal in jquery mobile but with much less controllers and actions!
I thought of write a controller plugin that check if controller and action exist in module mobile, if not I would like overwrite the module mobile to default.
I try this:
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
$dispatcher = Zend_Controller_Front::getInstance()->getDispatcher();
if ($request->getModuleName() == 'mobile') {
if (!$dispatcher->isDispatchable($request)) {
// Controller or action not exists
$request->setModuleName('default');
}
}
return $request;
}
but $dispatcher->isDispatchable($request) return always true though the action not exist! :S
and i receive "Action foo does not exist and was not trapped in __call()"
How can I do?
Thanks
Have you ever wondered how to check if a controller/action exist in zend FM from any side of app ? Here is the code
$front = Zend_Controller_Front::getInstance();
$dispatcher = $front->getDispatcher();
$test = new Zend_Controller_Request_Http();
$test->setParams(array(
'action' => 'index',
'controller' => 'content',
)
);
if($dispatcher->isDispatchable($test)) {
echo "yes-its a controller";
//$this->_forward('about-us', 'content'); // Do whatever you want
} else {
echo "NO- its not a Controller";
}
EDIT
Check like this way
$classMethods = get_class_methods($className);
if(!in_array("__call", $classMethods) &&
!in_array($this->getActionMethod($request), $classMethods))
return false;
and also please see detail link
I would suggest you make a static or dynamic routes either via config resource manager, bootstrap or via front controller plugin:
Example of defining static routes in Bootstrap.php:
public function _initRoutes()
{
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter(); // default Zend MVC routing will be preserved
// create first route that will point from nonexistent action in mobile module to existing action in default module
$route = new Zend_Controller_Router_Route_Static(
'mobile/some-controller/some-action', // specify url to controller and action that dont exist in "mobile" module
array(
'module' => 'default', // redirect to "default" module
'controller' => 'some-controller',
'action' => 'some-action', // this action exists in "some-controller" in "default" module
)
);
$router->addRoute('mobile-redirect-1', $route); // first param is the name of route, not url, this allows you to override existing routes like default route
// repeat process for another route
}
This would effectively route request for /mobile/some-controller/some-action to /default/some-controller/some-action
some-controller and some-action should be replaced with proper controller and action names.
I was using static routing which is ok if you route to exact urls, but since most applications use additional params in url for controller actions to use, it is better to use dynamic routes.
In above example simply change route creation class to Zend_Controller_Router_Route and route url to "mobile/some-controller/some-action/*" and every request will be routed dynamically like in example:
/mobile/some-contoller/some-action/param1/55/param2/66
will point to
/default/some-controller/some-action/param1/55/param2/66
For more info about routing in ZF1 check this link

how to call function of controller in cakephp framework with default function?

i am new comer for cakephp framework. i can not call functions of controller.
Controller-
class PagesController extends AppController {
public $name = 'Pages';
public $uses = array();
public function display() {
$path = func_get_args();
$count = count($path);
if (!$count) {
$this->redirect('/');
}
$page = $subpage = $title_for_layout = null;
if (!empty($path[0])) {
$page = $path[0];
}
if (!empty($path[1])) {
$subpage = $path[1];
}
if (!empty($path[$count - 1])) {
$title_for_layout = Inflector::humanize($path[$count - 1]);
}
$this->set(compact('page', 'subpage', 'title_for_layout'));
$this->render(implode('/', $path));
}
public function register() {
$this->set('fdf', 'chandan');
$this->render('home1');
}
}
But i am calling display(). but i am not calling register(). my routes.php file like-
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Please help me. how to call controller function from view in cakephp.
and what setting have to done for it ?.
A few points I would make, the routes file is for defining custom slugs/url, take a look at your first route definition here:
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
This is saying that "www.mysite.com/" should link to the controller pages, the action display and pass the first parameter as home.
This can be accessed by doing "www.mysite.com/pages/display/home" in short - but using "/" as a route is tidier. The general rule is "www.mysite.com/controller/action/param1/param2/etc.."
So following this logic you would access your new action method like such:
"www.mysite.com/pages/register"
That being said... When using MVC you should really follow the conventions set out, if you're going to create a register method you should really contain it within a controller which deals with user accounts i.e. "UsersController" - "www.mysite.com/users/register"
Also, you shouldn't really need to use $this->render() unless you have to render a separate view under special conditions.
To sum up, contain all actions within a relevant controller (i.e. www.mysite.com/users/login and www.mysite.com/users/register), never directly specify $this->render unless you really need to render something other than the default (/users/register.ctp would be the default for www.mysite.com/users/register) and routes are used to create tidier or custom urls.
I would highly recommend you read and follow the blog tutorial to grasp these concepts.

Cakephp Passed arguments

Hello, my code is not working in CakePHP framework and it is showing an error message.
URL:
http://domainname.com/About/param1/param2
Code:
class AboutController extends AppController {
public $name = 'About';
public $helpers = array('Html');
public function index($arg1, $arg2)
{
print_r($this->request->params['pass']);
$this->set('title_for_layout','Sarasavi Bookshop - About Sarasavi Bookshop');
$this->set('nameforfiles','about');
}
}
Error message:
Missing Method in AboutController
Error: The action param1 is not defined in controller AboutController
Error: Create AboutController::param1() in file: app\Controller\AboutController.php.
<?php
class AboutController extends AppController {
public function param1() {
}
}
Notice: If you want to customize this error message, create app\View\Errors\missing_action.ctp
After creating the function param1 I can get param2, But I need to get param1 and param2 both, in index function without create another action.
Please help me,
Thanks
Your original code would work if you went to http://domainname.com/About/index/param1/param2
If you don't want the index in the url, as I assume you don't, then you need to define a route.
Add this to your routes:
Router::connect(
'/About/*',
array('controller' => 'About', 'action' => 'index')
);
to automatically route requests that don't specify an action but do have params to go to your index action. You will need to add a route for any new About actions to stop requests for them from going to index by default though.
You probably access this URL without specifying action name (index) like this:
/about/param1/param2
This will not work as Cake expects to see action name after controller name. In this case, param1 is treated as action name.
You can access your action with URL
/about/index/param1/param2
To overcome this situation, make a new rule to your Router:
Router::connect(
'/about/:param1/:param2',
array('controller' => 'about', 'action' => 'index'),
array('param1', 'param2')
);

Zend Framework 2: Navigation

In my controller I create the Navigation object and passing it to the view
$navigation = new \Zend\Navigation\Navigation(array(
array(
'label' => 'Album',
'controller' => 'album',
'action' => 'index',
'route' => 'album',
),
));
There trying to use it
<?php echo $this->navigation($this->navigation)->menu() ?>
And get the error:
Fatal error: Zend\Navigation\Exception\DomainException: Zend\Navigation\Page\Mvc::getHref cannot execute as no Zend\Mvc\Router\RouteStackInterface instance is composed in Zend\View\Helper\Navigation\AbstractHelper.php on line 471
But navigation which I use in layout, so as it is written here: http://adam.lundrigan.ca/2012/07/quick-and-dirty-zf2-zend-navigation/ works. What is my mistake?
Thank you.
The problem is a missing Router (or to be more precise, a Zend\Mvc\Router\RouteStackInterface). A route stack is a collection of routes and can use a route name to turn that into an url. Basically it accepts a route name and creates an url for you:
$url = $routeStack->assemble('my/route');
This happens inside the MVC Pages of Zend\Navigation too. The page has a route parameter and when there is a router available, the page assembles it's own url (or in Zend\Navigation terms, an href). If you do not provide the router, it cannot assemble the route and thus throws an exception.
You must inject the router in every page of the navigation:
$navigation = new Navigation($config);
$router = $serviceLocator->get('router');
function injectRouter($navigation, $router) {
foreach ($navigation->getPages() as $page) {
if ($page instanceof MvcPage) {
$page->setRouter($router);
}
if ($page->hasPages()) {
injectRouter($page, $router);
}
}
}
As you see it is a recursive function, injecting the router into every page. Tedious! Therefore there is a factory to do this for you. There are four simple steps to make this happen.
STEP ONE
Put the navigation configuration in your module configuration first. Just as you have a default navigation, you can create a second one secondary.
'navigation' => array(
'secondary' => array(
'page-1' => array(
'label' => 'First page',
'route' => 'route-1'
),
'page-2' => array(
'label' => 'Second page',
'route' => 'route-2'
),
),
),
You have routes to your first page (route-1) and second page (route-2).
STEP TWO
A factory will convert this into a navigation object structure, you need to create a class for that first. Create a file SecondaryNavigationFactory.php in your MyModule/Navigation/Service directory.
namespace MyModule\Navigation\Service;
use Zend\Navigation\Service\DefaultNavigationFactory;
class SecondaryNavigationFactory extends DefaultNavigationFactory
{
protected function getName()
{
return 'secondary';
}
}
See I put the name secondary here, which is the same as your navigation key.
STEP THREE
You must register this factory to the service manager. Then the factory can do it's work and turn the configuration file into a Zend\Navigation object. You can do this in your module.config.php:
'service_manager' => array(
'factories' => array(
'secondary_navigation' => 'MyModule\Navigation\Service\SecondaryNavigationFactory'
),
)
See I made a service secondary_navigation here, where the factory will return a Zend\Navigation instance then. If you do now $sm->get('secondary_navigation') you will see that is a Zend\Navigation\Navigation object.
STEP FOUR
Tell the view helper to use this navigation and not the default one. The navigation view helper accepts a "navigation" parameter where you can state which navigation you want. In this case, the service manager has a service secondary_navigation and that is the one we need.
<?= $this->navigation('secondary_navigation')->menu() ?>
Now you will have the navigation secondary used in this view helper.
Disclosure: this answer is the same as I gave on this question: https://stackoverflow.com/a/12973806/434223
btw. you don't need to define controller and action if you define a route, only if your route is generic and controller/action are variable segments.
The problem is indeed that the routes can't be resolved without the router. I would expect the navigation class to solve that issue, but obviously you have to do it on your own. I just wrote a view helper to introduce the router with the MVC pages.
Here's how I use it within the view:
$navigation = $this->navigation();
$navigation->addPage(
array(
'route' => 'language',
'label' => 'language.list.nav'
)
);
$this->registerNavigationRouter($navigation);
echo $navigation->menu()->render();
The view helper:
<?php
namespace JarJar\View\Helper;
use Zend\View\Helper\AbstractHelper;
use Zend\View\Helper\Navigation;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Navigation\Page\Mvc;
class RegisterNavigationRouter extends AbstractHelper implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
public function __invoke(Navigation $navigation)
{
$router = $this->getRouter();
foreach ($navigation->getPages() as $page) {
if ($page instanceof Mvc) {
$page->setRouter($router);
}
}
}
protected function getRouter()
{
$router = $this->getServiceLocator()->getServiceLocator()->get('router');
return $router;
}
}
Don't forget to add the view helper in your config as invokable instance:
'view_helpers' => array(
'invokables' => array(
'registerNavigationRouter' => 'JarJar\View\Helper\RegisterNavigationRouter'
)
),
It's not a great solution, but it works.

Categories