PHP处理API是否不超过其限制?
我想知道我能做什么来避免多次调用API?例如,如果我试图使用yelp的api,它们在超过之前有一个调用限制(一旦超过这个数量,它们就会停止向您提供信息) 我能做什么?现在,我在从他们的站点获取信息所需的每个页面中都有以下内容(来自他们的API PHP示例):PHP处理API是否不超过其限制?,php,api,function,caching,oauth,Php,Api,Function,Caching,Oauth,我想知道我能做什么来避免多次调用API?例如,如果我试图使用yelp的api,它们在超过之前有一个调用限制(一旦超过这个数量,它们就会停止向您提供信息) 我能做什么?现在,我在从他们的站点获取信息所需的每个页面中都有以下内容(来自他们的API PHP示例): // For example, request business with id 'the-waterboy-sacramento' //$unsigned_url = "http://api.yelp.com/v2/business/th
// For example, request business with id 'the-waterboy-sacramento'
//$unsigned_url = "http://api.yelp.com/v2/business/the-waterboy-sacramento";
// For examaple, search for 'tacos' in 'sf'
//$unsigned_url = "http://api.yelp.com/v2/search?term=tacos&location=sf";
// My own code
$unsigned_url = "http://api.yelp.com/v2/search?term=".$term."";
// $term is coming from searching
// Set your keys here
$consumer_key = "some_id";
$consumer_secret = "some_id";
$token = "some_id";
$token_secret = "some_id";
// Token object built using the OAuth library
$token = new OAuthToken($token, $token_secret);
// Consumer object built using the OAuth library
$consumer = new OAuthConsumer($consumer_key, $consumer_secret);
// Yelp uses HMAC SHA1 encoding
$signature_method = new OAuthSignatureMethod_HMAC_SHA1();
// Build OAuth Request using the OAuth PHP library. Uses the consumer and token object created above.
$oauthrequest = OAuthRequest::from_consumer_and_token($consumer, $token, 'GET', $unsigned_url);
// Sign the request
$oauthrequest->sign_request($signature_method, $consumer, $token);
// Get the signed URL
$signed_url = $oauthrequest->to_url();
// Send Yelp API Call
$ch = curl_init($signed_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
$data = curl_exec($ch); // Yelp response
curl_close($ch);
当我想调用某个业务时,这似乎在每个页面上都做得太多了。我不使用它,但作为一个一般性的回答,考虑在数据库中缓存数据以减少API调用。它还将提高站点的性能,特别是当需要来自API的相同数据的同一页面多次加载时 这是一个基于文件的通用实现
/**
* Cache friendly function call stub.
*
* @param callback $Callback
* @param array $Arguments
* @param integer $Expiration
* @return mixed
*/
function CallFunctionAndCacheResult($Callback, array $Arguments, $Expiration = 3600){
// Validate $Callback
if(!is_callable($Callback)){
trigger_error('$Callback must be a callback.', E_USER_WARNING);
return false;
}
// Validate $Arguments (we need some to hash)
if(empty($Arguments)){
trigger_error('$Arguments cannot be empty.', E_USER_WARNING);
return false;
}
// Empty $Expiration means live calls
if(empty($Expiration)){
return call_user_func_array($Callback, $Arguments);
}
// Validate $Expiration (we need some to hash)
if(!is_numeric($Expiration) or (($Expiration = intval($Expiration)) < 1)){
trigger_error('$Expiration has to be a positive integer.', E_USER_WARNING);
return false;
}
// Hash the Arguments (Unique Call ID)
$Hash = md5(serialize($Arguments));
// Check if Cache file exists
if(is_file($Cache = dirname(__FILE__)."/{$Hash}.serial")){
// Test if file expired
if(($MTime = filemtime($Cache)) >= (time() - $Expiration)){
// Attempt to load data, assume it's corrupted
if(($Data = unserialize(file_get_contents($Cache))) !== false){
return $Data;
}
}
}
// Now regenerate the data if you got here
$Data = call_user_func_array($Callback, $Arguments);
// Store it, with LOCK_EX enabled to prevent collisions
file_put_contents($Cache, serialize($Data), LOCK_EX);
// Return the data
return $Data;
}
// Test case (store current time for 10 seconds, keep refreshing)
var_dump($Data = CallFunctionAndCacheResult(function(){
// Return some data to be cached
return array_merge(func_get_args(), array(
'cached' => gmstrftime('%A, %d %B %Y %H:%M:%S'),
));
}, array(
'Username',
'Password',
// ...
), 10));
/**
*缓存友好的函数调用存根。
*
*@param callback$callback
*@param数组$Arguments
*@param整数$Expiration
*@返回混合
*/
函数CallFunctionAndCacheResult($Callback,数组$Arguments,$Expiration=3600){
//验证$Callback
如果(!可调用($Callback)){
trigger_错误(“$Callback必须是回调,”,E_用户_警告);
返回false;
}
//验证$Arguments(我们需要一些参数进行散列)
if(空($Arguments)){
触发器错误(“$Arguments不能为空。”,E_USER_警告);
返回false;
}
//空$Expiration表示实时呼叫
if(空($Expiration)){
返回call\u user\u func\u数组($Callback,$Arguments);
}
//验证$Expiration(我们需要一些来散列)
如果(!是数值($Expiration)或($Expiration=intval($Expiration))<1)){
触发器_错误(“$Expiration必须是正整数。”,E_USER_警告);
返回false;
}
//散列参数(唯一调用ID)
$Hash=md5(序列化($Arguments));
//检查缓存文件是否存在
if(is_file($Cache=dirname(_file).“/{$Hash}.serial”)){
//测试文件是否过期
if(($MTime=filemtime($Cache))>=(time()-$Expiration)){
//尝试加载数据,假设数据已损坏
if($Data=unserialize(文件获取内容($Cache))!==false){
返回$Data;
}
}
}
//现在重新生成数据,如果你在这里
$Data=call\u user\u func\u数组($Callback,$Arguments);
//存储它,并启用LOCK_EX以防止冲突
文件内容($Cache,serialize($Data),LOCK_EX);
//返回数据
返回$Data;
}
//测试用例(存储当前时间10秒,保持刷新)
var_dump($Data=CallFunctionAndCacheResult(function()){
//返回一些要缓存的数据
返回数组\u合并(func\u get\u args(),数组(
'cached'=>gmstrftime(“%A,%d%B%Y%H:%M:%S”),
));
},数组(
“用户名”,
“密码”,
// ...
), 10));
希望它有意义。只需测试它,找出它,然后使用DB引擎即可获得相同的结果。我不使用它,但作为一般回答,考虑在数据库中缓存数据以减少API调用。它还将提高站点的性能,特别是当需要来自API的相同数据的同一页面多次加载时 这是一个基于文件的通用实现
/**
* Cache friendly function call stub.
*
* @param callback $Callback
* @param array $Arguments
* @param integer $Expiration
* @return mixed
*/
function CallFunctionAndCacheResult($Callback, array $Arguments, $Expiration = 3600){
// Validate $Callback
if(!is_callable($Callback)){
trigger_error('$Callback must be a callback.', E_USER_WARNING);
return false;
}
// Validate $Arguments (we need some to hash)
if(empty($Arguments)){
trigger_error('$Arguments cannot be empty.', E_USER_WARNING);
return false;
}
// Empty $Expiration means live calls
if(empty($Expiration)){
return call_user_func_array($Callback, $Arguments);
}
// Validate $Expiration (we need some to hash)
if(!is_numeric($Expiration) or (($Expiration = intval($Expiration)) < 1)){
trigger_error('$Expiration has to be a positive integer.', E_USER_WARNING);
return false;
}
// Hash the Arguments (Unique Call ID)
$Hash = md5(serialize($Arguments));
// Check if Cache file exists
if(is_file($Cache = dirname(__FILE__)."/{$Hash}.serial")){
// Test if file expired
if(($MTime = filemtime($Cache)) >= (time() - $Expiration)){
// Attempt to load data, assume it's corrupted
if(($Data = unserialize(file_get_contents($Cache))) !== false){
return $Data;
}
}
}
// Now regenerate the data if you got here
$Data = call_user_func_array($Callback, $Arguments);
// Store it, with LOCK_EX enabled to prevent collisions
file_put_contents($Cache, serialize($Data), LOCK_EX);
// Return the data
return $Data;
}
// Test case (store current time for 10 seconds, keep refreshing)
var_dump($Data = CallFunctionAndCacheResult(function(){
// Return some data to be cached
return array_merge(func_get_args(), array(
'cached' => gmstrftime('%A, %d %B %Y %H:%M:%S'),
));
}, array(
'Username',
'Password',
// ...
), 10));
/**
*缓存友好的函数调用存根。
*
*@param callback$callback
*@param数组$Arguments
*@param整数$Expiration
*@返回混合
*/
函数CallFunctionAndCacheResult($Callback,数组$Arguments,$Expiration=3600){
//验证$Callback
如果(!可调用($Callback)){
trigger_错误(“$Callback必须是回调,”,E_用户_警告);
返回false;
}
//验证$Arguments(我们需要一些参数进行散列)
if(空($Arguments)){
触发器错误(“$Arguments不能为空。”,E_USER_警告);
返回false;
}
//空$Expiration表示实时呼叫
if(空($Expiration)){
返回call\u user\u func\u数组($Callback,$Arguments);
}
//验证$Expiration(我们需要一些来散列)
如果(!是数值($Expiration)或($Expiration=intval($Expiration))<1)){
触发器_错误(“$Expiration必须是正整数。”,E_USER_警告);
返回false;
}
//散列参数(唯一调用ID)
$Hash=md5(序列化($Arguments));
//检查缓存文件是否存在
if(is_file($Cache=dirname(_file).“/{$Hash}.serial”)){
//测试文件是否过期
if(($MTime=filemtime($Cache))>=(time()-$Expiration)){
//尝试加载数据,假设数据已损坏
if($Data=unserialize(文件获取内容($Cache))!==false){
返回$Data;
}
}
}
//现在重新生成数据,如果你在这里
$Data=call\u user\u func\u数组($Callback,$Arguments);
//存储它,并启用LOCK_EX以防止冲突
文件内容($Cache,serialize($Data),LOCK_EX);
//返回数据
返回$Data;
}
//测试用例(存储当前时间10秒,保持刷新)
var_dump($Data=CallFunctionAndCacheResult(function()){
//返回一些要缓存的数据
返回数组\u合并(func\u get\u args(),数组(
'cached'=>gmstrftime(“%A,%d%B%Y%H:%M:%S”),
));
},数组(
“用户名”,
“密码”,
// ...
), 10));
希望它有意义。只需测试它,找出它并使用DB引擎即可获得相同的结果。缓存是您的朋友。当您认为自己在一次又一次地执行不需要的API查询时,您应该将信息缓存到cookie(如果是次要/非关键的信息)或数据库中
比如,如果一个用户希望刷新一个页面,在这个页面上我运行一个查询来获取他的名字,我不想超出限制。您可以获取他的名字一次,将其存储到cookie中,然后使用它,而不是每次查询。正如另一个答案所说,更快、更高效。缓存是您的朋友。