1. Go to this page and download the library: Download lark/framework library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
// routes for HTTP specific methods:
router()->delete('/route', function(){});
router()->get('/route', function(){});
router()->head('/route', function(){});
router()->options('/route', function(){});
router()->patch('/route', function(){});
router()->post('/route', function(){});
router()->put('/route', function(){});
// route for all HTTP methods
router()->all('/route', function(){});
// route for multiple HTTP methods
router()->route(['GET', 'POST'], '/route', function(){});
// a wildcard route "*" can be used to match any route
router()->get('*', function(){}); // all HTTP GET methods
router()->all('*', function(){}); // all HTTP methods (all requests)
router()->route(['GET', 'POST'], '*', function(){}); // all HTTP GET and POST methods
// match all routes that begin with "/api"
router()->get('/api.*?', function(){});
class MyController implements Lark\Router\RouteControllerInterface
{
public function bind(Router $router): void
{
$router->get('/users', function(){}); // "/api/users"
}
}
// in routes file
router()
->group('/api')
->controller(new MyController);
// function will be called on route match
router()->get('/example-html', function(): string {
return 'hello'; // return string to output as html
});
router()->get('/example-json', function(): array {
return ['message' => 'hello']; // return array|stdClass to output as JSON
// will auto add header "Content-Type: application/json"
// and response body will be:
// {"message": "hello"}
});
// class method "App\Controller\ExampleController::hello()" will be called on route match
router()->get('/example2', [App\Controller\ExampleController::class, 'hello']);
// match digits
router()->get('/users/(\d+)', function(int $id){});
// or match alphanumeric with length of 8
router()->get('/users/([a-z0-9]{8})', function(string $id) {});
// executed always
router()->bind(function(Lark\Request $req, Lark\Response $res){});
// executed if any route is matched
router()->matched(function(Lark\Request $req, Lark\Response $res){});
// define routes
// ...
// single action
router()->bind(function(){});
// multiple actions
router()->bind(function(){}, [MyClass::class, 'myMethod']);
// array of actions
router()->bind([
function(){},
function(){}
]);
namespace App;
use Throwable;
class ExceptionHandler
{
public function __construct(Throwable $th)
{
\Lark\Exception::handle($th, function (array $info) use ($th)
{
$code = $th->getCode();
if (!$code)
{
$code = 500;
}
// log error
// ...
// respond with error
res()
->code($code)
->json($info);
// --or-- continue to throw exception
throw $th;
});
}
}
use Lark\Debugger;
// append debugger info
Debugger::append(['some' => 'info'])
->name('Test info') // this will be displayed as title (optional)
->group('test'); // this will group info together (optional)
Debugger::append(['more' => 'info'])
->name('More test info')
->group('test');
Debugger::dump(); // dump all debugger info and exit
// or use:
// x(); // dump all debugger info and exit
app()->use('debug.dump', true);
app()->use('debug.log', true);
// setup default MongoDB database connection with connectionId "default"
// the first registered connection is always the default connection
// regardless of connectionId
app()->use('db.connection.default', [
'hosts' => ['127.0.0.1'],
'username' => 'test',
'password' => 'secret',
'replicaSet' => 'rsNameHere', // (optional)
// options can override any global database options
// (optional, see "Database Global Options" below)
'options' => []
]);
// register second connection with connectionId "myconn"
app()->use('db.connection.myconn', [...]);
// ...
// use default connection (no connectionId
use MongoDB\Driver\ReadConcern;
use MongoDB\Driver\WriteConcern;
app()->use('db.options', [
'db.allow' => [], // allow access to only specific databases
'db.deny' => ['admin', 'config', 'local'], // restrict access to databases
'debug.dump' => false, // will write concern
]);
$path = env('PATH');
// or use default value "/my/path" if environment variable does not exist
$path2 = env('PATH2', '/my/path');
// for variable key "PATH2"
// example request:
// POST /example
// Content-Type: application/json
// {"name": "Test", "contact": {"email": "[email protected]"}}
$data = req()->json(); // get all as object/array (no auto sanitizing)
// request JSON must be an array or 400 response is sent
$data = req()->jsonArray();
// request JSON must be an object or 400 response is sent
$data = req()->jsonObject();
// get individual field
$name = req()->jsonField('name')->string();
if(req()->jsonField('contact.email')->has())
{
$email = req()->jsonField('contact.email')->email();
}
app()->session()->flash()->set('userError', 'Invalid session');
// redirect, then use message
echo app()->session()->flash()->get('userError');
// message is no longer available on next request
// set header, status code 200, content-type and send JSON response
res()
->header('X-Test', 'value')
->code(Lark\Response::HTTP_OK)
->contentType('application/json') // not
// bootstrap
// setup default MongoDB database connection with connectionId "default"
app()->use('db.connection.default', [...]);
// register second connection with connectionId "myconn"
app()->use('db.connection.myconn', [...]);
// ...
// get Database object instance
$db = db('myDb$users');
// delete documents (note: filter cannot be empty)
$affected = $db->delete(['role' => 'admin']);
// delete documents by IDs
$affected = $db->deleteIds(['62ba4fd034faaf6fc132ef54', '62ba4fd034faaf6fc132ef55']);
// delete single document
$affected = $db->deleteOne(['name' => 'Test2']);
// delete all documents in collection
$affected = $db->deleteAll();
// create a new field
// set default value to empty array
$affected = $db->collectionField('tags')->create([]);
// delete a field
$affected = $db->collectionField('tags')->delete();
// check if a field exists on all documents
$exists = $db->collectionField('tags')->exists();
// check if a field exists on any document
$exists = $db->collectionField('tags')->exists(false);
// remove value "mytag" from field "tags" array
$affected = $db->collectionField('tags')->pull(
['id' => '62ba4fd034faaf6fc132ef54'],
'mytag'
);
// append values "mytag1" and "mytag2" to field "tags" array
// these values will only be appended if they
// don't already exists in the array
// use $unique=false to always append
$affected = $db->collectionField('tags')->push(
['id' => '62ba4fd034faaf6fc132ef54'],
['mytag1', 'mytag2']
);
// rename a field
$affected = $db->collectionField('tags')->rename('tagsNew');
$schema = new Schema([
'$import' => [
// field => file (in schemas directory)
'info' => 'partials/users.info'
],
'name' => ['string', 'notEmpty'],
// field for schema import (optional, does not need to be set here)
'info' => null
]);
// ...
class Model extends Model
{
const DBS = 'default$app$users';
public function get(string $id): ?array
{
return $this->db()->findId($id);
}
}
// get user document
$user = (new App\Model\User)->get('62ba4fd034faaf6fc132ef55');
// external calls: get documents
$docs = (new \App\Model\User)->db()->find(['role' => 'admin']);
class ExampleModel extends Model
{
public static function &schema(): Schema
{
return parent::schema([
'id' => ['string', 'id'],
// ...
]);
}
}
class ExampleModel extends Model
{
const SCHEMA = 'users.php';
public static function &schema(): Schema
{
return parent::schema(function(Schema &$schema)
{
$schema->apply('name', function($name)
{
return strtoupper($name);
});
});
}
}
use Lark\Database\Query;
use App\Model\User;
$query = new Query(new User, [
'name' => 'test'
]);
// Database::find()
$results = $query->find();
// Database::count()
$count = $query->count();
$isValid = (new Validator([
'name' => 'test',
'tags' => [
// these must be arrays because "schema:array" is used
// if "schema:object" is used these must be objects
['id' => '1', 'name' => 'test2'],
['id' => 2, 'name' => 'test3'],
]
], [
'name' => ['string', 'notEmpty'],
'tags' => [
'array', 'notEmpty',
[
'schema:array' => [
'id' => ['int', 'notNull'],
'name' => 'string'
]
]
]
]))->assert();
// throws Lark\Validator\ValidatorException:
// Validation failed: "tags.0.id" must be an integer or null
(new Validator([
'name' => null
], [
'name' => ['string', 'notNull']
]))->assert(function(string $field, string $message, string $name = null){
// handle error
//...
// return true to halt
// return false to continue to throw validation exception
return true;
});
// validator.rule.[type].[name]
app()->use('validator.rule.string.beginWithEndWith', App\Validator\BeginWithEndWith::class);
// App\Validator\MyRule class:
namespace App\Validator;
class BeginWithEndWith extends \Lark\Validator\Rule
{
private string $beginWith;
private string $endWith;
protected string $message = 'must begin with value and end with value';
public function __construct(string $beginWith, string $endWith)
{
$this->beginWith = $beginWith;
$this->endWith = $endWith;
}
public function validate($value): bool
{
$beginsWith = substr($value, 0, strlen($this->beginWith));
$endsWith = substr($value, -(strlen($this->endWith)));
return $beginsWith === $this->beginWith && $endsWith === $this->endWith;
}
}
// validation example
(new Validator([
'alias' => '123testXYZ'
], [
'alias' => ['string', ['beginWithEndWith' => ['123', 'XYZ']]]
]))->validate(); // true
// validator.rule.[type].[name]
// overwrite existing string rule "email"
app()->use('validator.rule.string.email', 'App\\Validator\\Email');
// App\Validator\Email class:
namespace App\Validator;
class Email extends \Lark\Validator\TypeString\Email
{
public function validate($value): bool
{
// must be valid email and domain "example.com"
return parent::validate($value)
&& preg_match('/@example\.com$/i', $value) === 1;
}
}
// validation example
(new Validator([
'email' => '[email protected]'
], [
'email' => ['string', 'email']
]))->validate(); // true
php
// bootstrap
// ...
$cli = Lark\Cli::getInstance();
// add command
$cli->command('files', 'Print files in directory')
->arg('dir', 'Read directory')
->action(function(string $dir) {
// print files in directory $dir
// optional, exit with any code by returning an int
// return 1; // same as $cli->exit(1);
});
// or use class/method:
// ->action([MyClass::class, 'methodName'])
// run app
$cli->run($_SERVER['argv']);
php
$o = $cli->output();
// output green text
$o->colorGreen->echo('This is green text');
// use multiple styles
$o->colorBlue->styleUnderline->echo('More text');
// style methods for common styles
$o->error('Error'); // red background
$o->info('Info'); // blue text
$o->ok('Success'); // green text
$o->warn('Warning'); // yellow text
$o->dim('Muted'); // dim text
// custom style methods can be registered
$o::register('blink', function ($text, $end = PHP_EOL) use ($out) {
$out->styleBlink;
$out->echo($text, $end);
});
$o->bink('Blinking text'); // blinking text
// override existing style methods
$o::register('error', function ($text, $end = PHP_EOL) use ($out) {
$out->colorRed; // text color red (instead of bg red)
$out->stderr($text, $end); // send to stderr
});
$o->error('Oops'); // red text