<commit_before>Harubi
======

## Introduction

Harubi is a MVC-like framework for backend servers, minus the View concern. In the era of Web 2.0 and smartphones, most clients render Views themselves. The clients may need to access the servers only for the storage and persistance. Harubi focuses on the servers by controlling access to the data Models. The absence of the View makes Harubi much lighter compared to MVC frameworks. A Harubi server can serve all types of clients including the web, desktops and mobiles. Harubi can also serve APIs.

A Harubi server is an ordinary web server which responds to a request in JSON format.

### Example 1

A client make a request to a Harubi server by specifying at least two arguments: a **model** and an **action** against the model, together with other related **controller** arguments, if exist. The following is a typical request:

```
http://example.com/?model=system&action=gettime
```

And the server is expected to respond with a JSON formatted data set:

```json
{"time":1426835075}
```

The Harubi server implementation looks like the following:

```php
beat('system', 'gettime', function ()
{	
	return array(
		'time' => time()
	);
});
```

The **beat()** call is pushing three arguments: **$model**, **$action** and **$controller**. In this case the $model is set to *system*, the $action is set to *gettime*, and the $controller is set to a closure. The beat() function will test whether the request satisfies with the specified model and action. If it does than the controller will be invoked. If the controller function has parameters then the values will be retrieved from the request arguments. However, in this case the controller has no parameter. The controller is expected to return an array which will be converted into JSON before the beat() function exits. In general, when the $model and $action matched, the beat() function will invoke the $controller and wait for it to return and then force PHP to exit with the expected response. Otherwise, the execution will continue looking for other beat() calls.

The beat pattern is the Harubi unique way to route requests to controllers.


### Example 2

The following is another example which the controller has a parameter **name**:

```
http://example.com/?model=user&action=read&name=ali
```

```php
beat('user', 'read', function ($name)
{	
	$where = equ('name', $name, 'string');

	$records = read('user', $where);

	return $records[0];
});
```

```json
{
    "name" : "ali",
    "email" : "<EMAIL>", 
    "created_utc" : 1426835075,
    "updated_utc" : 1426835075
}
```

The **equ()** function sanitizes the *where* equation clause for the SQL *select* query which will be silently generated and issued within the read() function. The sanitization is done on the value of the $name argument and is done so to prevent the database from the infamous *SQL injection* attack.

The **read()** function is one of the implemented CRUD functions in Harubi to simplify the database query processes.

## Model

A model is an abstract dataset with action interfaces. In Harubi a model is sliced into a set of beat() call implementations. Every beat() call is implementing an action for a model. It is easy to associate a model to a table in a database. However, in Harubi a model can become very complex such as involving multiple relational tables. As an example, a user may have a role which defines permissions to access the system. There could be a *getpermissions* action on the *user* model which could involve three tables: user, role and permission.

```php
beat('user', 'getpermissions', function ($name)
{	
	$where = equ('name', $name, 'string');

	$user_records = read('user', $where);

	$role_records = read('role', "name=" . $user_records[0]['role']);

	$perm_records = read('permission', "role_id=" . $role_records[0]['id']);

	return $perm_records;
});
```
 
## Controller

In Harubi, a controller is usually a closure implemention wrapped in a beat() call. Every controller implements a model's action. It is the duty of a controller to make all necessary database queries and form the respective response for the action as requested. The controller is expected to return an array of records.

If a controller is a closure then you may be tricked to see that a beat() call is a controller such as in the model example above, but the beat() call is not the controller. A controller can be implemented as a function for reuse in other beat() calls.

```php
function getpermissions_controller($name)
{
	$where = equ('name', $name, 'string');

	$user_records = read('user', $where);

	$role_records = read('role', "name=" . $user_records[0]['role']);

	$perm_records = read('permission', "role_id=" . $role_records[0]['id']);

	return $perm_records;
}

beat('user', 'getpermissions', 'getpermissions_controller');
```

## Getting Started

A Harubi server is a web server using PHP and MySQL. Please note that this getting started does not include tutorials in PHP and MySQL. Here you are assumed to know the relational database concept and to have the administrative rights to a MySQL server since you are going to create a table in it. You also need to have the administrative rights to a PHP-based web server since you are going to upload some files in it. Most of the time we assume you know what to do with anything related to PHP and MySQL.

First of all, create the following sample user.php file. It declares a user model with two actions: *create* and *read*. Later on you are going to create and read some user records.

**user.php**

```php
include_once 'harubi/harubi.php';

harubi();

beat('user', 'create', function ($name, $password)
{	
	$where = equ('name', $name, 'string');

	$records = read('user', $where);

	if (count($records) <= 0)
	{
		$now = time();
		$hash = password_hash($password, PASSWORD_BCRYPT);
		$id = create('user', array(
			'name' => $name,
			'password' => <PASSWORD>,
			'created_utc' => $now,
			'updated_utc' => $now
			));	

		if ($id > 0)
			return array(
				'name' => $name,
				'created_utc' => $now,
				'updated_utc' => $now
				);
	}

	return array(
		'error' => 1,
		'error_msg' => 'Could not create user'
		);
});

beat('user', 'read', function ($name)
{	
	$where = equ('name', $name, 'string');

	$records = read('user', $where);

	if (count($records) > 0)
	{
		unset($records[0]['id']);
		unset($records[0]['password']);
		return $records[0];
	}

	return array(
		'error' => 1,
		'error_msg' => 'Could not read user'
		);
});
```

In the *user.php* file the call to *harubi()* initiates the Harubi server. The harubi() function sets the database according to the settings in the *settings.inc* file below. Please set your MySQL credential accordingly.

**settings.inc**

```json
{
	"mysql" : {
		"hostname" : "localhost",
		"username" : "root",
		"password" : "<PASSWORD>",
		"database" : "harubi"
	},
	
	"tables" : {
		"user" : {
			"id" : "int",
			"name" : "string",
			"password" : "<PASSWORD>",
			"created_utc" : "int",
			"updated_utc" : "int"
		}
	}
}
```

You need to create a database and a user table in MySQL that matches with the settings above. You may use the following SQL script to create the table.

```sql
CREATE TABLE IF NOT EXISTS `user` (
	`id` bigint(20) NOT NULL AUTO_INCREMENT,
	`name` varchar(64) NOT NULL,
	`password` varchar(64) NOT NULL,
	`created_utc` int(11) NOT NULL,
	`updated_utc` int(11) NOT NULL,
	PRIMARY KEY (`id`),
	UNIQUE KEY `name` (`name`)
);
```
<commit_msg>Added mysql table prefix field under settings.inc<commit_after>Harubi
======

## Introduction

Harubi is a MVC-like framework for backend servers, minus the View concern. In the era of Web 2.0 and smartphones, most clients render Views themselves. The clients may need to access the servers only for the storage and persistance. Harubi focuses on the servers by controlling access to the data Models. The absence of the View makes Harubi much lighter compared to MVC frameworks. A Harubi server can serve all types of clients including the web, desktops and mobiles. Harubi can also serve APIs.

A Harubi server is an ordinary web server which responds to a request in JSON format.

### Example 1

A client make a request to a Harubi server by specifying at least two arguments: a **model** and an **action** against the model, together with other related **controller** arguments, if exist. The following is a typical request:

```
http://example.com/?model=system&action=gettime
```

And the server is expected to respond with a JSON formatted data set:

```json
{"time":1426835075}
```

The Harubi server implementation looks like the following:

```php
beat('system', 'gettime', function ()
{	
	return array(
		'time' => time()
	);
});
```

The **beat()** call is pushing three arguments: **$model**, **$action** and **$controller**. In this case the $model is set to *system*, the $action is set to *gettime*, and the $controller is set to a closure. The beat() function will test whether the request satisfies with the specified model and action. If it does than the controller will be invoked. If the controller function has parameters then the values will be retrieved from the request arguments. However, in this case the controller has no parameter. The controller is expected to return an array which will be converted into JSON before the beat() function exits. In general, when the $model and $action matched, the beat() function will invoke the $controller and wait for it to return and then force PHP to exit with the expected response. Otherwise, the execution will continue looking for other beat() calls.

The beat pattern is the Harubi unique way to route requests to controllers.


### Example 2

The following is another example which the controller has a parameter **name**:

```
http://example.com/?model=user&action=read&name=ali
```

```php
beat('user', 'read', function ($name)
{	
	$where = equ('name', $name, 'string');

	$records = read('user', $where);

	return $records[0];
});
```

```json
{
    "name" : "ali",
    "email" : "<EMAIL>", 
    "created_utc" : 1426835075,
    "updated_utc" : 1426835075
}
```

The **equ()** function sanitizes the *where* equation clause for the SQL *select* query which will be silently generated and issued within the read() function. The sanitization is done on the value of the $name argument and is done so to prevent the database from the infamous *SQL injection* attack.

The **read()** function is one of the implemented CRUD functions in Harubi to simplify the database query processes.

## Model

A model is an abstract dataset with action interfaces. In Harubi a model is sliced into a set of beat() call implementations. Every beat() call is implementing an action for a model. It is easy to associate a model to a table in a database. However, in Harubi a model can become very complex such as involving multiple relational tables. As an example, a user may have a role which defines permissions to access the system. There could be a *getpermissions* action on the *user* model which could involve three tables: user, role and permission.

```php
beat('user', 'getpermissions', function ($name)
{	
	$where = equ('name', $name, 'string');

	$user_records = read('user', $where);

	$role_records = read('role', "name=" . $user_records[0]['role']);

	$perm_records = read('permission', "role_id=" . $role_records[0]['id']);

	return $perm_records;
});
```
 
## Controller

In Harubi, a controller is usually a closure implemention wrapped in a beat() call. Every controller implements a model's action. It is the duty of a controller to make all necessary database queries and form the respective response for the action as requested. The controller is expected to return an array of records.

If a controller is a closure then you may be tricked to see that a beat() call is a controller such as in the model example above, but the beat() call is not the controller. A controller can be implemented as a function for reuse in other beat() calls.

```php
function getpermissions_controller($name)
{
	$where = equ('name', $name, 'string');

	$user_records = read('user', $where);

	$role_records = read('role', "name=" . $user_records[0]['role']);

	$perm_records = read('permission', "role_id=" . $role_records[0]['id']);

	return $perm_records;
}

beat('user', 'getpermissions', 'getpermissions_controller');
```

## Getting Started

A Harubi server is a web server using PHP and MySQL. Please note that this getting started does not include tutorials in PHP and MySQL. Here you are assumed to know the relational database concept and to have the administrative rights to a MySQL server since you are going to create a table in it. You also need to have the administrative rights to a PHP-based web server since you are going to upload some files in it. Most of the time we assume you know what to do with anything related to PHP and MySQL.

First of all, create the following sample user.php file. It declares a user model with two actions: *create* and *read*. Later on you are going to create and read some user records.

**user.php**

```php
include_once 'harubi/harubi.php';

harubi();

beat('user', 'create', function ($name, $password)
{	
	$where = equ('name', $name, 'string');

	$records = read('user', $where);

	if (count($records) <= 0)
	{
		$now = time();
		$hash = password_hash($password, PASSWORD_BCRYPT);
		$id = create('user', array(
			'name' => $name,
			'password' => $<PASSWORD>,
			'created_utc' => $now,
			'updated_utc' => $now
			));	

		if ($id > 0)
			return array(
				'name' => $name,
				'created_utc' => $now,
				'updated_utc' => $now
				);
	}

	return array(
		'error' => 1,
		'error_msg' => 'Could not create user'
		);
});

beat('user', 'read', function ($name)
{	
	$where = equ('name', $name, 'string');

	$records = read('user', $where);

	if (count($records) > 0)
	{
		unset($records[0]['id']);
		unset($records[0]['password']);
		return $records[0];
	}

	return array(
		'error' => 1,
		'error_msg' => 'Could not read user'
		);
});
```

In the *user.php* file the call to *harubi()* initiates the Harubi server. The harubi() function sets the database according to the settings in the *settings.inc* file below. Please set your MySQL credential accordingly.

**settings.inc**

```json
{
	"mysql" : {
		"hostname" : "localhost",
		"username" : "root",
		"password" : "<PASSWORD>",
		"database" : "harubi",
		"prefix"   : ""
	},
	
	"tables" : {
		"user" : {
			"id" : "int",
			"name" : "string",
			"password" : "string",
			"created_utc" : "int",
			"updated_utc" : "int"
		}
	}
}
```

You need to create a database and a user table in MySQL that matches with the settings above. You may use the following SQL script to create the table.

```sql
CREATE TABLE IF NOT EXISTS `user` (
	`id` bigint(20) NOT NULL AUTO_INCREMENT,
	`name` varchar(64) NOT NULL,
	`password` varchar(64) NOT NULL,
	`created_utc` int(11) NOT NULL,
	`updated_utc` int(11) NOT NULL,
	PRIMARY KEY (`id`),
	UNIQUE KEY `name` (`name`)
);
```

{'fraction_non_alphanumeric': 0.11786666666666666, 'fraction_numerical': 0.0076, 'mean_word_length': 4.336535040910708, 'pattern_counts': {'":': 2, '<': 12, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '847119', 'n_tokens_mistral': 4636, 'n_tokens_neox': 4291, 'n_words': 2029}