An OOP PHP micro-framework, a lightweight toolkit to help developers lay down the foundation of their PHP-based websites and applications . The Horus Framework is a pretty solid attempt at designing a good OOP framework in as a small package as possible. Focused on a light codebase and on a solid, standards-friendly approach, Horus can be used to write advanced applications without having to deal with complex coding toolkits like Zend or CakePHP. Horus is easy to learn and the code is pretty well commented in case developers need help figuring out what's going on -- "Softpedia"
mod_rewrite
simulatore.g: Apache
tested on PHP 5.2
Version 2.0
from the introduction, you don't need
any thing to do except for uncompress it then start coding directly .
Now open your index.php
and start ,
// include horus
require_once 'Horus/Horus.php';
// start it
new Horus;
// say hello world
echo "Hello World";
Hello World
, Easy or not :) .
You can notice that we didn't use any routing , but how about saying hello world using Horus Router
?
// include horus
require_once 'Horus/Horus.php';
// start it and tell horus to use it's own router
new Horus( array(
'horus.use_router' => yes // yes = true
'horus.enable_simulator' => yes // enable simulator if your server has no support for mod_rewrite
));
// respond to a get request saying "Hello World"
horus('router') -> get('/', function(){
echo "Hello World";
});
Now Goto Horus with your browser you will see Hello World
Horus Framework
is built-in very easy configurations to control what you want .
Horus
?
// 1)- when you construct horus, just give it an assoc-array of configurations, like this
new Horus(array('key' => 'value'));
// 2)- using config() method
horus()->config('key', 'value');
# or
horus()->config(array('key' => 'value'));
// to fetch any configuration
echo horus()->config('key');
key | value | default |
---|---|---|
horus.use_router | true / false |
false |
horus.timezone | see it on PHP.net | PHP Default |
horus.default_404 | a callback e.g function(){ echo '404 not found'; } |
Horus Default |
horus.auto_run | true / false |
true if you set it to false, you must type horus()->run(); at the end of your index.php |
horus.http_version | string |
1.1 |
horus.enable_simulator | true / false |
false if your server has no support for mod_rewrite, set to true/yes |
horus.session_name | string |
HORUS_SESSID |
horus.session_hash_function | Se it on PHP.net | 1 |
horus.session_use_only_cookies | Se it on PHP.net | true |
horus.session_http_only | Se it on PHP.net | true |
horus.session_regenerate_id | true / false |
true |
horus.session_save_path | string | PHP Default |
horus.enable_gzip | true / false |
true |
horus.minify_output | true / false |
false |
horus.fix_html | true / false |
false only if the page is html |
horus.fix_xml | true / false |
false only if the page is xml and fix_html is false |
horus.mode | dev / production |
dev |
Horus Router
You can respond to GET
, POST
, PUT
, HEAD
, DELETE
, .... etc .
// include horus core
require_once "Horus/Horus.php";
// Construct it
// Note that my server supports mod_rewrite, so i don't need simulator
// And i'm working on PHP 5.4, so i use the new array style [], you can use array()
new Horus( [ 'horus.use_router' => yes ] );
// i'll use horus('router')-> or horus()->router->
// Respond to a get request on the '/page-1' path
horus('router') -> get('/page-1', function(){
echo 'We are in get request';
});
// Respond to a post request on the '/page-1' path
horus('router') -> post('/page-1', function(){
echo 'We are in post request';
});
// Respond to a put request on the '/page-1' path
horus('router') -> put('/page-1', function(){
echo 'We are in put request';
});
// Respond to a put, get request on the '/page-1' path
horus('router') -> put_get('/page-1', function(){
echo 'We are in put or get request';
});
// Respond to a put, post get request on the '/page-1' path
horus('router') -> put_post_get('/page-1', function(){
echo 'We are in put,post or get request';
});
// Respond to all/any requests ( get, post, put, patch, ... etc ) on the '/page-1' path
horus('router') -> any('/page-1', function(){
echo 'We are in any request';
});
// And so, you can use any http method
// just "horus('router') -> {method}($pattern, $callback)"
// after you included horus and started it
// sample usage
horus('router') -> any('/', function(){
echo 'hello';
});
// with parameters
horus('router') -> any('/{alpha}', function($arg){
echo 'hello ', $arg;
});
horus('router') -> any('/{alpha}/{num}', function($alpha, $num){
echo 'hello ', $alpha, ' ', $num;
});
// NOTE: anonymous function is only available in PHP >= PHP 5.3
// You can use lambada
horus('router') -> any('/', create_function('', 'echo "hello";'));
# {alpha} is a regexp shortuct, all shortucts are:
# {num} ---> ([0-9\.]+) { example "152423" }
# {alpha} ---> ([a-zA-Z]+) { example: "mystring" }
# {alnum} ---> ([a-zA-Z0-9\.]+) { example: "mystring132.321" }
# {str} ---> ([a-zA-Z0-9-_\.]+) { example: "my-string_132.345" }
# {any} ---> '.+' { supports any char }
# {*} ---> '?|(.*?)' { to apply the callback on all sub-paths }
// after you included horus and started it
// sample usage
function func_1()
{
echo 'hello';
}
horus('router') -> any('/', 'func_1');
// with parameters
function func_2($name)
{
echo "hello ", $name;
}
horus('router') -> any('/{alpha}', 'func_2');
function func_3($alpha, $num)
{
echo 'hello ', $alpha, ' ', $num;
}
horus('router') -> any('/{alpha}/{num}', 'func_3');
// after you included horus and started it
// Simple Class
Class Test
{
public static function page1()
{
echo we are in "page1";
}
public function page2()
{
echo we are in "page2";
}
function insert()
{
// ...
}
}
// construct it
$text = new Test;
// Route some methods from it
horus('router') -> any('/p1', 'Test::page1');
horus('router') -> any('/p2', array( $test, 'page2' ));
horus('router') -> any('/p2', [ $test, 'page2' ]); // only in PHP >= PHP 5.4
// after you included horus and started it
// Simple Class
Class Test2
{
public function index()
{
// this method is important in each class
}
public function page1()
{
echo we are in "page1";
}
public function page2()
{
echo we are in "page2";
}
public function page_3()
{
echo 'page-3';
}
}
// Route some methods from it
horus('router') -> any('/', 'Test2');
// Now each method works as a page .
// Now you can enter '/page1', '/page2', '/page_3', '/page-3', 'page-3.html', '/page1.php', '/index' and '/'
// You noticed that Horus Router converts '-' to '_' and ignore any '.extension' to be very easy
Horus Framework has built-in smart autoloader . by default it's registered using
spl_autoload_register()
, you can add your own, but here i'll speak about horus autoloader .
Horus Autoloader Converts any underscore and backslash to the system directory separator, based on the horus installation
directory, so new Horus_View
will converted to '/path/to/horus_installation/Horus/View.php'
.
# say that we have the next directory structure
/*
------------------------
-\
--\MyApp
--\Horus
--\index.php
--\.htaccess
------------------------
# when you call "new MyApp_ClassName", then horus autoloader will
load "\MyApp\ClassName.php" then start it.
# or "new Horus_View" , then horus autoloader will
load "\Horus\View.php" then start it.
# or "use \MyApp\Namespace\File" , then horus autoloader will
load "\MyApp\Namespace\File.php" then start it.
# so you noticed that this autoloader is based on the directory name
an if you changed the directory name, you will be in a problem, so to solve this
you need to set a new path alias
e.g: if you changed the name of "Horus" directory to "Core"
*/
// tell horus that the new path of 'Horus' prefix is '\Core\'
horus()->autoloadPathAlias('Horus', '\Core\');
Horus has built in views manager class that is very simple and easy .
Usage
// after you included and started horus
// start the view
$view = new Horus_View;
// set the views path and it's extension
$view -> setup('path/to/views_dir', '.html');
// add var to the view
$view -> addVar('var', 'value');
# or
$view -> addVar(array('var' => 'value'));
// remove a var
$view -> unsetVar('var');
// has the var 'var' ?
$view -> hasVar('var'); // returns bool
// load a view file(s) 'header, body' as string and pass array of vars to them
$vars = array( 'var1' => 'val1', 'var2' => 'val2' );
$v = $view->load('header, body', $vars);
echo $v;
# to display it directly
$view->render('header, body', $vars);
// NOTE: you can assign the $view var to horus directly, and use it noramlly
horus()->view = $view;
// horus()->view->render(....) or horus('view')->render(....);
Horus has build-in multi-language manager
Usage
// after you included and started horus
// start the view
$lang = new Horus_Lang;
// set the languages path and it's extension
$lang -> setup('path/to/langs_dir', '.lang');
// load a language file { the file must return an array contains keys => values }
// say that we have lang-file "en.lang" then it's contents is
/*
<?php
return array
(
'key1' => 'val1',
'key2' => 'val2'
);
?>
*/
$lang->load('en');
// add translations ( assoc-array )
$lang -> add(array('key' => 'value'));
// get a translation
echo $lang->get('key');
// translate full subject
echo $lang->translate('my subject');
Horus comes with simple common helpers that will help you while
developing .
function dump($var, $var_dump = false)
Print var in human readable way print_r
+ pre
but if you like var_dump
+ pre
$var_dump
to true .
function headeri($string, $replace = false, $http_response_code = null)
An improved function instead of header()
uses the new http class .
function go($to, $using = 302)
Redirect to another page using 302|301|'html'|'js'
go('http://google.com', 'js:5')
redirect using javascript after 5 seconds, you could write 'js' only go('http://google.com', 'html:5')
redirect using html after 5 seconds, you could write 'html' only go('http://google.com', 302)
redirect using http-302 go('http://google.com', 301)
redirect using http-301
function cURL($url, array $curl_options = array())
Quick cURL connection, will return array of page content and page info (headers) $url
the url to connect to . $curl_options
array of curl options, default empty means (CURLOPT_RETURNTRANSFER => true) $data = cURL('google');
echo 'content: ', $data['content'];
dump($data['info'])
function session_init($lifetime = 0)
Start new session (alternative to session_start()) $lifetime
: the period (in sec) of the session, default 0 means 900 sec
function session_end()
Destroy session and free $_SESSION array .
function server($key = null)
get value from $_SERVER
echo server('request uri');
or
echo server('request-uri');
or
echo server('request_uri');
or
echo server('request/uri');
or
echo server('REQUEST_URI');
if $key
is null will return all $_SERVER
array
function isHttps()
check if the request is using HTTPS, return bool
function isAjax()
check if the request is under Ajax, return bool
function isApache()
check if the server is apache, return bool
function isCli()
check if the script run under Command line, return bool
function isCgi()
check if the script run under CGI, return bool
function uri($to = null)
Generate uri to an internal page in horus application
function asset($to = null)
Generate direct url to an asset file in horus application
function random_str($length = 5)
Generate random string with a certain length
function random_serial($serials_count = 1, $blocks_count = 5, $block_size = 5, $separaor = '-')
Generate random serial . $serials_count
: how many serials do you need ? $blocks_count
: how many blocks per serials ? $block_size
: size of each block ? $separator
: the blocks delimiter ?
function limit_words($subject, $offset, $limit, $ends = ' ...')
Limit subject based on words, e.g: you need only 5 words from the start of subject and end it with ...:
echo limit_words('this is test statement and this is test', 0, 5)
function array_insert(array $into, mixed $new, int $position)
insert array or element into any position of another array example:
$into = array(1,2,3,6,7);
$new = array(4, 5);
$position = 3;
$result = array_insert($into, $new, $position);
// will be: array(1, 2, 3, 4, 5, 6, 7)
function horus($using = null)
to get horus
instance
example:
// 1)-
horus()->view->render('header');
// 2)-
horus('view')->render('header);
function array_start(array $array)
to get the first element in an array example:
echo array_start(array(1,2,3,4,5));
// will output '1'
function array_end(array $array)
to get the last element in an array example:
echo array_end(array(1,2,3,4,5));
// will output '5'
function array_isset(array $array, array $keys)
check if the given $keys
are fully exists in $array
example:
echo array_isset(array(1,2,3,4,5), array(1,3));
// will output '1'
echo array_isset(array(1,2,3,4,5), array(1,8));
// will output '0' or null
function array_unset(array $array, array $keys)
unset array of keys from an array example:
$new = array_unset(array('x'=> 1, 'y'=>2, 'xz'=>3), array('x', 'y'));
// will remove $new will only be array('xz' => 3)
function define_array(array $defines)
just like define()
but will work over an array example:
define_array(array(
'DS' => DIRECTORY_SEPARATOR,
'NAME' => 'HORUS_FRAMEWORK',
));
echo DS;
echo NAME;
function mempty()
check whether var(s) empty example:
if(mempty($_GET['key1'], $_GET['key2'], $_GET['key3'])) {
echo 'empty';
}
function halt($code = 200, $message = null)
exit application and set status code and show message example:
halt(404, 'not found');
// or
halt(404, horus()->errDocs()->e404);
array_get(array $input, $needle, $except = null)
Get elements from array or get all except some example:
$array = array(1,2,3,4,5,6,7,8,9);
// get all
dump( array_get($array, '*') );
// get all except 1,2
dump( array_get($array, '*', array(1,2)) );
// get only 1,2
dump( array_get($array, array(1,2)) );
function password_hash($password, $algo = PASSWORD_DEFAULT, array $options = array())
Horus introduces this api in any PHP 5 version not only PHP 5.5, you don't need to upgrade to PHP 5.5 :D function password_get_info($hash)
See More Here Here
function password_needs_rehash($hash, $algo = PASSWORD_DEFAULT, array $options = array())
See More Here Here
function password_verify($password, $hash)
See More Here Here
function paginate($data_size, $current_page, $limit = 5, $link_format = '?p=%d', $max_links = 5)
Smart Tiny Pagination Function, No need to ownload big class for small operation ;) example:
// how many results to paginate ?
$count = 45;
// how many results per page ?
$perpage = 5;
// what is the current page ?
$current = $_GET['p']; // we used site.com/?p=xxx as our pager counter
// what is the target link format ?
// i'll use site.com/?p=xxx where xxx is an integer, we replace
// the integer parameter with '%d'
// e.g: for site.com/?go=news&new=blog&p=%d
$target = '?p=%d';
// how many links do you want ?
// < 1 2 3 4 5 > those are 5
$links = 5;
// now paginate
$p = paginate($count, $current, $perpage, $target, $links);
// now the var '$p' is an array contains
// 1)- pages_count (how many pages)
// 2)- start (the offset used for e.g: 'select .... limit $start, $limit')
// 3)- limit (the data limit = perpage)
// 4)- links[] (array contains generated links)
// they are: next, prev, current, first, last and (from 1 to links_limit)
$sql = "select * from table limit {$p['start']},{$p['start']}";
$query = horus('db')->query($sql);
while($row = horus('db')->fetch()) {
// show data here
}
// show links ?
foreach( $p['links'] as $name => $href) {
echo sprintf(' %s ', $href, $name);
}
// will print next prev first last current 1 2 3 4 5
// note: if there is no prev, next, then the $href of them will be false
// to help you detect it and make it "disabled=''"
function array_column (array $array , $column_key, $index_key = null)
Return the values from a single column in the input array function maili($from, $to, $subject, $message, $name = '',array $headers = array())
mail-[i]-mproved function
// yourmail
$from = 'yourmail@gmail.com';
// to (supports multiple)
$to = 'to@gmail.com'; // or array('m1@gmail.com', 'm2@gmail.com', ... );
// subject
$subject = 'test';
// message [supports html, and also it set to utf-8]
$message = 'hi this is message';
// name [will show in target mailbox from ] "Optional"
$name = 'myname';
// more headers ? assoc array of your custom headers
$headers = array('Content-Type'=>'text/html; charset=UTF-8'); // this is the default
// now send [ returns bool ]
dump(maili($from, $to, $subject, $message, $name, $headers));
events_listen($tag, $callback, $order = 0)
register new event $tag
: the event tag/place/category . $callback
: the event callback . $order
: the event order/periority { small number = heigh periority }
events_dispatch($tag, array $arguments = array())
run events under category/tag {$tag
} and pass arguments if needed . Returns
the last dispatched value .
function events_all()
returns all registered events .
function session_started()
check if the session is started, returns bool .
array_assoc_get(array $input, $needle, $except = null)
Get elements { keys => values } from array or get all except some example:
$array = array( 'k1'=>'v1', 'k2'=>'v2', 'k3'=>'v3' );
// get all
dump( array_get($array, '*') );
// get all except for 'k1', 'k2'
// will return array('k1' => 'v1')
dump( array_get($array, '*', array('k1', 'k2')) );
// get only 'k1', 'k2'
dump( array_get($array, array('k1', 'k2')) );
error documents
# start horus ...
$horus = new Horus();
# show an error page
$horus->errorDoc('error title', 'error escription');
# or get it and display it manully
echo $horus->errorDoc('error title', 'error escription', true);
# there are also some error documents shortcuts
echo $horus->errorDocs()->e400; // or
echo $horus->errorDocs()->e401; // or
// you can use any error from the next
/*****************
'e400'
'e401'
'e402'
'e403'
'e404'
'e405'
'e406'
'e500'
'e502'
'e503'
'e504'
******************/
Horus Framework doesn't love any overhead so it extends PDO
and simplified some things
let's see it:
# start horus ...
$horus = new Horus;
# just like PDO to connect
$horus->db = new Horus_DB; // or horus()->db = ....
$horus->db->connect('dns', 'username', 'password', $options);
// OR
# Connect to mysql server
$horus->db->mysql('db server', 'db name', 'username', 'password');
# Connect to sqlite
$horus->db->sqlite('db_filepath');
# Connect to mssql {sql server} server
$horus->db->mssql('db server', 'db name', 'username', 'password');
# Connect to oracle server
$horus->db->oracle('db server', 'db name', 'username', 'password');
# Connect to postgre server
$horus->db->pgsql('db server', 'db name', 'username', 'password');
# create a query (improved function)
# (and optionally pass array of binds inputs)
$horus->db->query(
'select * from table where col1=? and col2 = ?',
array('value1', 'value2'
));
// fetch just what pdo does
var_dump($horus->db->fetchAll());
// Yes every thing from just from one object
// So i call it (PDO Improved) as it merged PDO with PDOStatement
// So you can access any method of them just from that object '$horus->db'
Horus Framework provides you a simple extensible ORM For the database
ORM is "Object Rational Mapper" for database operations, to simplify dealing with it .
// start horus
$horus = new Horus;
// use it
// you will need the horus_db construction
$horus->db = new Horus_DB;
$orm = new Horus_DB_ORM($horus->db);
// you can access any 'db' method from 'orm' too
$orm -> mysql('server', 'dbname', 'username', 'password');
// set the table
$users = $orm->on('users');
# insert ( single-insert )
// insert into users(name, city, icon) values(?, ?, ?)
// return bool
$users->insert(array
(
'name' => 'user name',
'city' => 'user city',
'icon' => 'user icon'
))->end();
// only show the generated sql statement ?
echo $users->insert(array
(
'name' => 'user name',
'city' => 'user city',
'icon' => 'user icon'
))->getSQL();
// show the inputs only ?
dump($users->getInputs());
# insert multiple users at one query (good for performance)
// insert multiple rows at once
// return bool
$users->minsert(array
(
// into
array('name', 'city', 'icon'),
// values
array('name 1', 'city 1', 'icon 1'),
array('name 2', 'city 2', 'icon 2'),
array('name 3', 'city 3', 'icon 3'),
array('name 4', 'city 4', 'icon 4'),
array('name 5', 'city 5', 'icon 5'),
array('name 6', 'city 6', 'icon 6')
))->end();
// this is won't work for sqlite old versions that don't
// supports 'Values(?, ?),(?, ?),...', so for sqlite set
// the seconde param to true, as following:
$users->minsert(array
(
// into
array('name', 'city', 'icon'),
// values
array('name 1', 'city 1', 'icon 1'),
array('name 2', 'city 2', 'icon 2'),
array('name 3', 'city 3', 'icon 3'),
array('name 4', 'city 4', 'icon 4'),
array('name 5', 'city 5', 'icon 5'),
array('name 6', 'city 6', 'icon 6')
), true)->end();
# update
// return bool
$users->update(array
(
'name' => 'new name',
'icon' => 'new icon'
))->where('id = ?', 5)->end();
# or
// return bool
$users->update(array
(
'name' => 'new name',
'icon' => 'new icon'
))->where('id = ? and name = ?', array(5, 'old name'))->end();
# or
// return bool
$users->update(array
(
'name' => 'new name',
'icon' => 'new icon'
))->where('id = ? and name = ?')->inputs(array(5, 'old name'))->end();
# select
// return bool
$users->select('*')
->where('id = ?', 5)
->limit(1)
->order('id', 'DESC')
->end();
// now fetch, just like pdo, any fetch method
$users->fetchAll(PDO::FETCH_OBJ);
# delete
// return bool
$users->delete()->where('id' , 5)->end();
// you can also add a sql statement
$users->delete()->sql('where id = ?', 5)->end();
// or
$users->delete()->sql('where id = ?')->inputs(5)->end();
# you can add any feature !
# smart, advanced development
$users->multi_delete = function(array $ids){
$inputs = $ids;
$ids = array_fill(1, count($ids), '?');
$ids = implode(', ', $inputs);
horus()->orm->delete()->where('id in '.$ids);
horus()->orm->inputs($inputs);
return horus()->orm->on(horus()->orm->table);
// NOTE: horus() function is only available from
// Version 1.3.0
};
// now use it
$users->multi_delete(array(1, 12, 3));
Horus provides you with simple ways to exted it easily without a hassle .
There are 2 ways {Events/Hooks
} or { OOP Overloading
}
/*
Those are horus hooks
----------------------------
horus.boot -> when horus starts
horus.before_dispatch -> before dispatch all routes
horus.after_dispatch -> after dispatch routes
horus.output -> to control the output { the output will be passed to all hooks }
horus.shutdown -> when horus shutsdown
----------------------------
*/
// edit the output
// horus passing the output as the first argument
// and the second (last) argument is contains the last value
// of the last dispatched event
events_listen( 'horus.output', function($output, $filtered){
return ''.(empty($filtered) ? $output : $filtered);
});
// new example for filtering
$txt = 'my text';
// add event (will edit on the $txt) so it will be the first arg
// but the last arg contains the value of last edited
event_listen('test-tag', function($default_text, $last_filtered){
if(empty($last_filtered)) {
return '<i>'.$default_text.'</i>';
} else
return '<i>'.$last_filtered.'</i>';
});
event_listen('test-tag', function($default_text, $last_filtered){
if(empty($last_filtered)) {
return '<b>'.$default_text.'</b>';
} else
return '<b>'.$last_filtered.'</b>';
});
// dispatch and edit it
// will show "<b><i>my text</i></b>"
echo events_dispatch('test-tag', $txt);
// stop with hello
events_listen('horus.boot', function(){
die('hi');
});
# all events stored in $GLOBALS['horus_events'], so you can control them too
OOP Overloading
// assign var to horus
horus() -> my_var = 'my value';
// get var
echo horus()-> my_var;
// add method
horus()->method = function($txt){
echo $txt;
};
// use method
horus()->method('hi'); // show hi
// use it as static
Horus::method('hi');
// unset var/method
unset(horus()->my_var);
// check if isset
isset(horus()->my_var);