Giter VIP home page Giter VIP logo

ichi-route's Introduction

ICHI PHP ROUTER

ICHI PHP ROUTER is aimed to be the fast PHP Router with ease to use and protecting the security vulnerabilities

License

This package is Open Source According to MIT license

Table Of Content

Installation

composer require jijihohococo/ichi-route

Setting

You must create following htaccess file before setting route according to your server.

Apache

Create .htaccess file in your based folder


RewriteEngine On

RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

Nginx

Create .htacess file in your based folder


rewrite ^/(.*)/$ /$1 redirect;

if (!-e $request_filename){
	rewrite ^(.*)$ /index.php break;
}

Creating Controller

You must create the controller for your routes.

Firstly you need to created the file named "ichi" under your project folder and use the below code in this file

#!/usr/bin/env php
<?php

require __DIR__.'/vendor/autoload.php';

use JiJiHoHoCoCo\IchiRoute\Command\RouteCommand;


$routeCommand=new RouteCommand;
$routeCommand->run(__DIR__,$argv);

And then you can create the controller in your commandline

php ichi make:controller ItemController

The default file folder is "app/Controllers". So after making command, the controller you created will be in the this default file folder. If you want to change the default folder path, you can change it in your "ichi" file.

$routeCommand=new RouteCommand;
$routeCommand->setPath('new_app/Controllers');
$routeCommand->run(__DIR__,$argv);

Single Route

You can add routes with "get","post","put","delete" and "head" functions.

Each function represents the each route method

You can add route with closure function or the function of controller class.

With closure function

use JiJiHoHoCoCo\IchiRoute\Router\Route;

$route=new Route;
$route->get('items',function(){
	echo "show items";
});

With Controller class

$route->get('items','App\Controllers\ItemController@show');

You must autoload your the controller folder before using the route function in your composer.json

"autoload": {
	"psr-4": {
		"App\\": "app/"
	}
}

If you have the same controller path for all controllers, you can set base controller path for all routes before adding routes.

$route->setBaseControllerPath('App\Controllers');

To run all of your routes, you must use "run()" function.

You must use "run()" function after declaring all routes for your system

$route->run();

After running route function, the routes (URL) are able to run

'items/' (GET METHOD)

PATCH Method

To make PATCH method , you need __method request and add 'PATCH' values in this. And the action must 'POST'.

In your route

$route->patch('items','App\Controllers\ItemController@show');

For the form data

<form action="<?php echo route('items'); ?>" method="POST">
	<?php method('PATCH'); ?>
</form>

PUT Method

To make PUT method , you need __method request and add 'PUT' values in this. And the action must 'POST'.

In your route

$route->put('items','App\Controllers\ItemController@show');

For the form data

<form action="<?php echo route('items'); ?>" method="POST">
	<?php method('PUT'); ?>
</form>

DELETE Method

To make DELETE method , you need __method request and add 'DELETE' values in this. And the action must 'POST'.

In your route

$route->delete('items','App\Controllers\ItemController@show');

For the form data

<form action="<?php echo route('items'); ?>" method="POST">
	<?php method('DELETE'); ?>
</form>

Using Routes

Calling routes in frontend

<a href="<?php echo route('items'); ?>">Items</a>

Route Parameter

In many cases, you have a time to make route parameters

$route->get('items/show/{id}','App\Controllers\ItemController@show');

In your controller class

namespace App\Controllers;

class ItemController{

	// 'items/show/{id}' //
	public function show($id){
		echo $id;
	}
}

You can also do with closure function

$route->get('items/show/{id}',function($id){
	echo $id;
})

After running route function, the routes (URL) are able to run

'items/show/1' (GET METHOD)
'items/show/2' (GET METHOD)

Calling routes in frontend

<a href="<?php echo route('items/show/1'); ?>" >Item 1</a> 
<a href="<?php echo route('items/show/2'); ?>" >Item 2</a> 

Resource Route

You can CRUD routes with one route method

$route->resource('items','App\Controllers\ItemController');

In your controller class

namespace App\Controllers;

class ItemController{

	// GET METHOD //
	// 'items' //
	public function index(){

	}

	// GET METHOD //
	// 'items/create' //
	public function create(){

	}

	// POST METHOD //
	// 'items/create' //
	public function save(){

	}

	// GET METHOD //
	// 'items/{id}/edit'
	public function edit($id){

	}

	// PUT METHOD //
	// 'items/{id}/edit' //
	public function update($id){

	}

	// DELETE METHOD //
	// 'items/{id}/destroy' //
	public function destroy($id){

	}


}

You can also create the resource controller in terminal after making according to the insturctions from Creating Controller

php ichi make:controller ItemController --resource

After running route function, the routes (URL) are able to run

	
	'items/' (GET METHOD) // Go to to get items' list
	'items/create' (GET METHOD) // Go to create item
	'items/create' (POST METHOD) // Create items
	'items/1/edit' (GET METHOD) // Go to update item
	'items/1/edit' (PUT METHOD) // Update item
	'items/1/destroy' (DELETE METHOD) // Delete item

You can also create the api resource controller in terminal after making according to the insturctions from Creating Controller

php ichi make:controller ItemController --api-resource

After running route function, the routes (URL) are able to run

	
	'items/' (GET METHOD) // Go to to get items' list
	'items/create' (POST METHOD) // Create items
	'items/1/edit' (GET METHOD) // Go to update item
	'items/1/edit' (PUT METHOD) // Update item
	'items/1/destroy' (DELETE METHOD) // Delete item

Prefix Route

You can use prefix route to make groups

$route->group(['url_group'=>'admin'],function(){
	
	$this->get('items','App\Controllers\ItemController@getItems');
	$this->get('brands','App\Controllers\BrandController@getBrands');
});

So the below url are able to use

'admin/items' (GET METHOD)
'admin/brands' (GET METHOD)

You can add the routes in the group closure function.

Don't include '/' in declaring "url_group"

Subdomain Route

You must set your main domain name before declaring routes if you want to use subdomains.

use JiJiHoHoCoCo\IchiRoute\Router\Route;

$route=new Route;
$route->setDefaultDomain('your_main_domain.com');

Single Subdomain

You can set your subdomain routes with "domain()" function

You can use all route functions within "domain()" function

You can't use domain function within group function

$route->domain('your_subdomain.com',function(){
	$this->get('items','Subdomain/ItemController@get');
});

If you want to show your subdomain route, use getSubdomainRoute function. First parameter is domain name and second parameter is declared route under this subdomain.

<a href="<?php echo getSubdomainRoute('your_subdomain.com','items'); ?>" >Subdomain Items</a>

Subdomain Parameter

If you want to use parameter in your subdomain

Parameters are embrace with "{" and "}" as route parameters

You must pass subdomain parameters into the closure function or class's function

Class's function

$route->domain('{subdomain}.com',function(){
	$this->get('items','Subdomain/ItemController@get');
});
namespace App\Controllers\Subdomain;

class ItemController{

	public function get($subdomain){

	}
}

Closure function

$route->domain('{subdomain}.com',function(){
	$this->get('items',function($subdomain){

	});
})

If you want to use multiple subdomain parameters, use '.' between parameters and string

Class's function

$route->domain('{subdomain}.{person}.com',function(){
	$this->get('items','Subdomain/ItemController@get');
});
namespace App\Controllers\Subdomain;

class ItemController{

	public function get($subdomain,$person){

	}
}

Closure function

$route->domain('{subdomain}.{person}.com',function(){
	$this->get('items',function($subdomain,$person){

	});
});

If you want to use route parameters in subdomain parameters, You must pass subdomain parameters and also route parameters in your class's function or closure function

Class's function

$route->domain('{subdomain}.{person}.com',function(){
	$this->get('items/{id}','Subdomain/ItemController@get');
});
namespace App\Controllers\Subdomain;

class ItemController{

	public function get($subdomain,$person,$id){

	}
}

Closure function

$route->domain('{subdomain}.{person}.com',function(){
	$this->get('items/{id}',function($subdomain,$person,$id){

	});
});

If you want to get subdomain parameters in your middleware which are under that subdomain routes

In your middleware class

namespace App\Middlewares;

use JiJiHoHoCoCo\IchiRoute\Middleware\MainMiddleware;

class TestMiddleware extends MainMiddleware{

	public function handle(){
		$subdomainParameters=$this->getDomainParameters();
	}
}

You can't pass subdomain parameters into your middleware like you can do with your route parameters

Dependency Injection

You can make dependency injection with controller class.

You must have interface and class according to the below format

Your interface and class must be autoloaded

Interface Class
ItemInterface Item
ItemRepositoryInterface Item Repository

The functions of class that dependency injected will automatically run

In your controller class

namespace App\Controllers;

use App\Repositories\ItemRepositoryInteface;
class ItemController{

	public $item;
	public function __construct(ItemRepositoryInteface $item){
		$this->item=$item;
	}
}

You can also add another dependency injection in your repositories.

namespace App\Repositories;

use App\Repositories\{ItemRepositoryInteface,BrandRepositoryInterface};

class ItemRepository implements ItemRepositoryInteface{

	public $brand;

	public function __construct(BrandRepositoryInterface $brand){
		$this->brand=$brand;
	}
}

Middleware

You can add middlewares in single route like below

$route->get('order','App\Controllers\OrderController@order',[
'App\Middlewares\OrderMiddleware'
]);

You must delcare middleware class

Your middleware classes must be autoloaded in composer as we mentioned before

namespace App\Middlewares;

use JiJiHoHoCoCo\IchiRoute\Middleware\MainMiddleware;

class OrderMiddleware extends MainMiddleware{

	public function handle(){
		//--check your business logic--//
		return $this->next();
	}
}

You must extend JiJiHoHoCoCo\IchiRoute\Middleware\MainMiddleware and add "handle()" function. In your "handle" function, you must always return "next()" function. You can check your business transactions in this "handle" function.

You can create the middleware via terminal after creating "ichi" file as we mentioned in Creating Controller

php ichi make:middleware OrderMiddleware

The default path for observer is "app/Middlewares". You can also change this in "ichi" file.

$routeCommand=new RouteCommand;
$routeCommand->setResourcePath('new_app/Middlewares');
$routeCommand->run(__DIR__,$argv);

You can add multiple middleware classes

$route->get('order','App\Controllers\OrderController@order',[
	'App\Middlewares\LoginMiddleware',
	'App\Middlewares\OrderMiddleware'
]);

Those middlewares will be loaded sequently because of using "next()" function in each "handle()" function.

You can add parameters in middleware with your route parameters

$route->get('items/{id}','App\Controllers\ItemController@getItems',[
	'App\Middlewares\CheckItemMiddleware:id'
]);

In your middleware class

namespace App\Middlewares;

use JiJiHoHoCoCo\IchiRoute\Middleware\MainMiddleware;

class CheckItemMiddleware extends MainMiddleware{

	public function handle($id){
		//--check your business logic--//
		return $this->next();
	}

}

You can add multiple parameters in middleware with your route parameters

$route->get('items/{id}/{stock_id}',
	'App\Controllers\ItemController@getItems',[
	'App\Middlewares\CheckItemMiddleware:id,stock_id'
]);

In your middleware class

namespace App\Middlewares;

use JiJiHoHoCoCo\IchiRoute\Middleware\MainMiddleware;

class CheckItemMiddleware extends MainMiddleware{

	public function handle($id,$stock){
		//--check your business logic--//
		return $this->next();
	}

}

You can add middlewares in prefix routes like the way you do in single routes and parameter routes

$route->group(['url_group' => 'admin' , 
	'middleware' => ['App\Middlewares\CheckAdminMiddleware']
 ],function(){
 	$this->resource('items','App\Controllers\ItemController');
 });

You can add only middleware in prefix routes.

$route->group(['middleare' => ['App\Middlewares\CheckUserMiddleware'] ],function(){
	$this->get('order','App\Controllers\OrderController@order');
});

If you have the same middleware path for all middlewares, you can set base middleware path for all routes before adding routes.

$route->setBaseMiddlewarePath('App\Middlewares');

There are some middlewares that already written in this library. For those middlewares you must declare their middleware path completely.

If you have the middlewares that you want to check for all routes

If you don't delcare base middleware path

$route->defaultMiddlewares([
'App\Middlewares\CheckUserMiddleware'
]);

If you declare base middleware path

$route->defaultMiddlewares([
'CheckUserMiddleware'
]);

CSRF Token Authentication

You can protect create and update route with CSRF Token Authentication

You must generate CSRF Token before declaring the routes

use JiJiHoHoCoCo\IchiRoute\Router\Route;

generateCSRFToken();

$route=new Route;
$route->post('items','App\ItemController@create',[
'JiJiHoHoCoCo\IchiRoute\Middleware\CSRFMiddleware'
]);

You can add JiJiHoHoCoCo\IchiRoute\Middleware\CSRFMiddleware in your prefix routes too.

use JiJiHoHoCoCo\IchiRoute\Router\Route;

generateCSRFToken();

$route=new Route;
$route->group(['middleare' => 
	['JiJiHoHoCoCo\IchiRoute\Middleware\CSRFMiddleware'] ],function(){
	$this->post('items','App\ItemController@create');
});

In your frontend php file

<form action="<?php echo route('items'); ?>" method="POST" >
	<?php csrfToken(); ?>
	<input type="text" name="name">
	<input type="submit" name="submit">
</form>

API Request Authentication

You can add middleware to accept only API request for your route

$route->get('items_api','App\Controllers\ItemController@getItems',[
	'JiJiHoHoCoCo\IchiRoute\Middleware\APIMiddleware'
]);

To pass JiJiHoHoCoCo\IchiRoute\Middleware\APIMiddleware, you must add "application/json" value in your "Content-Type" header when you request that api route

CORS

You can make CORS to get your data from another domains

$route->get('items_api','App\Controllers\ItemController@getItems',[
	'JiJiHoHoCoCo\IchiRoute\Middleware\CORSMiddleware'
]);

You can make options for your CORS with JiJiHoHoCoCo\IchiRoute\Setting\CORS

 
use JiJiHoHoCoCo\IchiRoute\Setting\CORS;

CORS::setAvialableSites(['http://domain-one.com','http://domain-two.com']);
// To set Access Control Allow Origins (default is '*')

CORS::setAvailableSitesRegex(['/w3schools/']);
// To set Access Control Allow Origins according to regex

CORS::setAvialableMethods(['GET','POST']);
// To set Access Control Allow Origin Methods (default is '*')

CORS::setAvailableHeaders(['X-Custom-Header','Upgrade-Insecure-Requests']);
// To set Access Control Allow Origin Headers (default is '*')

CORS::setToAllowCredential();
// To set Access Control Allow Credentials to TRUE. (default is 'false')

CORS::setMaxAge(3600);
// To set Access Control Max Age (default is 0)

Caching Route

You can cache parameter routes with

  1. Database
  2. Redis
  3. Memcached

You must do following instructions before adding routes

Caching with Database

You must run this SQL code to create "ichi_routes" table in your database

CREATE TABLE IF NOT EXISTS ichi_routes( 
	id   INT AUTO_INCREMENT,
	route_key  VARCHAR(100) NOT NULL,
	route_method VARCHAR(100) NOT NULL,
	expired_time VARCHAR(100) NULL,
	PRIMARY KEY(id))

And add your pdo object with expired time in seconds

$route->setPDO($pdoObject,10000);

You can also make without expired time

$route->setPDO($pdoObject);

Caching with Redis

Add your redis object with expired time in seconds

$route->setRedis($redisObject,10000);

You can also make without expired time

$route->setRedis($redisObject);

Caching with Memcached

Add your memcached object with expired time in seconds

$route->setMemcached($memcachedObject,10000);

You can also make without expired time

$route->setMemcached($memcachedObject);

Error Page Customization

You can call the error page (whatever it is default or customized)

use JiJiHoHoCoCo\IchiRoute\UI\ErrorPage;

echo ErrorPage::show();
exit();

Default eror message is "404 - URL is not found". Default HTTP response code is 404.

You can customize error message and HTTP response code

use JiJiHoHoCoCo\IchiRoute\UI\ErrorPage;

echo ErrorPage::show('403 - Unauthorized Request',403);
exit();

If you don't like the default error page from this library,you can show the own error page

use JiJiHoHoCoCo\IchiRoute\UI\ErrorPage;

ErrorPage::setErrorPage('<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>

<h1>404</h1>
<p>404 URL</p>

</body>
</html>');

If you want to show more specific error according to your HTTP response code, you must create a function

use JiJiHoHoCoCo\IchiRoute\UI\ErrorPage;

$errorPage=function($message,$code){
		return <<<HTML
			<html>
			<meta name="viewport" content="width=device-width, initial-scale=1.0"> 
			<title>$message</title>
			<body style="background-color: white;">
			<div style="position: fixed;top:50%;left:50%;transform: translate(-50%, -50%);color:black;font-family: 'Nunito', sans-serif;">
			<p>$message</p>
			</div>
			</body>
			</html>
			HTML;
	};

ErrorPage::setErrorPage($errorPage);

In your customized function, you must have "$message" and "$code" parameters

ichi-route's People

Contributors

jijihohococo avatar

Stargazers

 avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.