创建以 API 为中心的 Web 应用(Creating an API-Centric Web Application)

By | 2018年7月10日

Planning to start working on a new web application? In this tutorial, we’ll discuss how to create an API-centric web application, and explain why this is essential in today’s multi-platform world.

Introduction

API?

For those who are unfamiliar with the term, API is short for Application Programming Interface. According to Wikipedia:

An application programming interface (API) is a source code based specification intended to be used as an interface by software components to communicate with each other. An API may include specifications for routines, data structures, object classes, and variables.

In simpler terms, an API refers to a set of functions built into an application, which can be used by other applications (or by itself, as we’ll see later), to interact with the application. An API is a great way to expose an application’s functionality to external applications safely and securely, since all functionality that these external applications can do is limited with what functionality is exposed in the API.

正计划着要开始搞一个新的网络应用?在这篇教程中,我们将讨论如何创建以API为中心的网络应用,还会解释在今天的多平台世界,这类应用为什么是重要的。

引言

API?

对于还不甚熟悉这个术语的朋友,API是Application Programming Interface(应用编程接口)的简称。根据维基百科

API是以源代码为基础的约定,它用于软件组件之间相互通信的接口。API可能包含函数、数据结构、对象类、以及变量等的约定。

创建以 API 为中心的 Web 应用(Creating an API-Centric Web Application)

API可视化

图片蒙惠http://blog.zoho.com

简单地讲,API指的是一组应用中的函数,它们能够被其它应用(或者这些函数所属应用自己,下文中我们将会看到)用来与应用进行交互。API是一种很棒的向外部应用安全和妥善地表明其功能的方式,因为这些外部应用所能利用的所有功能仅限于API中所表现出的功能。

What’s an “API-Centric” Web Application?

An API-Centric Web Application is a web application that basically executes most, if not, all its functionality through API calls.

An API-Centric Web Application is a web application that basically executes most, if not, all its functionality through API calls. For example, if you were to log in a user, you would send his credentials to the API, and the API would return to you a result saying if the user provided the correct user-password combination.

Another characteristic of an API-Centric Web Application is that the API will always be stateless, meaning it can’t recognize API calls by session. Since API calls will be made by usually via the backend code, it will be hard to implement session handling, since there are usually no cookies involved in that. This limitation is actually good — this “forces” a developer to build an API that works not based on the state of the current user, but rather on functionality, which in turn, makes it easier to test, since the current state of a user doesn’t need to be recreated.

什么是“以API为中心的”网络应用?

以API为中心的网络应用就是基本上通过API调用执行大多数甚或所有功能的一类网络应用。

以API为中心的网络应用就是基本上通过API调用执行大多数甚或所有功能的一类网络应用。举个例子,如果你正要登录一个用户,你应当将其认证信息发送给API,然后API会向你返回一个结果,说明该用户是否提供了正确的用户名-密码组合。

以API为中心的网络应用的另外一个特征就是API一直是无状态的,这意味着这种应用无法辨别由会话发起的API调用。由于API调用通常由后端代码构成,实现对会话的掌控将比较困难,因为这其中通常没有cookies介入。这种局限事实上是好事——它“迫使”开发者建造不基于当前用户状态工作的API,但是相应地在功能上,它使测试易于进行,因为用户的当前状态无需被重建。

Why go through all this trouble?

As web developers, we’ve seen technology evolve first hand. It’s common knowledge that people today don’t just use applications via a browser, but through other gadgets, like mobile phones and tablets. For example, this article on Mashable, entitled “Consumers Now Spending More Time on Mobile Apps Than the Web”, states:

Consumers are spending more time on mobile apps than on the web for the first time, a new report claims.

Flurry compared its mobile data to stats from comScore and Alexa, and found that in June, consumers spent 81 minutes per day using mobile apps, compared to 74 minutes of web surfing.

Here’s a more recent article from ReadWriteWeb, entitled “More People Browse On Mobile Than Use IE6 & IE7 Combined:

The latest data on browser trends from Sitepoint show that more people browse the Web on smartphones than use Internet Explorer 6 and 7 combined. Those two old clunkers have been the bugbears of Web developers for years, requiring sites to degrade as nicely as possible to that least common denominator of browsers. But it’s a new world now; 6.95% of Web activity in November 2011 was on mobile browsers, and only 6.49% was on IE 6 or 7.

As we can clearly see, more and more people get their news from alternative venues, specifically mobile devices.

为什么要经历这些麻烦?

作为Web开发者,我们已经亲眼目睹了技术的进步。有一个常识是,当代的人们不会只通过浏览器来使用应用,还会通过其它诸如移动电话和平板电脑之类的设备使用。举个例子,这篇发表在Mashable上的名为“用户在移动应用上花的时间比在网络上的多”的写道:

一项新近的报告表明,用户花在移动应用上的时间首次超过了花在网络上的时间。

Flurry对比了其移动数据与来自comScore和Alexa的统计数据,发现在六月,用户每天花费81分钟使用移动应用,而只花74分钟用于网上冲浪。

这里还有一篇来自ReadWriteWeb的更新的文章“在移动设备上浏览网络的人多于使用IE6和IE7的人数总和”

来自Sitepoint的
浏览器趋势的最新数据表明,在智能手机上浏览Web的人比使用IE6和IE7浏览的人更多。这两件难有起色的老古董多年来一直是Web开发者的噩梦,它们需要各网站尽可能妥当地降格到至少常用浏览器所能支持的水平。但是现在时代不同了;2011年十一月中,6.95%的Web活动在移动浏览器上发生,而发生在IE6或IE7上的则只有6.49%。

正如我们所见,越来越多的人正通过其它途径获得讯息,特别是移动设备。

What does this have to do with me creating an API-Centric Web Application?

This would inevitably lead to more usage of our application, since it can be used anywhere a person wants.

One of the main advantages of creating an API-centric application is that it helps you build functionality that can be used by ANY device, be it a browser, a mobile phone, a tablet, or even a desktop app. All you need to do is to create the API in such a way that all these devices can communicate with it, and voila! You’ll have built a centralized application that can take input and execute functionality from any device that a person has!

创建以 API 为中心的 Web 应用(Creating an API-Centric Web Application)

API-Centric Application Diagram

这与我创建以API为中心的网络应用有何关系?

这必将会使我们的应用更加有用,因为它可以用在任何你需要的地方。

创建以API为中心的网络应用的主要优势之一便是它帮助你建立可以用于任何设备的功能,浏览器、移动电话、甚至是桌面应用。你所需要做的就是创建的API能够使所有这些设备利用它完成通信,然后,瞧!你将能够建造一个集中式应用,它能够接受来自用户所使用的任何设备的输入并执行相应的功能。

创建以 API 为中心的 Web 应用(Creating an API-Centric Web Application)

以API为中心的应用的框图

By creating an application in this manner, we’re able to easily take advantage of the different mediums used by different people. This would inevitably lead to more usage of an application, since it can be used anywhere a person wants.

To drive the point home, here’s an article about Twitter’s new redesigned website, which tells us about how they now use their API to power Twitter.com, essentially making it API-centric:

One of the most important architectural changes is that Twitter.com is now a client of our own API. It fetches data from the same endpoints that the mobile site, our apps for iPhone, iPad, Android, and every third-party application use. This shift allowed us to allocate more resources to the API team, generating over 40 patches. In the initial page load and every call from the client, all data is now fetched from a highly optimized JSON fragment cache.

In this tutorial, we’ll be creating a simple TODO list application that is API-Centric and create one front-end client on the browser that interacts with our TODO list application. By the end, you’ll know the integral parts of an API-Centric application, and at the same time, how to facilitate secure communication between the two. With that in mind, let’s begin!

通过以这种方式创建应用,我们能够从容地利用不同的人使用不同的媒介这一优势。这必将使应用更加有用,因为它能用在用户需要的任何地方。

为了证明我们的观点,这里有一篇关于Twitter的重新设计的网站的文章,文章告诉我们他们现在如何利用他们的API来驱动Twitter.com的,实质上是使其以API为中心:

最重要的架构改动之一就是Twitter.com现在是我们自己API的客户。它从终端提取数据,此终端与移动网站,我们为iPhone、iPad、Android,以及所有第三方应用所用端点相同。这一转变使我们能向API团队分配更多的资源,同时生成了40多个补丁。在初始页面负载和来自客户端的每个调用上,所有的数据现在都是从一个高度优化的JSON段缓存中获取的。

在本篇教程中,我们将创建一个简单的TODO列表应用,该应用以API为中心;还要创建一个浏览器上的前端客户端,该客户端与我们的TODO列表应用进行交互。文末,你就能了解一个以API为中心的应用的有机组成部分,同时,还能了解怎样使应用和客户端两者之间的安全通信变得容易。记住这些,我们开始吧!

Step 1: Plan the Application’s Functions

The TODO application we’ll be building in this tutorial will have the basic CRUD functions:

  • Create TODO Items
  • Read TODO Items
  • Update TODO Items (rename, mark as done, mark as undone)
  • Delete TODO Items

Each TODO item will have:

  • a Title
  • a Date Due
  • a Description
  • a flag to tell if the TODO Item Is Done

Let’s mockup the application as well so we have a guide on how it should look like afterwards:

创建以 API 为中心的 Web 应用(Creating an API-Centric Web Application)

SimpleTODO Mockup

步骤 1: 规划该应用的功能

本教程中我们将要构建的这个 TODO 应用将会有下面几个基本的CRUD功能:

  • 创建 TODO 条目
  • 读取 TODO 条目
  • 更新 TODO 条目 (重命名,标记为完成,标记为未完成)
  • 删除 TODO 条目

每一个 TODO 条目将拥有:

  • 一个标题 Title
  • 一个截止日期 Date Due
  • 一个描述 Description
  • 一个判断 TODO 条目是否完成的标志 Is Done

让我们模拟一下该应用,使我们考虑该应用以后会是什么样子时,能有有一个直观的参考:

创建以 API 为中心的 Web 应用(Creating an API-Centric Web Application)

简单的TODO 模拟示例

Step 2: Create the API Server

Since we’re developing an API-Centric application, we’ll be creating two “projects”: the API Server, and the Front-end Client. Let’s begin by creating the API server first.

On your web server’s folder, create a folder namedsimpletodo_api, and create anindex.phpfile. Thisindex.phpfile will act as a front controller for the API, so all requests to the API server will be made through this file. Open it up and put the following code inside:

<?php
// Define path to data folder
define('DATA_PATH', realpath(dirname(__FILE__).'/data'));

//include our models
include_once 'models/TodoItem.php';

//wrap the whole thing in a try-catch block to catch any wayward exceptions!
try {
	//get all of the parameters in the POST/GET request
	$params = $_REQUEST;
	
	//get the controller and format it correctly so the first
	//letter is always capitalized
	$controller = ucfirst(strtolower($params['controller']));
	
	//get the action and format it correctly so all the
	//letters are not capitalized, and append 'Action'
	$action = strtolower($params['action']).'Action';

	//check if the controller exists. if not, throw an exception
	if( file_exists("controllers/{$controller}.php") ) {
		include_once "controllers/{$controller}.php";
	} else {
		throw new Exception('Controller is invalid.');
	}
	
	//create a new instance of the controller, and pass
	//it the parameters from the request
	$controller = new $controller($params);
	
	//check if the action exists in the controller. if not, throw an exception.
	if( method_exists($controller, $action) === false ) {
		throw new Exception('Action is invalid.');
	}
	
	//execute the action
	$result['data'] = $controller->$action();
	$result['success'] = true;
	
} catch( Exception $e ) {
	//catch any exceptions and report the problem
	$result = array();
	$result['success'] = false;
	$result['errormsg'] = $e->getMessage();
}

//echo the result of the API call
echo json_encode($result);
exit();

What we’ve essentially built here is a simple front controller that does the following:

  • Accept an API call with any number of parameters
  • Extract theControllerandActionfor the API call
  • Make the necessary checks to ensure that theControllerandActionexist
  • Execute the API call
  • Catch errors, if any
  • Send back a result to the caller

步骤 2: 创建API服务器

既然我们是在开发一个以API为中心的应用,我们将创建两个“项目”: API 服务器,和前端客户端。 我们首先从创建API服务器开始。

在你的web server文件夹,创建一个文件夹,命名为simpletodo_api,然后创建一个index.php文件。这个index.php文件将作为一个访问API的前端控制器,所以,所有访问API服务器的请求都会由该文件产生。打开它并往里输入下列代码:

<?php
// 定义数据目录的路径
define('DATA_PATH', realpath(dirname(__FILE__).'/data'));

//引入我们的models
include_once 'models/TodoItem.php';

//在一个try-catch块中包含所有代码,来捕获所有可能的异常!
try {
	//获得在POST/GET request中的所有参数
	$params = $_REQUEST;
	
	//获取controller并把它正确的格式化使得第一个字母总是大写的
	$controller = ucfirst(strtolower($params['controller']));
	
	//获取action并把它正确的格式化,使它所有的字母都是小写的,并追加一个'Action'
	$action = strtolower($params['action']).'Action';

	//检查controller是否存在。如果不存在,抛出异常
	if( file_exists("controllers/{$controller}.php") ) {
		include_once "controllers/{$controller}.php";
	} else {
		throw new Exception('Controller is invalid.');
	}
	
	//创建一个新的controller实例,并把从request中获取的参数传给它
	$controller = new $controller($params);
	
	//检查controller中是否存在action。如果不存在,抛出异常。
	if( method_exists($controller, $action) === false ) {
		throw new Exception('Action is invalid.');
	}
	
	//执行action
	$result['data'] = $controller->$action();
	$result['success'] = true;
	
} catch( Exception $e ) {
	//捕获任何一次样并且报告问题
	$result = array();
	$result['success'] = false;
	$result['errormsg'] = $e->getMessage();
}

//回显调用API的结果
echo json_encode($result);
exit();

实质上,这里我们创建的是一个简单的前端控制器,它实现了下列功能:

  • 接受一次拥有任意个参数的API调用
  • 为本次API调用抽取出Controller和Action
  • 进行必要的检查确保Controller和Action都存在
  • 执行API调用
  • 捕获异常,如果有的话
  • 返回一个结果给调用者
Besides theindex.phpfile, create three folders: a
controllers,
models and
data folder.

创建以 API 为中心的 Web 应用(Creating an API-Centric Web Application)
  • The controllers folder will contain all the controllers we’ll be using for the API server. We’ll be building it using the MVC architecture to make the structure of the API server cleaner and more organized.
  • The models folder will contain all the data models for the API server.
  • The data folder will be where the API server saves any data

Go into the controllers folder and create a file calledTodo.php. This will be our controller for any TODO list related tasks. With the functions we’ll be needing for our TODO application in mind, create the necessary methods for the Todo controller:

<?php
class Todo
{
	private $_params;
	
	public function __construct($params)
	{
		$this->_params = $params;
	}
	
	public function createAction()
	{
		//create a new todo item
	}
	
	public function readAction()
	{
		//read all the todo items
	}
	
	public function updateAction()
	{
		//update a todo item
	}
	
	public function deleteAction()
	{
		//delete a todo item
	}
}

Now, add the necessary functionality to eachaction. I’ll provide the code for thecreateActionmethod and I’ll leave it up to you to create the code for the other methods. If you’re not in the mood though, you can just download the source code for the demo and copy it from there.

public function createAction()
{
	//create a new todo item
	$todo = new TodoItem();
	$todo->title = $this->_params['title'];
	$todo->description = $this->_params['description'];
	$todo->due_date = $this->_params['due_date'];
	$todo->is_done = 'false';
	
	//pass the user's username and password to authenticate the user
	$todo->save($this->_params['username'], $this->_params['userpass']);
	
	//return the todo item in array format
	return $todo->toArray();
}

除了需要创建index.php外你还需要创建三个文件夹: 
controllers,
models 和 
data.

创建以 API 为中心的 Web 应用(Creating an API-Centric Web Application)
  • controllers  文件夹存放的是所有我们API服务器将会用到的的控制器。我们用MVC架构来使API服务器结构更清楚合理。
  • models 文件夹存放所有API服务器要用到的数据模型。
  • data 文件夹将会用来保存API服务器的任何数据。

在controllers文件夹下创建一个叫Todo.php的文件。这将是任何TODO列表有关任务的控制器。按照TODO应用所需提供的功能,向Todo控制器里面添加必要的方法:

<?php
class Todo
{
	private $_params;
	
	public function __construct($params)
	{
		$this->_params = $params;
	}
	
	public function createAction()
	{
		//create a new todo item
	}
	
	public function readAction()
	{
		//read all the todo items
	}
	
	public function updateAction()
	{
		//update a todo item
	}
	
	public function deleteAction()
	{
		//delete a todo item
	}
}

现在为每个action中添加必要的功能实现。我将会提供createAction()方法的源码,其他方法将留作作业。如果你觉得毫无头绪,你也可以下载示例的源码,从那里拷贝。

public function createAction()
{
	//create a new todo item
	$todo = new TodoItem();
	$todo->title = $this->_params['title'];
	$todo->description = $this->_params['description'];
	$todo->due_date = $this->_params['due_date'];
	$todo->is_done = 'false';
	
	//pass the user's username and password to authenticate the user
	$todo->save($this->_params['username'], $this->_params['userpass']);
	
	//return the todo item in array format
	return $todo->toArray();
}

CreateTodoItem.phpinside themodelsfolder so we can create the “item creation” code. Take note that I won’t be connecting to a database, rather, I’ll be saving the information into files. It should be relatively easy though to make this work with any database.

<?php
class TodoItem
{
	public $todo_id;
	public $title;
	public $description;
	public $due_date;
	public $is_done;
	
	public function save($username, $userpass)
	{
		//get the username/password hash
		$userhash = sha1("{$username}_{$userpass}");
		if( is_dir(DATA_PATH."/{$userhash}") === false ) {
			mkdir(DATA_PATH."/{$userhash}");
		}
		
		//if the $todo_id isn't set yet, it means we need to create a new todo item
		if( is_null($this->todo_id) || !is_numeric($this->todo_id) ) {
			//the todo id is the current time
			$this->todo_id = time();
		}
		
		//get the array version of this todo item
		$todo_item_array = $this->toArray();
		
		//save the serialized array version into a file
		$success = file_put_contents(DATA_PATH."/{$userhash}/{$this->todo_id}.txt", serialize($todo_item_array));
		
		//if saving was not successful, throw an exception
		if( $success === false ) {
			throw new Exception('Failed to save todo item');
		}
		
		//return the array version
		return $todo_item_array;
	}
	
	public function toArray()
	{
		//return an array version of the todo item
		return array(
			'todo_id' => $this->todo_id,
			'title' => $this->title,
			'description' => $this->description,
			'due_date' => $this->due_date,
			'is_done' => $this->is_done
		);
	}
}

ThecreateActionmethod calls two functions on theTodoItemmodel:

  • save() – this saves theTodoIteminto a file, as well as set thetodo_idfor theTodoItemif necessary
  • toArray() – this returns an array version of theTodoItem, where the variables are the array’s indexes

Since the API is called via HTTP requests, let’s test that API call by calling it through the browser:

http://localhost/simpletodo_api/?controller=todo&action=create&title=test%20title&description=test%20description&due_date=12/08/2011&username=nikko&userpass=test1234

If everything worked, you should see a new folder inside thedatafolder, and inside that folder, you should see a file with the following content:

创建以 API 为中心的 Web 应用(Creating an API-Centric Web Application)

createAction()result

Congratulations! You’ve successfully created an API server and made an API call!

在文件夹models下创建TodoItem.php,这样我们就可以创建“条目添加”的代码了。注意:我并没有和数据库进行连接,相反我将信息保存到文件中,虽然这可以用任何数据库来实现,但是
这样做相对来说要容易些

<?php
class TodoItem
{
	public $todo_id;
	public $title;
	public $description;
	public $due_date;
	public $is_done;
	
	public function save($username, $userpass)
	{
		//get the username/password hash
		$userhash = sha1("{$username}_{$userpass}");
		if( is_dir(DATA_PATH."/{$userhash}") === false ) {
			mkdir(DATA_PATH."/{$userhash}");
		}
		
		//if the $todo_id isn't set yet, it means we need to create a new todo item
		if( is_null($this->todo_id) || !is_numeric($this->todo_id) ) {
			//the todo id is the current time
			$this->todo_id = time();
		}
		
		//get the array version of this todo item
		$todo_item_array = $this->toArray();
		
		//save the serialized array version into a file
		$success = file_put_contents(DATA_PATH."/{$userhash}/{$this->todo_id}.txt", serialize($todo_item_array));
		
		//if saving was not successful, throw an exception
		if( $success === false ) {
			throw new Exception('Failed to save todo item');
		}
		
		//return the array version
		return $todo_item_array;
	}
	
	public function toArray()
	{
		//return an array version of the todo item
		return array(
			'todo_id' => $this->todo_id,
			'title' => $this->title,
			'description' => $this->description,
			'due_date' => $this->due_date,
			'is_done' => $this->is_done
		);
	}
}

createAction方法使用到TodoItem模型里面两个方法:

  • save() – 该方法将TodoItem保存到一个文件中,如有必要,需要设置todo_id。
  • toArray() – 该方法返回一个以变量为索引的数组Todo条目。

由于API需要通过HTTP请求调用,在浏览器输入如下地址测试API:

http://localhost/simpletodo_api/?controller=todo&action=create&title=test%20title&description=test%20description&due_date=12/08/2011&username=nikko&userpass=test1234

如果没有错,你应该在data文件夹下看到一个新的文件夹,在该文件夹里面有一个文件,文件内容如下:

创建以 API 为中心的 Web 应用(Creating an API-Centric Web Application)

createAction()结果

恭喜!您已经成功创建了一个的API服务器和API调用!

Step 3: Secure the API Server with anAPP IDandAPP SECRET

Currently, the API server is set to accept ALL API requests. We’ll need to limit it to our own applications only, to ensure that only our own front-end clients are able to make API requests. Alternatively, you can actually create a system wherein users can create their own applications that have access to your API server, similar to how Facebook and Twitter applications work.

Begin by creating a set of id-key pairs for the clients that will be using the API server. Since this is just a demo, we can use any random, 32 character string. For theAPP ID, let’s say it’s application APP001.

Open the index.php file again, and then update it with the following code:

<?php
// Define path to data folder
define('DATA_PATH', realpath(dirname(__FILE__).'/data'));

//Define our id-key pairs
$applications = array(
	'APP001' => '28e336ac6c9423d946ba02d19c6a2632', //randomly generated app key 
);
//include our models
include_once 'models/TodoItem.php';

//wrap the whole thing in a try-catch block to catch any wayward exceptions!
try {
	//*UPDATED*
	//get the encrypted request
	$enc_request = $_REQUEST['enc_request'];
	
	//get the provided app id
	$app_id = $_REQUEST['app_id'];
	
	//check first if the app id exists in the list of applications
	if( !isset($applications[$app_id]) ) {
		throw new Exception('Application does not exist!');
	}
	
	//decrypt the request
	$params = json_decode(trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $applications[$app_id], base64_decode($enc_request), MCRYPT_MODE_ECB)));
	
	//check if the request is valid by checking if it's an array and looking for the controller and action
	if( $params == false || isset($params->controller) == false || isset($params->action) == false ) {
		throw new Exception('Request is not valid');
	}
	
	//cast it into an array
	$params = (array) $params;
	...
	...
	...

步骤3:确保API服务器具有APP ID和APP SECRET

目前,API服务器被设置为接受全部API请求。我们将需要将之限制在我们自己的应用上,以确保只有我们自己的前端客户端能够完成API请求。另外,你实际上也可以创建一个系统,其中的用户可以创建他们自己的应用,而那些应用也用用对你的API服务器的访问权,这与Facebook和Twitter的应用的的工作原理类似。

我们从为使用API服务器的用户创建一组id-密码对开始。由于这只是一个Demo,我们可以使用任何随机的、32位字符串。对于APP ID,我们将其设定为APP001

再次打开index.php文件,然后用下列代码更新之:

<?php
// Define path to data folder
define('DATA_PATH', realpath(dirname(__FILE__).'/data'));

//Define our id-key pairs
$applications = array(
	'APP001' => '28e336ac6c9423d946ba02d19c6a2632', //randomly generated app key 
);
//include our models
include_once 'models/TodoItem.php';

//wrap the whole thing in a try-catch block to catch any wayward exceptions!
try {
	//*UPDATED*
	//get the encrypted request
	$enc_request = $_REQUEST['enc_request'];
	
	//get the provided app id
	$app_id = $_REQUEST['app_id'];
	
	//check first if the app id exists in the list of applications
	if( !isset($applications[$app_id]) ) {
		throw new Exception('Application does not exist!');
	}
	
	//decrypt the request
	$params = json_decode(trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $applications[$app_id], base64_decode($enc_request), MCRYPT_MODE_ECB)));
	
	//check if the request is valid by checking if it's an array and looking for the controller and action
	if( $params == false || isset($params->controller) == false || isset($params->action) == false ) {
		throw new Exception('Request is not valid');
	}
	
	//cast it into an array
	$params = (array) $params;
	...
	...
	...

发表评论

电子邮件地址不会被公开。 必填项已用*标注