Home News

APIQL 0.3 - Скрипт обработки команд языка запросов

05.09.2018

Скрипт нужен для определения и выполнения команд языка запросов. Он может определять собственные команды заданного пользователем языка запросов, с помощью определения синтаксиса этих команд. Скрипт компилирует вызовы команд путем создания 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 : [email protected] 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; } }

Скачать архивы

Темперини Мирко

1192

Комментировать

rss