Скрипт нужен для определения и выполнения команд языка запросов. Он может определять собственные команды заданного пользователем языка запросов, с помощью определения синтаксиса этих команд. Скрипт компилирует вызовы команд путем создания PHP-кода, который выполняется после отправки возможных аргументов команды.
APIQL является инструментом для достижения простого и легкого способа использования интерфейса для ваших программ.
С APIQL можно создавать запросы, которые взаимодействуют с возложенных на них функциями, использование дополнительных аргументов и выполнения операций, запросов и т.д., соблюдая определённый синтаксис. с APIQL структура данных сохраняется, и выбирается JavaScript синтаксис для каждого типа информации.
Таким образом, вы можете использовать JSON объекты, массивы, логические значения или нулевые, числа и строки. Будет просто, например, создать базу данных в текстовом файле, а также набор запросов для управления ей.
И не только это, вы также можете создать API систему, которая отражает форму классических реляционных запросов базы данных и управлять результатами в условиях полной свободы.
Вы можете определять части запроса простым и интуитивно понятным способом, необходимые и дополнительное параметры запроса тоже. Ознакомьтесь с документацией, чтобы лучше понять, как APIQL может Вам помочь!
Лицензия BSD.
Системные требования скрипта:
PHP не младше 5.0 версии.
Исходник скрипта
/*
APIQL v. 0.3
Name : APIQL
Author : Temperini Mirko
Description : a custom api builder based on js notation,
to semplify you development application.
With this tool you can build your query with your custom
syntax/command
Version : 0.3
Date : 2011-07-17
Email : dottwatson@gmail.com
Licence : GPL
APIQL gives you the possibility to build your own queries with data,personal syntax and commands.
It is based on a model where you can define in order:
-if the command in required or optional
-the command name
-the command data accepted. The command data can be:
-string
-int
-float
-boolean
-null
-array a javascript array notation e.g. ["bar","foo",24]
-json a json string e.g. {bar:foo,"surname":doe,age:32}
-php code
APIQL supports subqueries
APIQL supports events as 'beforeQuery' , 'afterQuery' and 'error'
APIQL gives you a nice tool for convert not well formed json strings into a valid PHP JSON strings
How it works?
step 1: declare a model
step 2: register model and bind it to function
step 3: call your query
e.g.
apiql::register('!set/!new friend[json]','new_friend');
apiql::query('set new friend {name:bar,surname:foo}',25);
function new_friend($sql,$age){
echo 'you have requested to set a new friend as<br />';
var_dump($sql['new friend']);
echo "<br />the age of {$sql['new friend']['name']} is $age<br />";
}
See examples how to configure and use APIQL
*/
class apiql{
public static $syntax = array();
public static $callback = '';
public static $isValid = false;
public static $data = null;
public static $error = '';
public static $events = array(
'afterQuery' =>array(),
'beforeQuery' =>array(),
'error' =>array(),
);
private static $config=array(
'check_func_exists'=>false,
'display_errors'=>false,
'error_level'=>E_USER_WARNING
);
/*
* access: public
* description: sets your class configuration to prevent
* or not function exixtence,display errors
* vars: what [string] the configuration param name
* val [bool/int] the value of the param
*
*returns: null
*/
public static function set($what='',$val=false){
$what=(string)$what;
if(isset(self::$config[$what])){
self::$config[$what] = $val;
}
}
/*
* access: public
*
* description: get your class configuration param value
*
* vars: what [string] the configuration param name
*
*returns: the value on success, null on faailure
*/
public static function get($what=''){
$what=(string)$what;
if(isset(self::$config[$what])){
return self::$config[$what];
}
return null;
}
/*
* access: public
* vars: model [string] the query model to parse
* fn [string] the function name to bind the query
*
* return: true on success or false on failure
*/
public static function register($model='',$fn=''){
$elements=explode('/',$model);
foreach($elements as $el){
$tmp=array(
'model' =>trim($el),
'required' =>false,
'data_type' =>array(),
'callback' =>''
);
preg_match('/^
(?P<required>!|\?)
(?P<name>[a-z0-9_-\s]+)
(?P<data_type>(\[([a-z\s]+,?)+\])|$)
/xi',$el,$blocks);
if(empty($blocks)){
self::trigger_error("apiql query => invalid block `{$el}`");
return self::reset();
}
$tmp['required']=($blocks['required'] == '!')?true:false;
if(trim($blocks['data_type']) != ''){
$data=explode(',',substr($blocks['data_type'],1,-1));
foreach($data as $type){
$type=trim($type);
if(preg_match('/^(string|int|float|null|boolean|json|array|php)$/i',$type)){
$tmp['data_type'][]=strtolower($type);
}
else{
self::trigger_error("apiql query => invalid data type `{$type}`");
return self::reset(true);
}
}
}
self::$syntax[$blocks['name']]=$tmp;
}
if(!function_exists($fn) && self::$config['check_func_exists'] == true){
self::trigger_error("apiql query => undefined function `{$fn}` as callback");
return self::reset();
}
else{
self::$callback = $fn;
}
self::compile();
}
/*
* access: private
* description: try to compile the query ad register it
* vars: none
*
*returns: true on success or false on failure
*/
private static function compile(){
$const=array();
foreach(self::$syntax as $el){
$const[]=$el['model'];
}
$const =md5(implode('/',$const));
$const ='apiql_'.$const;
$value =array('query'=>self::$syntax,'callback'=>self::$callback);
$value =serialize($value);
if(!defined($const)){
self::reset();
return define($const,$value,true);
}
else{
self::trigger_error("unable to register query: query is already defined");
return self::reset(true);
}
}
/*
* access: public
*
* description: execute your query and bind its results on your binded function
*
* vars: req [string] the query to be executed
* [,opt1,op2,opt3...] all extra arguments will be
* passed to the binded function 'as is'
*
* return: your query results on success or false on failure
*/
public static function query($req=''){
$extra_data=func_get_args();
$not_extra=array_shift($extra_data);
$requested_reg='(?<requested>)';
$constants=get_defined_constants(true);
$constants=(isset($constants['user']))?$constants['user']:array();
foreach($constants as $ckey=>$const){
if(preg_match('/^apiql_[a-f0-9]{32}$/i',$ckey)){
//extrasc infos on constant name
$qry_data=unserialize($const);
//var_dump($qry_data);
$reg=array();
$cnt=0;
foreach($qry_data['query'] as $name=>$el){
$data_type='';
if(!empty($el['data_type'])){
$data_type=array();
foreach($el['data_type'] as $data_value){
if($data_value=='string') $data_type[] ='\'[^\']*\'';
elseif($data_value=='int') $data_type[] ='((\'\-?\d+\')|\-?(\d+))';
elseif($data_value=='float') $data_type[] ='((\'\-?(\d+)?\.\d+\')|\-?(\d+)?\.\d+)';
elseif($data_value=='null') $data_type[] ='(null)';
elseif($data_value=='boolean') $data_type[] ='(true|false)';
elseif($data_value=='json') $data_type[] ='(\{[^\}]+\})';
elseif($data_value=='array') $data_type[] ='(\[[^\]]+\])';
elseif($data_value=='php') $data_type[] ='(\(.+\))';
}
$data_type[]='apiql::query\([[:space:]]*("[^"]*"|\'[^\']*\')[[:space:]]*\)';
$data_type='[[:space:]]+(?P<data_'.$cnt.'>'.implode($data_type,'|').')';
}
$name=preg_quote($name,'/');
$name=preg_replace('/[[:space:]]+/','[[:space:]]+',$name);
if($cnt > 0) $name='[[:space:]]+'.$name;
$reg_el="(?P<name_{$cnt}>{$name}{$data_type})";
if($el['required'] == false) $reg_el.='?';
$reg[]=$reg_el;
$cnt++;
}
$reg ="/^[[:space:]]*\n".implode("\n",$reg)."\n[[:space:]]*$/smix";
preg_match($reg,$req,$check);
if(!empty($check)){
//check if the query contains subqueries.
//in this case we execute subqueries and
//each query is replaced with its result
preg_match_all('/
(?P<query_block>
apiql::query\(
[[:space:]]*
(?P<query>
("[^"]*"|\'[^\']*\')
)
[[:space:]]*
\)
)/Usmix',$req,$sub_queries);
if(isset($sub_queries['query_block']) && !empty($sub_queries['query_block'])){
foreach($sub_queries['query_block'] as $sq_i=>$sq_str){
$sq_query =substr($sub_queries['query'][$sq_i],1,-1);
$sq_res =apiql::query($sq_query);
$sq_res =(is_string($sq_res))
?"'".str_replace("'","\\'",$sq_res)."'"
:apiql::string($sq_res);
$req=str_replace($sq_str,$sq_res,$req);
}
}
}
preg_match($reg,$req,$check);
if(!empty($check)){
preg_match($reg,$req,$check);
$fn_data=array();
foreach($check as $ck_key=>$ck_val){
if(strpos($ck_key,'name_') === 0){
$fn_data[$ck_key] =$ck_val;
$data_index =substr($ck_key,5);
if(isset($check['data_'.$data_index])){
$fn_data[$ck_key] =str_replace($check['data_'.$data_index],'',$fn_data[$ck_key]);
$fn_data[$ck_key] =trim($fn_data[$ck_key]);
$fn_data['data_'.$data_index] =$check['data_'.$data_index];
}
}
}
$fn_args=array('names'=>array(),'data'=>array());
foreach($fn_data as $f_key=>$f_value){
if(strpos($f_key,'name_') === 0){
$f_cnt=str_replace('name_','',$f_key);
$fn_args['names'][$f_cnt]=trim($f_value);
if(isset($fn_data['data_'.$f_cnt])){
$test_data=trim($fn_data['data_'.$f_cnt]);
if(preg_match('#^({.*}|\[.*\])$#',$test_data)){
$test_data=self::JSONdecode($test_data,true);
}
else{
$test_data=self::checkStr($test_data);
}
$fn_args['data'][$f_cnt]=$test_data;
}
}
}
//var_dump($fn_args);
self::$data=array();
foreach($fn_args['names'] as $fk=>$name){
//array_key_exists is better then isset,
//it is a good solution for not make confusion with null values
$to_name=(array_key_exists($fk, $fn_args['data']) )
?$fn_args['data'][$fk]
:false;
self::$data[$name]=$to_name;
}
//beforeQuery events
self::fireEvents('beforeQuery');
$send_to_fn=$extra_data;
array_unshift($send_to_fn,self::$data);
$out=call_user_func_array($qry_data['callback'],$send_to_fn);
//afterQuery events
self::fireEvents('afterQuery');
return $out;
}
}
}
self::trigger_error("apiql query => undefined query");
return self::reset(true);
}
/*
* access: private
*
* description: convert a string rappresentation of a boolean,number or null
* value in its effective value
*
* vars: str [string] the string to be checked
*
* return: its real value and type
*/
private static function checkStr($str){
if(preg_match('#^\'.*\'$#',$str)) $str=substr($str,1,-1);
if(is_numeric($str)){
eval('$check = '.$str.';');
return $check;
}
if(strtolower($str) == 'true') return true;
if(strtolower($str) == 'false') return false;
if(strtolower($str) == 'null') return null;
return $str;
}
/*
* access: public
*
* description: bind an event function on before or after a query
*
* vars: ev [string] the event to register
* can be 'beforeQuery','afterQuery' or 'error'
*
* returns: null
*/
public static function addEvent($ev,$fn_name){
$ev =strtolower((string)$ev);
$ev =str_replace('query','Query',trim($ev));
$fn_name=strtolower(trim((string)$fn_name));
if(isset(self::$events[$ev])){
self::$events[$ev][]=$fn_name;
}
}
/*
* access: public
*
* description: remove a specific function from the event specified
*
* vars: ev [string] the event from where the function will be deleterd
* fn_name [string] the function to be removed from.
*
* returns: null
*/
public static function removeEvent($ev,$fn_name){
$ev =strtolower((string)$ev);
$ev =str_replace('query','Query',trim($ev));
$fn_name=strtolower(trim((string)$ev));
$key =array_search($fn_name,self::$events[$ev]);
if($key !== false){
unset(self::$events[$ev][$key]);
}
}
/*
* access: public
*
* description: remove all function from the events specified
*
* vars: [ev1,ev2,ev3] [string] the events from where the functions will be removed
*
* returns: null
*/
public static function removeEvents(){
$evs=func_get_args();
if(!empty($evs)) $evs=array_keys(self::$events);
foreach($evs as $ev){
$ev=strtolower((string)$ev);
$ev=str_replace('query','Query',trim($ev));
if(isset(self::$events[$ev]) && !empty(self::$events[$ev])){
self::$events[$ev]=array();
}
}
return true;
}
/*
* access: public
*
* description: fires all functions from the events specified
*
* vars: [ev1,ev2,ev3] [string] the events from where the functions will be fired
*
* returns: null
*/
public static function fireEvents(){
$evs=func_get_args();
if(empty($evs)) $evs=array_keys(self::$events);
foreach($evs as $ev){
$ev=strtolower((string)$ev);
$ev=str_replace('query','Query',trim($ev));
if(isset(self::$events[$ev]) && !empty(self::$events[$ev])){
foreach(self::$events[$ev] as $fn){
if(function_exists($fn))
$ev_data=call_user_func($fn,self::$data);
}
}
}
}
/*
* access: private
*
* description: reset the internal data except the configuration
*
* vars: asError [bool] if true, fires the 'error' event
*
* returns: false if is called as actiot to execute after an error, or true
*/
private static function reset($asError=false){
self::$syntax = array();
self::$callback = '';
self::$isValid = false;
self::$data = null;
self::$error = '';
if($asError) {
self::fireEvents('error');
return false;
}
return true;
}
/*
* access: private
*
* description: internal error trigger
*
* vars: msg [string] the string to be triggered
*
* returns: null
*/
private static function trigger_error($msg){
self::$error=$msg;
if(self::$config['display_errors'] == true){
trigger_error($msg,self::$config['error_level']);
}
}
/*
* access: public
*
* description: convert a not well formed json string in valid php json object
*
* vars: json [string] the json string to be analyzed
* assoc [bool] if true, force as object
* returns: a well formed json string, valid for PHP
*/
public static function JSONdecode($json, $assoc = false){
$json = str_replace(array("\n","\r"),"",$json);
//remove trailing commas and encode in utf8
$json=preg_replace('/,\s*([\]}])/m', '$1', $json);
$json = preg_replace('/([{,])(\s*)([^"]+?)\s*:/','$1"$3":',$json);
$json = preg_replace('/([{,])"\'([^"]+?)\'":/','$1"$2":',$json);
$json = preg_replace('/:(\s*)([^"]+?)\s*([,}])/',':"$2"$3',$json);
$json = preg_replace('/:"\'([^"]+?)\'"([,}])/',':"$1"$2',$json);
$json = preg_replace('/:"(null|true|false|\d+\.\d+|\d+|\.\d+)"([,}])/',':$1$2',$json);
return json_decode($json,$assoc);
}
/*
* access: public
*
* description: convert the passed argument as json string
*
* vars: obj the value to be converted
*
* returns: converted value
*/
public static function string($obj=null){
if(is_object($obj)){
$out=get_object_vars($obj);
$out=json_encode($out);
}
elseif(is_array($obj)) {$out=json_encode($obj);}
elseif(is_bool($obj)) {$out=($obj == true)?'true':'false';}
elseif(is_null($obj)) {$out= 'null';}
else {$out=(string)$obj;}
return $out;
}
}
Скачать архивы
Скачать zip-архив со скриптом.
Скачать tar.gz-архив со скриптом.