ashish336b/carpo-php

There is no license information available for the latest version (v1.1.8) of this package.

This is small php framework for api based development

v1.1.8 2021-05-12 15:08 UTC

README

This is simple php closure based framework for api development

Installation

composer create-project ashish336b/carpo-php-framework blog

With this Installation is completed. Run the command to open web server in port 1212.

php -S localhost:1212 -t public/

Project Folder Structure.

├───app
│ ├───controller
│ ├───middleware
│ ├───model
│ └───views
├───public
└───vendor

  • app/controller contains all your controller class for project
  • app/middleware contains all your middleware class fro project.
  • app/views contains all views files for project.

with this Full installation is completed.

Routes

You can create routes by calling static class Application

use ashish336b\PhpCBF\Application as App;
App::get("/", function (Request $request, Response $response) {
   echo "My First Route.";
});

Methods

App::get("/urlPattern" , function(){});
App::post("/urlPattern" , function(){});
App::put("/urlPattern" , function(){});
App::delete("/urlPattern",function(){});

There is also another method you can access from \ashish\PhpCBF\Application class

App::on("EVENT_TYPE" , function(){});

EVENTTYPE can be either BEFORE or AFTER

  • BEFORE : This event run before all application middleware and routes. Best usecase to set CORS header.
  • AFTER : If you need to run a piece of code after running your middleware and routes function use this. For example global response header is set here

URL Pattern

  • Url pattern is used to define routes. Both static pattern and dynamic pattern can be defined mostly same as laravel.

  • static Routes: App::get("/users", Closure);

    baseurl/users url is dispatched with this pattern.

  • Variable Routes: APP::get("/home/{id}", closure) baseurl/home/1orbaseurl/home/2` ... is dispatch.

  • You cannot register two same pattern.

Optional Pattern.

  • App::get("/user/{id?}" , closure);
    both baseurl/user/1 and baseurl/user are dispatched here id params is optional.
  • You should not define any required placeholder/params after optional placeholder/params.
    /user/{id?}/{userId} This is completely wrong.
    /user/{userId}/{id?} This is correct way.
  • It is good practice to have only one optional params in pattern and it must be last placeholder.
  • However two or more optional params are supported if only one required params appears before any optional params. Using more than one optional params may lead to confusion and hard to debug so is not recommended
  • You cannot register static Routes after any variable routes that matches static route pattern. Example:
    suppose this variable pattern is defined at firstuser/{id} and you define another pattern user/home which matches``user/{id}` It gives you error.
  • However you can define user/home at first and then user/{id}. This is completely fine.

Routes Group

  • Your can define routes group just like in other famous framework like laravel, slim. etc.
  • First Params is array which can have two keys params and middleware.
  • Params : For defining common url pattern that appears in every routes group.
  • Middleware : name of middleware class that is inside /App/middleware/ namespace.
App::group(["prefix"=>"/admin"],function(){
   // every GET POST PUT DELETE methods routes can be define.
   App::get("/login",Closure);
   //dispatch /admin/login
   App::get("/login/{id}", Closure);
   //dispatch /admin/login/1 , /admin/login/anything etc.
});
  • get, post , put and delete method have two parameters. url pattern and closure respectively.
  • closure can have two paramas $request and $response of type Request and Response respectively
App::get("/user/{id}/{anotherParams}", function (Request $request, Response $response) {
   // Access params value with $request->params.
   $request->params->id;
   $request->params->anotherParams;
});

Controller

You can create controller class inside app/controller with namespace namespace App\controller;

<?php

namespace App\controller;

use ashish336b\PhpCBF\Request;
use ashish336b\PhpCBF\Response;

class AdminController
{
  public function index(Request $request, Response $response)
  {
     $request->url = $request->getUrl();
     return $response->toJSON($request);
  }
  public function user(Request $request, Response $response)
  {
     echo $response->render("/admin", ['fullUrl' => $request->fullURL]);
  }
}

you can define class and method to execute in route with classname@methodname.

App::get("/admin/user", "AdminController@user");
  • In routes "AdminController@user" means AdminController is directly inside controller folder which have user method that is to be executed for response.

  • If your controller is inside /app/controller/user/UserController.php and method is index that is to be executed then

App::get("/user", "user\UserController@index")

Model

This contains data related logic such as retriving data from database and passing to controller.
you have to create model class inside model folder. This folder can contain sub folder to group models.

<?php

namespace App\model;

use ashish336b\PhpCBF\DB;
use ashish336b\PhpCBF\Model;

class Auth extends Model
{
   protected $table = "user";
   public function fetchUser()
   {
      //directly run query from model
      return $this->query("select * from user")->results();
      // fetch all row of table specified in $table
      return $this->fetch();
      // get columns of table
      return $this->getColumns();
   }
}

To access model function from controller.

$user  = $this->model("Auth")->fetchUser();

Here Auth is the name of file that is inside model folder and fetchUser() is method inside Auth file/class.

$this->model("Admin\Auth")->fetchUser();

In above case Auth class is inside Admin folder which is inside model folder.

Database

This framework mainly support mysql database. However you can integrate any database with the help other open source project.

  • To fetch all data from table(eg. user)
DB::table("user")->get();
  • To run any query
$result = DB::raw()->query("select * from user where id =  ?",[1])->result();
  • count result
$noOfRow = DB::raw()->query("select * from user")->count();

Migration

you can use migration to run create table, alert etc. every migration should be inside app/migration directory.

<?php

namespace App\migrations;

use ashish336b\PhpCBF\Application;

class create_user_table
{
   public function up()
   {

      $SQL = "CREATE TABLE users (
               id INT AUTO_INCREMENT PRIMARY KEY,
               firstname VARCHAR(255) NOT NULL,
               lastname VARCHAR(255) NOT NULL,
               email VARCHAR(255) NOT NULL,
               created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
               updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )";
   Application::$pdo->exec($SQL);
   }

   public function down()
   {
      $SQL = "DROP TABLE users;";
      Application::$pdo->exec($SQL);
   }
}

every migration should be created in this manner. Till now sub directory is not allowed to store migration. Every migration should be in app/migrations directory.

Middleware

Middleware provide a convenient mechanism for filtering HTTP requests entering your application. For Example if you want to check if user is authenticated or not you can check it in middleware. If user is not authenticated you can throw response of 403 which does not allow routes closure to execute.

Your can define Middleware in routes groups as well as individual routes.

App::group(["prefix"=>"/admin","middleware"=>["Auth"]],function(){
   App::get("/",function(){
      echo "/admin";
   })
});

Auth class should be inside app/middleware/Auth.php with namespace namespace app\\middleware\\;

  • Middleware should always return true if none of the condition meets.
<?php

namespace App\middleware;

use ashish336b\PhpCBF\Request;
use ashish336b\PhpCBF\Response;

class Auth
{
   public function run(Request $request, Response $response)
   {
      $auth = false;
      if(!$auth){
         return $response->toJSON(["message" => "not authenticated"]);
      }
      return true;
   }
}
  • You can define middleware in individual middleware in get,post,put and delete method.
App::get("/user","UserController@index",["Guest"]);

Request

Request and Response can be accessed in both controller method and closure from parameter.

-return url without get params. eg. /admin/index

$request->getUrl();
  • Return all body from post request as object.
$request->body
  • Access Body with name. If BODY_NAME is in object of $request->body then it return value else return null.
$request->body("BODY_NAME");
  • Get all get params from url as object.
$request->query
  • Return get query params value. If QUERY_NAME is not set it return null
$request->query("QUERY_NAME");
  • return all request headers as object.
$request->allHeaders();
  • Return header value. If not set return false
$request->header("Header_NAME");

Response

Response class have two method as of now.

  • Return object to json.
$response->toJSON($obj);
  • render method return view containing html files. Accept two params first is path of folder from view folder and another is associative array.
$response->render("/admin",array);
  • /admin is file from /app/view/admin.php
  • /admin/login is file from /app/view/admin/login.php

views

  • views have three method render() , include() and extend().
  • render() is already explainded in Response documentation.
  • include() method is called inside view file to include files. Usually done for including header and footer.
    views/admin.php
<body>
<?php $this->include("/partials/header") ?>
<h1>MVC Framework <?php echo $ok ?></h1>
<?php $this->include("/partials/footer") ?>
</body>
  • Example : include header.php inside views/partials/header.php.
  • Extend method is used for extending layouts. This replace {{any_string}} with content that comes after calling extend() method and before end() method in views file Example. layout.php
<?php $this->include('partials/header'); ?>
{{any_string}}
<?php $this->include("partials/footer") ?>
  • Extending above layout.php view file.
<?php $this->extend("any_string", "partials/layout"); ?>
<h1>Body <?php echo $ok ?></h1>
<?php $this->end() ?>
  • replace {{any_string}} with <h1>Body <?php echo $ok ?></h1>

License & copyright

Copyright (c) Ashish Bhandari

Licensed under the MID License.