我想要实现的是让我的应用程序使用自己的API。更具体地说,我正在将架构从HMVC改为:
CLIENTS
MODEL
model files
CONTROLLERS
API.php
-option to consume API directly as JSON
Clients.php
- consumes data directly from the API
- exactly the same as if it had called it from the MODEL
VIEW
控制器直接从“API”部分获取数据 - 但我避免了两个主要障碍:
a)将来自API控制器的JSON编码数据传递给Controller(只是为了节省编码/解码它的次要开销)
b)更重要的是,不必在每个请求上检查访问令牌,以确保允许应用程序访问信息。
我有以下情况:
用户登录系统并希望使用API - 他们发送有效的访问令牌
用户已登录系统 - 导航至API页面但未提供访问令牌,因此应将其重定向回该部分/ 404页面的控制器。
用户未登录我们的系统但拥有授权令牌,因此可以使用该API。
用户登录但未提供INCORRECT访问令牌,因此应收到无效的令牌消息。
我最终得到的解决方案效果很好,但似乎非常“意大利面条”代码!
我已经扩展了授权(Ion_Auth
)类,如下所示:
class Authentication extends Ion_auth {
public $application = false;
}
然后在我所有的控制器中
$this->authentication->application = true;
在__construct
:
最后在 API控制器中,我有:
private $application = false;
public function __construct()
{
$this->token = $this->input->get_post('token');
parent::__construct();
if($this->authentication->application == true){
$this->application = true;
}
//API should have a token set before anything can happen, this is for every request
if($this->token){
//Check that the token is valid
if (!$this->checkToken($this->token)){
$this->error('Token did not match');
}
//all clear if we get to here - token matched
}else{ //no token was found
//ok so we have no token - is the user logged in? If not then they are trying to use the API but haven't set a token in the request.
if (!$this->authentication->logged_in()){
$this->error('No Token was sent');
}else{
//user is logged in and might have gone to the page by mistake
if(!$this->application){
echo "you shouldn't be here"; //this will be replaced with the redirect
exit;
}
}
}
//all cases passed and the application can continue - however we have a flag of $this->application set now which will let us decide whether to just 'return' data as array / object OR (if false i.e. from API) then we json encode the data for consumption.
}
有一个功能:
private function sendIt($data){
if($this->application){
return $data;
}else{
$this->output
->set_content_type('application/json');
echo json_encode($data);
exit;
}
}
用于代替'return'以确保应用程序使用的数据以正确的格式使用,而API数据则采用JSON编码。
用法:
return $this->sendIt($clients);
这个功能正如我所说,但它似乎不是很简洁。任何人都可以提供任何关于我如何正确执行此操作的建议,即符合上述所有规则而无需在每个控制器中设置变量?
为清楚起见,我的文件夹结构如下:
CLIENTS
MODELS
CONTROLLERS
- Client
- Api
VIEWS
JOBS
MODELS
CONTROLLERS
- Jobs
- Api
VIEWS
导航到site/clients
的想法导致数据直接从API页面中提取而不需要访问令牌 - 但导航到'site / clients / api'会导致重定向(如果已登录) )如果已登录或未登录但传递了错误的令牌,则出现“无令牌”错误(如果未登录)或“错误令牌”错误。
我真的被困在这里,拥有600个控制器,所以我不想不止这么做!
最终要点
我不能使用类名和URL来识别直接调用API,因为我不想在每个不同的页面上设置规则,我当前的解决方案至少提供了一个剪切和粘贴解决方案!
修改
感谢halfer - 我无法在评论中回答,所以这里有一个编辑来解决他的评论并希望为他们增加清晰度
$this->authentication->application
只是查看请求是否为内部的触发器 - 它应该是'$is_application'
。
在authentication module
(在所有控制器之前运行)中设置为false的布尔值
在false
。{/ p>中设置为authentication module
那么,如果应用程序中的controller
为模块调用了API
控制器(我在自己的应用程序中使用它),则会将此标志设置为true
我用这个'标志'做两件事:
set the output type -> 'return' if the application requests the info or 'JSON' if it is requested directly from the API page.
Decide if an access token for the API needs to be present - if the application requests info from the API internally then no access token is required - if it is accessed directly from the URL then an access token is required.
我已经修改了顶部的结构,以更好地解释模块的布局。
导航到site/clients
会自动在控制器中查找clients.php
文件。
导航到site/clients/api
导航到客户端控制器文件夹 - 然后导航到api文件。
sites/clients
处的控制器消费者所有数据并将数据发送到site/clients/api
- 然后api与数据库进行通信。
我也将把它变成一个单独的功能,这样控制器看起来就不那么混乱了 - 但这就是魔法将要发生的地方 - 这只是在玩!而且这只是在玩!
希望增加清晰度,并再次感谢任何花时间达到这一点的人!!!!