PHRoute can't route to controller 'Class not found ' - php

Having never used a router before outside of a traditional framework I've become a little stuck with PHRoute and routing to a controller. My code is as follows, I have a index.php which includes config files and bootstrap/app.php which contents are as follows:
require_once('../application/controllers/home.php');
$router = $app['router'];
$router->any('/home', ['Home','Application/Controllers/Home']);
function processInput($uri){
$uri = implode('/',
array_slice(
explode('/', $_SERVER['REQUEST_URI']), 1));
return $uri;
}
use Phroute\Phroute\Dispatcher;
$dispatcher = new Dispatcher($router->getData());
$response = $dispatcher->dispatch($_SERVER['REQUEST_METHOD'], processInput($_SERVER['REQUEST_URI']));
echo $response;
The problem is it can't find my home controller when I hit the /home route
Uncaught Error: Class 'Home' not found in /application/vendor/phroute/phroute/src/Phroute/HandlerResolver.php:16
In the above code I have done a simple require so I know the class is defiantly loaded into the script. The class looks like the following:
<?php
namespace Application\Controllers;
class Home
{
public function __construct(){
echo 'home construct';
}
public function index(){
echo 'index';
}
}
Am I missing something?

The problem is your route definition. The phroute documentation says:
// Lazy load autoloaded route handling classes using strings for classnames
// Calls the Controllers\User::displayUser($id) method with {id} parameter as an argument
$router->any('/users/{id}', ['Controllers\User','displayUser']);
Your route definition should be the classname (including the namespace) followed by the method to be invoked:
$router->any('/home', ['Application\Controllers\Home', 'index']);

Related

Get current route inside Controller Laravel

I have several routes in web.php:
Route::get('/','PagesController#index');
Route::get('/contact','PagesController#contact');
and so on...
I need to get in my PagesController the current 'module' (index, contact or smth else).
The Controller's code:
class PagesController extends Controller
{
public function index()
{
$menu = new Menu();
$links = $menu->getMenu();
//$header=url()->current(); // returns the full url, e.g. http://test.com/
//$header=Route::current(); // error: Class Route not found
return view("index",['links'=>$links,'header'=>$header]);
}
}
For example, $header should be equal to "/" inside PagesController#index and $header = "contact" inside PagesController#contact.
I need the universal solution for all the modules I'll have in future.
Thanks a lot!
I have not had a chance to test this, however you should be able to achieve this with the following:
Route::get('/{page?}', function($page = 'index') {
return app('App\Http\Controllers\PageController')->{$page}($page);
});
Basically, this is setting a route to have an optional $page variable. If no page name is passed (e.g. contact), we default to index.
We finally use the app() helper to call the PageController and then use the ->{$page}() syntax to call a dynamic controller method (In the default case index).
Hope this helps.

How does Symfony2 passes the parameter of a URI to the controller Action method?

I have started learning Symfony2. I came across a doubt: if I have this route:
# app/config/routing.yml
hello:
path: /hello/{name}
defaults: { _controller: AcmeHelloBundle:Hello:index }
And this controller:
// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
public function indexAction($name)
{
return new Response('<html><body>Ciao '.$name.'!</body></html>');
}
}
Internally Symfony2 (inside app/bootstrap.php.cache) calls the call user_func_array() PHP built-in function:
$arguments = $this->resolver->getArguments($request, $controller);
$response = call_user_func_array($controller, $arguments);
And the call to the getArguments() method returns an array of arguments to pass to the action method. But if the controller were:
// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
public function indexAction($n)
{
return new Response('<html><body>Ciao '.$n.'!</body></html>');
}
}
Symfony would have complained with a RuntimeException because no param $n is set.
My question is: how Symfony controls this behaviour, I mean, if a route has a {name} param, why the controller must have an action method with a $name parameter and the parameter must be called $name?
Cause in plain PHP, this would work:
$name = 'Alex';
function indexAction($n) {
echo $n;
}
$f = 'indexAction';
$arguments = array($name);
call_user_func_array($f, $arguments);
Even if the functions signature accepts a param named as $n and not as $name.
I hope that this question is understandable, if not, please tell me and I will make an edit.
Thanks for the attention!
It's all done in the Controller Resolver HttpKernel/Controller/ControllerResolver.php via getArguments() & doArguments().
For a better understanding, you will find what you need in Getting The Controller Arguments
Edit: Answer comment.
Does Symfony use the ReflectionParameter class internally in order to keep track of the params of the method's signature and match them with the route params?
Yes, the ControllerResolver uses:
ReflectionMethod to keep track of the params of the method's signature if $controller is a method
ReflectionObject if $controller is an object
ReflectionFunction if $controller is an function
Here is how:
public function getArguments(Request $request, $controller)
{
if (is_array($controller)) {
$r = new \ReflectionMethod($controller[0], $controller[1]);
} elseif (is_object($controller) && !$controller instanceof \Closure) {
$r = new \ReflectionObject($controller);
$r = $r->getMethod('__invoke');
} else {
$r = new \ReflectionFunction($controller);
}
return $this->doGetArguments($request, $controller, $r->getParameters());
}
The request is handled by the Symfony front controller (e.g. app.php);
The Symfony core (i.e. Kernel) asks the router to inspect the request;
The router matches the incoming URL to a specific route and returns information about the route, including the controller that should be executed;
The Symfony Kernel executes the controller, which ultimately returns a Response object.
Resource
In your example you only have one parameter on your action, so it's obvious to us that it needs to be populated from the route.
To extend your example, if you added another parameter to the route such as:
# app/config/routing.yml
hello:
path: /hello/{name}/{surname}
defaults: { _controller: AcmeHelloBundle:Hello:index }
And changed your controller to:
// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
public function indexAction($s, $n)
{
return new Response('<html><body>Ciao '.$n.' '.$s.'!</body></html>');
}
}
Symfony wouldn't know which variable $s or $n to populate with which route parameter.
If you change your action:
public function indexAction($surname, $name)
{
return new Response('<html><body>Ciao '.$name.' '.$surname.'!</body></html>');
}
Now, Symfony can look at your argument names and map them to the route parameters. It also means you can have your indexAction arguments in any order as long as their names match the route parameters. I believe Symfony internally uses the Reflection API to figure all this out.

How Action helper communicate with view helper

I create a action helper file path is
C:\xampp\htdocs\ecom\application\controllers\helpers
file name :Inputdata.php
class Zend_Controller_Action_Helper_Inputdata extends Zend_Controller_Action_Helper_Abstract
{
function Inputdata()
{
return $this;
}
function fetch_db_value($var)
{
if(get_magic_quotes_gpc()==0) {
return is_array($var) ? array_map(array($this,'fetch_db_value'), $var) : nl2br(stripslashes(trim($var)));
}else {
return is_array($var) ? array_map(array($this,'fetch_db_value'), $var) : nl2br(trim($var));
}
}
}
I am calling this function on controller giving output proper like :
$dbData=$this->_helper->Inputdata->fetch_db_value($dbData);
I have also a view helper, path is
C:\xampp\htdocs\ecom\application\views\helpers
file name : Comman.php
class Zend_View_Helper_Comman
{
public function displayProducts($res){
# Res is a array
foreach($res as $val){
# $val also is sub array of array $res
$val=$this->_helper->Inputdata->fetch_db_value($val);
print_r($val)
}
}
}
this function
$this->_helper->Inputdata->fetch_db_value
is giving error
any idea about syntax how to user action helper custom function in view helper custom function
syntax how call function displayProducts() on controller
Re: the action helper:
The namespace prefix on your action helper is Zend_. The autoloader will look for it in the location in which the Zend Framework library resides. In order for the autoloader - the resource loader, in this case - to look for the action helper in application/controllers/helpers, the namespace prefix has to be the appnamespace, typically Application_. So renaming the class to Application_Controller_Helper_Inputdata should do the trick.
Re: the view helper:
A similar thing applies. Typically, you would use the appnamespace prefix Application_. So renaming the class to Application_View_Helper_Comman should make the displayProducts() method accessible in a view-script as:
$this->comman()->displayProducts($res)
You mention referencing the view-helper method in a controller. This is typically not done; view-helpers are usually referenced only in view-scripts. However, if you really want to do it, you can access it via the View object. In a controller:
$this->_view->comman()->displayProducts($res)
If that view-helper is only going to contain that single displayProducts() method, then you can rename that class to be Application_View_Helper_DisplayProducts and reference the method in a view-script using:
$this->displayProducts($res)

Calling a class method for a route

I've used Slim for several projects and I always was connecting routes to class methods, by doing $app->route('/', array('MyClass', 'method'));
However, after installing it with composer, this is the error I'm getting:
call_user_func_array() expects parameter 1 to be a valid callback, non-static method Pages::home() should not be called statically
Here's the code:
class Pages {
function home() {
print 'home';
}
}
$app = new \Slim\Slim();
$app->get('/', array('Pages', 'home'));
$app->run();
Did I miss something? Should I edit my class additionally?
Thanks!
Looks like your error reporting is turned up higher than it has been in the past, as I believe the error you're getting is an E_STRICT error. If you changed your function home() method to public static function home() you'd no longer get the error.
That said, a better solution might be to try the new(-ish) controller feature in Slim 2.4.0. Your new route would look like this:
$app->get('/', '\Pages:home');
The code is wrong, you are passing an array as a parameter instead of the callback. Try passing a function.
Documentation for GET Routes:
http://docs.slimframework.com/#GET-Routes
class Pages {
function home() {
print 'home';
}
}
$app = new \Slim\Slim();
$app->get('/',function() {
$page = new Pages();
$page->home();
});
$app->run();

Zend Action Helpers not loading through Action HelperBroker

In my module bootstrap:
<?php
class Api_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initAllowedMethods()
{
$front = Zend_Controller_Front::getInstance();
$front->setParam('api_allowedMethods', array('POST'));
}
protected function _initActionHelperBrokers()
{
Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH . '/modules/api/controllers/helpers', 'Api_Controller_Action_Helper_');
Zend_Controller_Action_HelperBroker::addHelper(new Api_Controller_Action_Helper_Model());
}
}
There is a Api_Controller_Action_Helper_Model at /var/www/project/application/modules/api/controller/helpers/Model.php
But I get:
PHP Fatal error: Class 'Api_Controller_Action_Helper_Model' not found in /var/www/accounts.amh.localhost/application/modules/api/Bootstrap.php on line 15
As far as I can tell from the API and http://akrabat.com/zend-framework/using-action-helpers-in-zend-framework/ this should work.
I'm pretty sure this isn't a bootstrapping issue like I have had before, as I am specifically add the path/prefix right before trying to add the helper.
What else might I have missed?
The problem here is that the module autoloader does not know about controller action helper resources.
Try something like this in your module bootstrap
protected function _initResourceLoader()
{
$resourceLoader = $this->getResourceLoader();
$resourceLoader->addResourceType('actionhelper',
'controllers/helpers', 'Controller_Action_Helper');
}
All that being said, as your helper has an empty constructor, you could omit the addHelper() line and just let the broker automatically create it when requested in your controllers, eg
$helper = $this->getHelper('Model');

Categories