A rewrited Scarlets framework for website based on PHP
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Written by Software License Build Status Tweet


This framework still under development

Scarlets is a web framework for PHP that can help you build a website with API and another build-in system. This framework have a lazyload on it's system, so you can select which system that you want to use to keep your website in a high performance state.

Scarlets have a build-in traffic monitor for any hacking activity or another security problem. And it will suggest you a security option if you have a backdoor on your system.

Installation instruction

Clone/download this repository and put it on a folder Then copy the example folder and edit the framework path on root.php

Install by using command prompt

Make sure you have installed PHP on your computer (Windows and OSX can use XAMPP)
and make sure the php command is available on the command prompt

$ php -v

If not, then you need to set it up on the environment variables.

When the php command is available, open your command prompt and enter this line

$ php -r "copy('https://raw.githubusercontent.com/ScarletsFiction/Scarlets/master/net-install', 'net-install');"
$ php net-install

The framework will automatically installed, and the example files will be prepared on your project folder.


Scarlets have internal upgrade feature

$ php scarlets upgrade

But if there are any error and the framework was unable to be loaded
Please clone this repository and extract it to vendor/scarletsfiction/scarlets


Scarlets Console

This framework has a build-in server by calling

$ php scarlets serve (port) (address) (options)

Address: localhost, network, IPAddress
Options: --log, --verbose

alt text

You can also create your own command for your project

alt text

The user defined command are editable on /routes/console.php

Define command

Console::command(pattern, callback, info='');

Console::command('echo {*}', function($message){

Use invisible writting


Console::command('input', function(){
    echo("Type something invisible: ");
    print_r("Result: ".Console::hiddenInput());
}, 'Type something');

Change text color

Console::chalk(text, color);

Console::command('echo {*}', function($message){
    echo(Console::chalk("Computer> $message", 'yellow'));

Match more pattern

Console::args(pattern, callback);

Console::command('echo {*}', function($all){
    Console::args('{0} {1}', function($name, $message){
        echo("$name> $message");

    // Check if args above was not being called
        echo "Computer> $all";

Adding help section

Console::help(text, color);

Console::help('echo', "Type 'echo (anything here)' to get echo back.");

Clear console


Check if running on console


Obtain registered console command


Arrange result as a table on console



This webrouter will help you route any URL Request
All route should be placed on /routes/ folder The router priority is:

  1. status.php (HTTP status)
  2. api.php (API Router)
  3. web.php (Web Router)

Route by Request Method

Route::get(pattern, callback, options=''); The accepted request method are get, post, delete, put, options.

The allowed match pattern are started with parameter index
And followed by:

  1. : (Regex)
  2. ? (Optional)

The parameter index for example below is 0 and the regex [A-Za-z]+

Route::get('/text/{0:[A-Za-z]+}', function($text = ['world']){
    // Serve::raw("Hello, $text[0]");
    return "Hello, $text[0]";

Serve views

The views folder are located on /resources/views/ folder

Serve::view(file, parameter);

Route::get('/', function(){
    Serve::view('hello', ['message' => 'World']);
}, 'name:home');

You can easily access the message parameter from target views like below

<p class="msg"> <?= $message ?> </p>

or maybe obtaining POST, GET request with

<p class="msg"> <?= $p['anything'] ?> </p>
<p class="msg"> <?= $q::post('anything') ?> </p>

If you're using frontend MVW framework, you can obtain dynamic view only by set isStatic to true for static view.

Namespace Router group

Route::namespace(namespace, callback);

Route::namespaces('App\Http\Controllers', function(){
    // Class controller at "App\Http\Controllers" Namespace

    // Call 'route' function on "User\Home" Class
    Route::get('/user/{0}', 'User\Home::route');

URL Prefix group

Route::prefix(prefix, callback);

Route::prefix('admin', function(){
    Route::get('users', function(){
        // Matches The "/admin/users" URL
        Serve::raw("Hi admin!");

        // Or route to User List

Router name group

Route::name(name, callback);

Route::name('list', function(){
    Route::get('users', function(){
        // Route assigned name "list.users"
        Serve::raw("User List");
    }, 'name:users');

Domain Router

Route::domain(domain, callback);

Route::domain('{0}.framework.test', function($domain){
    Route::get('/home/{0}', function($query){
        // Will be available on "*.framework.test" domain

Middleware Router group

Route::domain(domain, callback);

Route::middleware('limit:2,60', function(){
    Route::get('limit', function(){
        Serve::raw("Limited request");

// Or you could also set the middleware from request method's router
Route::get('limit', function(){
    Serve::raw("Limited request");
}, 'limit:2,60');

Registering middleware for router

Route\Middleware::$register['limit'] = function($request = 2, $seconds = 30){
    $total = Cache::get('request.limit', 0);

    if($total < $request){
        // Set expiration when it's the first request only ($total == 0)
        $expire = $total === 0 ? $seconds : 0;

        // Put the request count on cache
        Cache::set('request.limit', $total + 1, $expire);

        // Continue request
        return false;

    // Block request
        return true;



Before using this library, you must modify the database configuration on /config/database.php

Get database connection

$myDatabase = Scarlets\Library\Database::connect(databaseName='{default}');

Select table rows

$myDatabase->select(tableName, $columns, $where=[]);

$myDatabase->select('test', ['name', 'data'], {
    'OR'=>['id'=>123, 'words[~]'=>'hello'],
// SELECT name, data FROM test WHERE (id = ? OR (words LIKE ?)) LIMIT 1

The other database library documentation is almost similar with SFDatabase-js

Below are the undocumented library

The library documentation still in progress
If you're willing to help write this documentation I will gladly accept it

LocalFile system

You may need to assign the namespace to the top of your code

use \Scarlets\Library\FileSystem\LocalFile;

The filesystem configuration are stored on /config/filesystem.php.
Then you can pass {the storage name}/your/path to the LocalFile function.


Load contents from file


$data = LocalFile::load('{app}/data/text.inf');

load, size, append, prepend, createDir, put, search, lastModified, copy, rename, move, delete, read, tail, zipDirectory, extractZip, zipStatus


You may need to assign the namespace to the top of your code

use \Scarlets\Library\Cache;


Cache::get(key, default=null);

The example below will return data from timestamp key
but if the key was not found or expired, then it will return
default value.

$data = Cache::get('timestamp', 0);

Cache::set(key, value, seconds=0);

The example below will set time() on timestamp key
and expired after 20 second.

$data = Cache::set('timestamp', time(), 20);

has, pull, forget, flush, extendTime


You may need to assign the namespace to the top of your code

use \Scarlets\Library\Crypto;

The security configuration are stored on /config/security.php.
The default cipher will be used if the cipher parameter was false.

This library is using openssl php extension.
So make sure you have enabled it before use.
And the available cipher are listed on php documentation.


Crypto::encrypt(text, pass=false, cipher=false, mask=false);

Set the mask parameter to true if you want to encode any symbol
to text. Make sure you have change default crypto_mask
on the configuration to improve security.

$data = Cache::encrypt('hello', 'secretcode', false, false);
// Output:
// Tst2nVw4sDMB5M5jwwSPiTp+Olh4QTRhek55YnF6VFdPUURYa1ZKbHc9PQ==

Crypto::decrypt(encryptedText, pass=false, cipher=false, mask=false);

$data = Cache::decrypt('hello', 'secretcode');


You may need to assign the namespace to the top of your code

use \Scarlets\Library\Language;

The default language are configured on /config/app.php.
And the languages files are located on /resources/lang/.


Language::get($key, $values = [], $languageID='')

$text = Language::get('time.current_date', [date('d M Y')], 'en');


You may need to assign the namespace to the top of your code

use \Scarlets\Library\Socket;


This function will open new socket server that able
to process multiple request at the same time.

Socket::create(address, port, readCallback, connectionCallback=0)

Socket::create('localhost', 8000, function($socketResource, $data){
    echo("Data received:");
}, function($socketResource, $status){
    echo("Someone $status");

This function will open new socket server than able
to process single request at the a time.

Socket::simple(address, port, readCallback)

Socket::simple('localhost', 8000, function($socketResource, $data){
    echo("Data received:");

Socket::ping(domain, port=80)


You may need to assign the namespace to the top of your code

use \Scarlets\Library\WebRequest;


Web Request with curl extension

WebRequest::loadURL(url, data="")

$data = WebRequest::loadURL('https://www.google.com', [
    'ssl'=>false, // Skip ssl verification
    'header'=>['Some: header'],
    'post'=>['data' => 'anything'],
    'limitSize'=>10, // In KB
    'proxy'=>['ip' => '', 'port' => 8000],
    'returnheader' => true // Return header only

From this server to client browser

WebRequest::giveFiles(filePath, fileName = null)


From other server to local file

WebRequest::download(from, to, type="curl")


From client browser to this server

WebRequest::receiveFile(directory, allowedExt, rename='')

Make sure you limit the allowed extension to
avoid security issue

allowedExt = ['css', 'js', 'png']

Accessing App Configuration

Get all configuration array reference

The sample below will return loaded configuration from /config/ folder

$config = Scarlets\Config::load('app'); /* (App folder)/config/app.php -> hostname value $config['app.hostname'] = 'localhost'; */


Error warning

Scarlets\Error::warning('Something happen');


Scarlets\Log::message('Something happen');

Register shutdown callback


The callback will be called when the framework is going to shutdown


If you want to help in Scarlets framework, please fork this project and edit on your repository, then make a pull request to here.

Keep the code simple and clear.


If you have any question please ask on stackoverflow with tags 'scarlets-php'.
But if you found bug or feature request, you post an issue on this repository.

For any private support, you can contact the author of this framework:
StefansArya (Indonesia, English)
stefansarya1 at gmail


Scarlets is under the MIT license.

Help improve this framework by support the author \(≧▽≦)/