I'm developing a website using the PHP Phalcon Framework and I am really stuck in a problem with the router, here I go.
In order to restrict the HTTP Method for your route to match, I use this declaration:
$router->addGet('/admin/paginas', array(
'namespace' => 'Backend\Controllers',
'controller' => 'pagina',
'action' => 'list'
));
But it fails with the following error:
Unexpected value type: expected object implementing Phalcon\DiInterface, null given
I have some other routes defined in the same services.php file with add and there's no problem with them, for example:
$router->add('/oportunidades-trabajo', array(
'controller' => 'page',
'action' => 'oportunidadesTrabajo'
));
Works perfectly fine. I've tried removing namespace, changing the controller, using short sintax, using ->via() instead of addGet, but nothing solves my issue.
If i remove this route declaration everything works fine.
Here's the full declaration of the router:
$di->set('router', function () {
$router = new Router(false);
$router->removeExtraSlashes(true);
# FRONT END
$router->add('/oportunidades-trabajo', array(
'controller' => 'page',
'action' => 'oportunidadesTrabajo'
));
# BACK END - Paginas
# list
$router->addGet('/admin/paginas', array(
'namespace' => 'Backend\Controllers',
'controller' => 'pagina',
'action' => 'list'
));
# NOT FOUND
$router->notFound(array(
'controller' => 'page',
'action' => 'page404'
));
$router->handle();
return $router;
});
I would appreciate a lot your help, as I'm stuck with this and I cannot continue with the project.
Thanks a lot in advance for your time.
$router->handle(); must not be called in the service definition.
Just delete $router->handle();
Source: http://forum.phalconphp.com/discussion/3623/strange-error-with-the-phalcon-router
Related
Help with routing settings, there is the following request template with frontend: /books/([0-9]+)/book-authors/([0-9]+)/images
There is a controller located in namespace: Shop\Controllers\Books\BookAuthors\ImagesController
The controller has an indexAction method.
In routing.php I specify the following:
$router = new Router(false);
$router->removeExtraSlashes(true);
$router->setDefaultNamespace('Shop\Controllers');
$router->setDefaultController('index');
$router->setDefaultAction('index');
$router->addGet('/books/([0-9]+)/book-authors/([0-9]+)/images', [
'namespace' => 'Shop\Controllers\Books\BookAuthors',
'bookId' => 1,
'authorId' => 2,
'controller' => 'images',
'action' => 'index',
]);
return $router;
As a result, we get that the redirect always goes to the default controller. Please tell me how to fix...
I tried to debug and check why the template does not fit, but when I checked regex101 on the site, everything matches there and should work, but for some reason it does not work in phalcon.
Application return every time "not found"
The route works fine, although you can try this for simplicity and clarity:
$router->addGet('/books/{bookId:[0-9]+}/book-authors/{authorId:[0-9]+}/images',
[
'controller' => 'images',
'action' => 'index'
]
);
And in your ImagesController define indexAction as:
public function indexAction(int $bookId, int $authorId)
{
echo "BookId: $bookId and AuthorId: $authorId";
}
For /books/10/book-authors/22/images the result should be:
BookId: 10 and AuthorId: 22
Try this:
$router->addGet('/books/:int/book-authors/:int/images', [
'namespace' => 'Shop\Controllers\Books\BookAuthors',
'controller' => 'images',
'action' => 'index',
'bookId' => 1,
'authorId' => 2,
]);
Note that I don't know if you can have multiple ":int" in the router definition and I have not tried this code.
If you can't have multiple ":int" in the line, you may need to restructure and move the bookId and authorId to the end and use :params. Note that I also dropped the "images" controller name since you don't need that in the line.
$router->addGet('/books/book-authors/:params', [
'namespace' => 'Shop\Controllers\Books\BookAuthors',
'controller' => 'images',
'action' => 'index',
'params' => 1,
]);
Your URL would be something along the lines of "/books/book-authors/98/212" for bookID 98 and authorId 212.
In Zend Framework 2, I tried using the following route:
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/:username[/:action]',
'defaults' => array(
'__NAMESPACE__' => 'Website\Controller',
'controller' => 'User',
'action' => 'index',
),
),
'may_terminate' => true,
),
However, when going to http://www.example.com/MyUsernameHere, I get a 404 not found error:
The requested controller could not be mapped to an existing controller class.
Controller:
User(resolves to invalid controller class or alias: User)
It's almost like the router completely ignores the 'Website\Controller' namespace and looks for User without the namespace in front it.
So, if I manually enter the namespace like so:
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/:username[/:action]',
'defaults' => array(
'controller' => 'Website\Controller\User',
'action' => 'index',
),
),
'may_terminate' => true,
),
then the page loads as expected.
What gives? Can the '__NAMESPACE__' parameter not be used for controllers? The ZF2 website clearly gives an example using '__NAMESPACE__', but I cannot get it work in practice. Is the example wrong and outdated?
For this to work as you expected you have to attach the ModuleRouteListener to the MVC event manager. You can do this in your module onBootstrap method:
public function onBootstrap(MvcEvent $event)
{
//...
$application = $event->getApplication();
$eventManager = $application->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
//...
}
After you did that your code will work as expected.
They actually should have mentioned this in the page with the example that you referred to in your question. You can check for more details on the module route listener here in the Zend\Mvc documentation. They write there:
This listener determines if the module namespace should be prepended to the controller name. This is the case if the route match contains a parameter key matching the MODULE_NAMESPACE constant.
I got a problem solving an variable Adminurl in Zend Framework 1.
The Route looks fine and should work, it do except if i give parameters.
Thanks for anyone who could help.
Why this will not work?
$adminpath is simple valid string.
'resources' => array(
'router' => array(
'routes' => array(
'backend' => array(
'route' => $adminpath.'/:module/:controller/:action/*'
)
)
)
),
It returns:
http://localhost/cms/admin/AppB/update/activate/moduleName/AppCm
An error occurred
Page not found
Exception information:
Message: Invalid controller specified (admin)
Stack trace:
Request Parameters:
array (
'controller' => 'admin',
'action' => 'AppB',
'update' => 'activate',
'moduleName' => 'AppCm',
'module' => 'App',
)
You have two intersected routes. They are both can parse this URL, but someone parse first, and stops an URL-recognition process. Default route parse URL first and returns
'module' => 'App',
'controller' => 'admin',
'action' => 'AppB',
Try to put defaultRoute initialization
/* #var Zend_Controller_Router_Rewrite $router */
$router->addDefaultRoutes();
/*init of '/:module/:controller/:action/*' route*/
after adding of all other routes .
Sometimes it is important to regulate route priority directly from config. To do this, you can add priority parameter in a routes config, for example:
'routes' => array(
'backend' => array(
'route' => $adminpath.'/:module/:controller/:action/*',
'priority' => 555
),
)
And sort a config by priority before the routes config would add to router ( $router->addConfig call ). In ZF2 route priority param is native.
We're using Zend Framework 2 and use toRoute within our controllers to redirect to various locations, for example $this->redirect()->toRoute('home');.
Is there anyway to have this redirect to https instead of http using this method or an alternative method?
Thank you!
In order to use https in your route you need to use the Zend\Mvc\Router\Http\Scheme router. Specifying the configuration for such route is not very different from the other routes. You need to specify the route type as Scheme and add an option 'scheme' => 'https' in your router configuration in module.config.php.
Here is an example:
return array(
'router' => array(
'routes' => array(
'routename' => array(
'type' => 'Scheme', // <- This is important
'options' => array(
'route' => '/url',
'scheme' => 'https', // <- and this.
'defaults' => array(
'__NAMESPACE__' => 'MdlNamespace\Controller',
'controller' => 'Index',
'action' => 'someAction',
),
),
),
// the rest of the routes
),
),
// the rest of the module config
);
If you have the route routename configured like above, this: $this->redirect()->toRoute('routename'); will work.
See this for reference to the ZF2's manual.
Hope this helps :)
Stoyan
I have a controller setup to accept two vars: /clients/view/var1/var2
And I want to show it as /var1/var2
SO i tried
Router::connect('/*', array('admin'=>false, 'controller' => 'clients', 'action' => 'view'));
But this stops all other controllers working as /* routes everything
All other pages that are on the site are within the admin prefix so basically i need a route that is ignored if the current prefix is admin! I tried this (regex is from Regular expression to match a line that doesn't contain a word?):
Router::connect('/:one', array('admin'=>false, 'controller' => 'clients', 'action' => 'view'), array(
'one' => '^((?!admin).*)$'
));
But I think the regex is incorrect because if i naviate to /test it asks for the tests controller, not clients
My only other routes are:
Router::connect('/admin', array('admin'=>true, 'controller' => 'clients', 'action' => 'index'));
Router::connect('/', array('admin'=>false, 'controller' => 'users', 'action' => 'login'));
What am I doing wrong? Thanks.
I misunderstood your question the first time. I tested your code and didn't get the expected result either. The reason might be that the regex parser doesn't support negative lookahead assertion. But I still think you can solve this with reordering the routes:
The CakeBook describes which routes are automatically generated if you use prefix routing. In your case these routes have to be assigned manually before the '/*'-route to catch all admin actions. Here is the code that worked for me:
// the previously defined routes
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/admin', array('controller' => 'clients', 'action' => 'index', 'admin' => true));
// prefix routing default routes with admin prefix
Router::connect("/admin/:controller", array('action' => 'index', 'prefix' => 'admin', 'admin' => true));
Router::connect("/admin/:controller/:action/*", array('prefix' => 'admin', 'admin' => true));
// the 'handle all the rest' route, without regex
Router::connect(
'/*',
array('admin'=>false, 'controller' => 'clients', 'action' => 'view'),
array()
);
Now I get all my admin controller actions with the admin prefix and /test1/test2 gets redirected to the client controller.
I think the solution is described in the bakery article on routing - "Passing parameters to the action" (code not tested):
Router::connect(
'/clients/view/:var1/:var2/*',
array(
'controller' => 'clients',
'action' => 'view'
),
array(
'pass' => array(
'var1',
'var2'
)
)
);
The controller action would look like:
public function view($var1 = null, $var2 = null) {
// do controller stuff
}
Also you have too look at the order of your routes (read section "The order of the routes matters"). In your example the '/*' stops all other routes if it comes first, if you assign the rule after the others it handles only requests which didn't match any other route.