Calling a method of a controller in Altorouter - php

I have been trying to get the index() method of the Home controller using the altorouter but am unable to. I have searched a few places but I could not find any help.
Here is the index.php
<?php
include 'system/startup.php';
include 'library/AltoRouter.php';
// Router
$router = new AltoRouter();
// Change here before upload
$router->setBasePath('/demo');
$router->map('GET|POST','/', 'home#index', 'home');
// match current request
$match = $router->match();
if( $match && is_callable( $match['target'] ) ) {
call_user_func_array( $match['target'], $match['params'] );
} else {
// no route matched
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
}
the home controller in the catalog>controller directory.
<?php
class home {
public function index() {
echo 'home';
}
}
Can anyone using or who ever used this altorouter guide?.
P.S. I have the autoload function in the startup.php file (included at the top of the index.php)

This is old thread but this can help you. You need match request in different way:
<?php
include 'system/startup.php';
include 'library/AltoRouter.php';
// Router
$router = new AltoRouter();
$router->setBasePath('/demo');
$router->map('GET|POST','/', 'home#index', 'home');
$match = $router->match();
if ($match === false) {
// here you can handle 404
} else {
list( $controller, $action ) = explode( '#', $match['target'] );
if ( is_callable(array($controller, $action)) ) {
call_user_func_array(array($controller,$action), array($match['params']));
} else {
// here your routes are wrong.
// Throw an exception in debug, send a 500 error in production
}
}

Related

Create dynamic page with php

I'm writing a small routing system for a project. It's not perfect and it's a custom solution that will map the url to their templates if requested from the user. I want to generate a dynamic page based on an unique id for each event inserted inside the database from the user. So if the user request the event 1234 it will get a page with the event detail at the url https://mysitedomain.com/event/1234. I need to understand how to achieve this with my code, I'm using a front controller and red bean as ORM to access the database.
Here is the code of my router. Any suggestion will be appreciated. for now I'm only able to serve the templates.
<?php
namespace Router;
define('TEMPLATE_PATH', dirname(__DIR__, 2).'/assets/templates/');
class Route {
private static $assets = ['bootstrap' => 'assets/css/bootstrap.min.css',
'jquery' => 'assets/js/jquery.min.js',
'bootstrapjs' => 'assets/js/bootstrap.min.js',
];
public static function init()
{
if( isset($_SERVER['REQUEST_URI']) ){
$requested_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH);
if( $requested_uri === '/' ){
echo self::serveTemplate('index', self::$assets);
}
elseif( $requested_uri != '/' ){
$requested_uri = explode('/', $_SERVER['REQUEST_URI']);
if( $requested_uri[1] === 'event' ){
echo self::serveTemplate('event', self::$assets, ['event_id' => 001] );
}
else{
echo self::serveTemplate($view, self::$assets);
}
}
}
}
private static function serveTemplate(string $template, array $data, array $event_id = null)
{
if( !is_null($event_id) ){
$data[] = $event_id;
ob_start();
extract($data);
require_once TEMPLATE_PATH."$template.php";
return ob_get_clean();
}
else{
ob_start();
extract($data);
require_once TEMPLATE_PATH."$template.php";
return ob_get_clean();
}
}
}
?>
Writing a router from scratch is a little complex, you have to play a lots with regular expression to accommodate various scenario of requested url and your router should handle HTTP methods like POST, GET, DELETE, PUT and PATCH.
You may want to use existing libraries like Fast Route, easy to use and it's simplicity could give you idea how it is created.

MVC indexController not using the correct action

I have two Actions in my IndexController.
public function indexAction()
{
$this->view->setVars([
'name' => 'Stefan',
]);
}
public function testAction()
{
$this->view->setVars([
'name' => 'testOutput',
]);
}
When going to call my index page
https://localhost/index/
It does output the name that i set in my views/index/index.php
<h1>Hello <?php echo $name ?></h1>
And i do get the output
Hello Stefan
Problem:
If i got to
https://localhost/index/test
I also get the same output even tho i cleary stated something else in my testAction
So he Acces the indexAction even if im in not calling the Action in my browser.
What i would want is, since i have echo $name; in my test.php file.
That i get the output
testOutput
Here would be my Autoloader.
Thank you in advance.
<?php
// simple autoloader
spl_autoload_register(function ($className) {
if (substr($className, 0, 4) !== 'Mvc\\') {
// not our business
return;
}
$fileName = __DIR__.'/'.str_replace('\\', DIRECTORY_SEPARATOR, substr($className, 4)).'.php';
if (file_exists($fileName)) {
include $fileName;
}
});
// get the requested url
$url = (isset($_GET['_url']) ? $_GET['_url'] : '');
$urlParts = explode('/', $url);
// build the controller class
$controllerName = (isset($urlParts[0]) && $urlParts[0] ? $urlParts[0] : 'index');
$controllerClassName = '\\Mvc\\Controller\\'.ucfirst($controllerName).'Controller';
// build the action method
$actionName = (isset($urlParts[1]) && $urlParts[1] ? $urlParts[1] : 'index');
$actionMethodName = $actionName.'Action';
try {
if (!class_exists($controllerClassName)) {
throw new \Mvc\Library\NotFoundException();
}
$controller = new $controllerClassName();
if (!$controller instanceof \Mvc\Controller\Controller || !method_exists($controller, $actionMethodName)) {
throw new \Mvc\Library\NotFoundException();
}
$view = new \Mvc\Library\View(__DIR__.DIRECTORY_SEPARATOR.'views', $controllerName, $actionName);
$controller->setView($view);
$controller->$actionMethodName();
$view->render();
} catch (\Mvc\Library\NotFoundException $e) {
http_response_code(404);
echo 'Page not found: '.$controllerClassName.'::'.$actionMethodName;
} catch (\Exception $e) {
http_response_code(500);
echo 'Exception: <b>'.$e->getMessage().'</b><br><pre>'.$e->getTraceAsString().'</pre>';
}
EDIT:
It really doesnt matter what i action i call after the index. it can be index/asdsad
And he still goes to the main indexAction.
It doesnt even say that he can't find the action.
EDIT2:
Output from var_dump($url,$urlParts,$controllerName,$actionMethodName)
string(0) ""
array(1) {
[0]=>
string(0) ""
}
string(5) "index"
string(11) "indexAction"

Routing via Php AltoRouter

I am trying to use a router (AltoRouter) for the first time and am unable to call any page.
Web folder structure
The Code
Index.php
require 'lib/AltoRouter.php';
$router = new AltoRouter();
$router->setBasePath('/alto');
$router->map('GET|POST','/', 'home#index', 'home');
$router->map('GET|POST','/', 'display.php', 'display');
$router->map('GET','/plan/', 'plan.php', 'plan');
$router->map('GET','/users/', array('c' => 'UserController', 'a' => 'ListAction'));
$router->map('GET','/users/[i:id]', 'users#show', 'users_show');
$router->map('POST','/users/[i:id]/[delete|update:action]', 'usersController#doAction', 'users_do');
// match current request
$match = $router->match();
if( $match && is_callable( $match['target'] ) ) {
call_user_func_array( $match['target'], $match['params'] );
} else {
// no route was matched
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
}
I have a file named plan.php (display plan) in the plan folder and the hyperlink that I am trying is
Plan <?php echo $router->generate('plan'); ?>
which does not work.
Can you help?
You cannot call plan.php by passing plan.php as an argument to match function
Check examples at http://altorouter.com/usage/processing-requests.html
If you want to use content from plan.php
you should use map in the following format
$router->map('GET','/plan/', function() {
require __DIR__ . '/plan/plan.php';
} , 'plan');
to the file plan/plan.php add echo 'testing plan';
Also, double check that your .htaccess file contains
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
Also, if you set base path with $router->setBasePath('/alto'); your index.php files should be placed in the alto directory so your url would be in that case http://example.com/alto/index.php
Working example:
require 'lib/AltoRouter.php';
$router = new AltoRouter();
$router->setBasePath('/alto');
$router->map('GET','/plan/', function( ) {
require __DIR__ . '/plan/plan.php';
} , 'plan');
// match current request
$match = $router->match();
if( $match && is_callable( $match['target'] ) ) {
call_user_func_array( $match['target'], $match['params'] );
} else {
// no route was matched
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
}
then this will work just fine
Plan <?php echo $router->generate('plan'); ?>

Why/Where does CodeIgniter set a 404 http status when the page is found?

I am using CodeIgniter2. I am using routing to route url segments to a controller and method.
This seems to work. My pages load as expected i.e. the url goes to the correct method to get the page info from the database, come back and display the correct page. My routes.php relevant code is:
$route['default_controller'] = "content";
$route['en/(:num)/(:any)'] = "content/en/$1";
$route['de/(:num)/(:any)'] = "content/de/$1";
$route['es/(:num)/(:any)'] = "content/es/$1";
$route['it/(:num)/(:any)'] = "content/it/$1";
$route['ar/(:num)/(:any)'] = "content/ar/$1";
$route['404_override'] = '';
HOWEVER instead of that displayed page showing a http status of 200, it shows a http status of 404 ... I have no idea why.
I suspect it is to do with a MY_Router.php file i have to give a custom error page but i can't work out what's going on.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Router extends CI_Router {
var $error_controller = 'error';
var $error_method_404 = 'error_404';
function My_Router()
{
parent::CI_Router();
}
// this is just the same method as in Router.php, with show_404() replaced by $this->error_404();
function _validate_request($segments)
{
// Does the requested controller exist in the root folder?
if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
{
return $segments;
}
// Is the controller in a sub-folder?
if (is_dir(APPPATH.'controllers/'.$segments[0]))
{
// Set the directory and remove it from the segment array
$this->set_directory($segments[0]);
$segments = array_slice($segments, 1);
if (count($segments) > 0)
{
// Does the requested controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT))
{
return $this->error_404();
}
}
else
{
$this->set_class($this->default_controller);
$this->set_method('index');
// Does the default controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT))
{
$this->directory = '';
return array();
}
}
return $segments;
}
// Can't find the requested controller...
return $this->error_404();
}
function error_404()
{
$this->directory = "";
$segments = array();
$segments[] = $this->error_controller;
$segments[] = $this->error_method_404;
return $segments;
}
function fetch_class()
{
// if method doesn't exist in class, change
// class to error and method to error_404
$this->check_method();
return $this->class;
}
function check_method()
{
$ignore_remap = true;
$class = $this->class;
if (class_exists($class))
{
// methods for this class
$class_methods = array_map('strtolower', get_class_methods($class));
// ignore controllers using _remap()
if($ignore_remap && in_array('_remap', $class_methods))
{
return;
}
if (! in_array(strtolower($this->method), $class_methods))
{
$this->directory = "";
$this->class = $this->error_controller;
$this->method = $this->error_method_404;
include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);
}
}
}
function show_404()
{
include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);
call_user_func(array($this->error_controller, $this->error_method_404));
}
}
/* End of file MY_Router.php */
/* Location: ./system/application/libraries/MY_Router.php */
Solved - the wordpress blog integrated in the site was setting the 404 status for all non wordpress pages i.e. codeigniter pages
index.php of CI had the following code which needed to be commented out
/*
*---------------------------------------------------------------
* WORDPRESS INTEGRATION
*---------------------------------------------------------------
* The ci_site_url function helps to avoid collision between WP & CI.
*/
//header("HTTP/1.0 200 OK");
define('WP_USE_THEMES', false);
require_once './blog/wp-blog-header.php';
add_filter('site_url', 'ci_site_url', 1);
function ci_site_url()
{
include(APPPATH.'/config/config.php');
return $config['base_url'];
}

altorouter routes doesn't work

i'm trying to use altorouter for set routing map of my php project, at this moment the file routes.php is this
<?php
$router = new AltoRouter();
$router->setBasePath('/home/b2bmomo/www/');
/* Setup the URL routing. This is production ready. */
// Main routes that non-customers see
$router->map('GET','/', '', 'home');
$router->map( 'GET', '/upload.php', 'uploadexcel');
$match = $router->match();
// call closure or throw 404 status
if( $match && is_callable( $match['target'] ) ) {
call_user_func_array( $match['target'], $match['params'] );
} else {
// no route was matched
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
}
?>
i have 2 files in the principal directory of my project, index.php and upload.php, what's wrong?
have you modified your .htaccess files to rewrite as per the altorouter site?
your routes look wrong. try like this:
// 1. protocol - 2. route uri -3. static filename -4. route name
$router->map('GET','/uploadexcel', 'upload.php', 'upload-route');
as it looks like you are wanting a static page (not a controller) try this (allows for both):
if($match) {
$target = $match["target"];
if(strpos($target, "#") !== false) { //-> class#method as set in routes above, eg 'myClass#myMethod' as third parameter in mapped route
list($controller, $action) = explode("#", $target);
$controller = new $controller;
$controller->$action($match["params"]);
} else {
if(is_callable($match["target"])) {
call_user_func_array($match["target"], $match["params"]); //call a function
}else{
require $_SERVER['DOCUMENT_ROOT'].$match["target"]; //for static page
}
}
} else {
require "static/404.html";
die();
}
which is pretty much from here: https://m.reddit.com/r/PHP/comments/3rzxic/basic_routing_in_php_with_altorouter/?ref=readnext_6
and get rid of that basepath line.
good luck
you car run class#function via "call_user_func_array":
if ($match) {
if (is_string($match['target']) && strpos($match['target'], '#') !== false) {
$match['target'] = explode('#', $match['target']);
}
if (is_callable($match['target'])) {
call_user_func_array($match['target'], $match['params']);
} else {
// no route was matched
header($_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
die('404 Not Found');
}
}

Categories