PHP第二十六篇——APP接口是怎么来的?

学了差不多一个月的PHP,总想找个机会试试手,因为工作的原因每天能抽出来的时间真心少,这两天就开始在进行真正的PHP接口开发学习了,到今天为止,我终于知道我做iOS开发的时候发送请求返回的数据是这么来的……

APP接口

PHP开发APP接口

APP接口开发

  1. APP接口简介
  2. 封装通讯接口方法
  3. 核心技术
  4. APP接口实例

接口请求流程

客户端-发送GET/POST请求-服务端-数据库/缓存-调用APP接口-客户端

APP接口简介

  1. 接口地址(url) ==== 函数名
  2. GET或POST数据 ==== 函数的参数
  3. 这个接口输出的数据 ===== 函数的返回值

API概述

1、API 比开发 WEB 更简洁,但可能逻辑更复杂,API 只返回结果,也就是只完成数据输出,不呈现页面,
2、WEB 开发,更多的是 GET 和 POST 请求,API 还有 PUT、DELETE 请求
3、和 WEB 开发一样,首先需要一些相关的参数,这些参数,都会由客户端传过来,也许是 GET 也许是 POST,这个需要开发团队相互之间约定好,或者制定统一规范
4、有了参数,根据应用需求,完成数据处理,例如:获取用户信息、发朋友圈、发消息、一局游戏结束数据提交等等
5、数据逻辑处理完之后,返回客户端所需要用到的相关数据,例如:用户信息数组、朋友圈列表、消息状态、游戏结果数据等等,那数据是怎么返给客户端呢?常见有XML、JSON,设置相应的header并把要返回的数据直接打印出来即可
6、客户端获取到你返回的数据后,在客户端本地和用户进行交互

APP接口介绍

首先要区别去面向对象中的接口

面向对象中的接口是一个抽象类,如PHP或者java中使用interface,iOS中使用的@interface,这里起到的是一个标准或者规范,适合多人开发使用。

APP中的接口:是指数据接口

APP发送HTTP请求,服务器根据请求的参数返回对应的接口数据,客户端解析数据并显示,客户端并不需要关心接口数据是这么实现的,这么返回的,只要发送请求根据返回的数据解析使用就可以!

接口:包括接口地址,接口文件,接口数据

如何进行通讯

  1. ->需要有一个客户端APP

  2. ->触发客户端APP的时候

  3. ->发送HTTP对应的地址GET/POST请求

  4. ->发送给服务端

  5. ->服务端收到接口请求之后会做相应的处理

  6. ->比如从数据库/缓存读取对应的数据

  7. ->返回给客户端

  8. ->客户端收到服务器返回的数据

  9. ->开始解析成自己想要的格式(XML、JSON)

  10. ->显示到界面上

通讯格式区别

JSON的定义

一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持),从而可以在不同平台间进行数据交换。JSON采用兼容性很高的文本格式,同时也具备类似于C语言体系的行为。

XML的定义

扩展标记语言 (Extensible Markup Language,XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML是标准通用标记语言 (SGML) 的子集,非常适合 Web 传输。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。

XML优缺点

缺点

1. 格式统一, 符合标准
2. 容易与其他系统进行远程交互, 数据共享比较方便

缺点:

1. XML文件格式文件庞大, 格式复杂, 传输占用带宽
2. 服务器端和客户端都需要花费大量代码来解析XML, 不论服务器端和客户端代码变的异常复杂和不容易维护
3. 客户端不同浏览器之间解析XML的方式不一致, 需要重复编写很多代码
4. 服务器端和客户端解析XML花费资源和时间

JSON优缺点

那么除了XML格式, 还有没有其他格式, 有一种叫做JSON(JavaScript Object Notation) 的轻量级数据交换格式能够替代XML的工作.

优点:

1. 数据格式比较简单, 易于读写, 格式都是压缩的, 占用带宽小
2. 易于解析这种语言, 客户端JavaScript可以简单的通过eval_r()进行JSON数据的读取
3. 支持多种语言, 包括ActionScript, C, C#, ColdFusion, Java,JavaScript, Perl, PHP, Python, Ruby等语言服务器端语言, 便于服务器端的解析
4. 在PHP世界, 已经有PHP-JSON和JSON-PHP出现了, 便于PHP序列化后的程序直接调用. PHP服务器端的对象、数组等能够直接生JSON格式, 便于客户端的访问提取.
5. 因为JSON格式能够直接为服务器端代码使用, 大大简化了服务器端和客户端的代码开发量, 但是完成的任务不变, 且易于维护

缺点:

1. 没有XML格式这么推广的深入人心和使用广泛, 没有XML那么通用性
2. JSON格式目前在Web Service中推广还属于初级阶段

JSON 和 XML 优缺点的比较

1. 在可读性方面,JSON和XML的数据可读性基本相同。JSON和XML的可读性可谓不相上下,一边是建议的语法,一边是规范的标签形式,很难分出胜负。
2. 在可扩展性方面,XML天生有很好的扩展性,JSON当然也有,没有什么是XML能扩展,JSON不能的。
3. 在编码难度方面,XML有丰富的编码工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的编码明显比XML容易许多,即使不借助工具也能写出JSON的代码,可是要写好XML就不太容易了。
4. 在解码难度方面,XML的解析得考虑子节点父节点,让人头昏眼花,而JSON的解析难度几乎为0。这一点XML输的真是没话说。
5. 在流行度方面,XML已经被业界广泛的使用,而JSON才刚刚开始,但是在Ajax这个特定的领域,未来的发展一定是XML让位于JSON。到时Ajax应该变成Ajaj(AsynchronousJavascript and JSON)了。
6. JSON和XML同样拥有丰富的解析手段。
7. JSON相对于XML来讲,数据的体积小。
8. JSON与JavaScript的交互更加方便。
9. JSON对数据的描述性比XML较差。
10. JSON的速度要远远快于XML。
  • protocol buffer

现在还有一种据说是比较流行,但是目前还没有PHP的API,叫做protocol buffer

protocol buffer是google的一个开源项目,它是用于结构化数据串行化的灵活、高效、自动的方法,例如XML,不过它比xml更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构。

对于protocol buffer网上确实有不少好评,但是目前只有C++,java,python的API,希望以后有机会能试一试效果。

APP接口做的那些事

获取数据:从数据库中或者缓存中获取数据,然后通过接口数据返回给客户端
提交数据:通过接口提交数据给服务器。然后服务器入库处理,或者其他处理

获取数据:GET请求

界面显示数据,首页,广场,用户信息......

提交数据:POST请求

提交反馈,注册登录,修改用户信息......

封装通讯接口方法

JSON方式封装通讯接口

一. 生成JSON数据——数组方式

首先必须知道PHP生成接口数据的方法是json_encode($value),这个方法只能接口UTF-8编码数据,其他格式数据会返回null

首先我们定义一个简单的数组,然后使用json_encode方法将数组转成json数据

$arrayName = array(
'id' => 1,
'name' => 'iCocos'
);

echo $arrayName;
echo json_encode($arrayName);

浏览器输入对应的链接地址,答应结果

Array
Array{"id":1,"name":"iCocos"}

当然如果你不是UTF8编码数据,可以使用字符编码之间转换函数iconv(),将对应的编码转成自己想要的编码

iconv('原始编码','目标编码','数据变量')

二. 通讯数据的标准格式

一般来说规范一点的后台开发人员都会有一套自己的标准

  • code 状态吗(2XX-成功, 3XX重定向, 4XX客户端错误, 5XX服务器错误)
  • message 提示信息
  • data 返回数据
    • id : 1
    • name : iCocos

如果你是做移动端的,到公司发现你们后台返回连这种标准都没有,哪怕是类似的,那么不用多说,建议还是闪人吧!

三. 下面我们简单的实战一下

首先定义一个工具类,用来把传递进来的数据和相应的信息转换成json,然后输出

定义一个PHPResponse.php文件,并且定义一个PHPResponse类,在类里面定义一个静态方法,并且简单的实现一些逻辑处理就进行转换输出

<?php
/**
* 相应类
*/
class PHPResponse
{

    //返回JSON数据方法
    public static function jsonData($code, $message = '', $data = array())
    {
        //如果code不是数字
        if (!is_numeric($code)) {
            # code...
            return '';
        }

        $res = array(
            'code' => $code,
            'message' => $message,
            'data' => $data
        );

        echo var_dump($res);

        //echo json_encode($res);
        exit(); //exit;
    }
}

因为这里只是简单的测试,所以在index.php中引入对应的文件,然后传递数据和对应的参数进上面的方法

require_once('./PHPResponse.php');
$arrRes = array(
    'id' => 1,
    'name' = 'iCocos'
);

PHPResponse::jsonData(200, '成功', $arrRes);

浏览器输入对应的路径,就能看到真实的数据返回

array(3) { 
    ["code"]=> int(200) 
    ["message"]=> string(6) "成功" 
    ["data"]=> array(2) { 
        ["id"]=> int(1) 
        ["name"]=> string(6) "iCocos" 
    } 
}

生成XML数据

  1. 组装字符串

  2. 使用系统类

    • DomDocument
    • XMLWrite
    • SimpleXML

这里使用字符串的方式,其实在学习iOS的时候就有了解过这一点:

public static function xmlToEncode($data) {
    $xml = "<?xml version='1.0' encoding='UTF-8'?>\n";
    $xml = "<root>\n";
    $xml = "<code>200</code>\n";
    $xml = "<message>返回成功</message>\n";
    $xml = "<data>\n";
    $xml = "<id>1</id>\n";
    $xml = "<name>iCocos<name>\n";
    $xml = "</data>\n";
    $xml = "</root>\n";

    echo $xml;
}

注意:xml节点不能使用数字

浏览器输入后测试显示就是平时我们看到的xml数据格式

<?xml version='1.0' encoding='UTF-8'?>
<root>
    <code>200</code>
    <message>返回成功</message>
    <data>
        <id>1</id>
        <name>iCocos<name>
    </data>
</root>

当然可能你直接看到的是这样的,这是因为浏览器自动帮我们解析,属于来说就是Content-Type:text/html,而我们需要显示的是Content-Type:text/xml,只要右键查看源码就可以查看

200 返回成功 1 iCocos

如果想要显示的时候就自动解析成xml,只要调用对应的php方法就可以

heaer("Content-Type:text/xml");

XML方式封装通讯数据方法:响应的格式和json是一样的

XML方式其实现在来讲的话使用并不高,我经历了几家公司都使用的json,但是作为php开发也是必须要会。

首先定义一个工具类,用来把传递进来的数据和相应的信息转换成xml,然后输出

定义一个PHPResponse.php文件,并且定义一个PHPResponse类,在类里面定义一个静态方法,并且简单的实现一些逻辑处理就进行转换输出

/**
* 按xml方式输出通信数据
* @param integer $code 状态码
* @param string $message 提示信息
* @param array $data 数据
* return string
*/
public static function xmlEncode($code, $message, $data = array()) {
    if(!is_numeric($code)) {
        return '';
    }

    $result = array(
        'code' => $code,
        'message' => $message,
        'data' => $data,
    );

    header("Content-Type:text/xml");
    $xml = "<?xml version='1.0' encoding='UTF-8'?>\n";
    $xml .= "<root>\n";

    $xml .= self::xmlToEncode($result);

    $xml .= "</root>";
    echo $xml;
}

解析数组,返回xml数据

public static function xmlToEncode($data) {

    $xml = $attr = "";
    foreach($data as $key => $value) {
        if(is_numeric($key)) {
        $attr = " id='{$key}'";
        $key = "item";
    }
    $xml .= "<{$key}{$attr}>";
    $xml .= is_array($value) ? self::xmlToEncode($value) : $value; //如果value是数组就循环便利执行这个方法
    $xml .= "</{$key}>\n";
    }
    return $xml;
}

调用

$arrayName = array(
    'id' => 1,
    'name' => 'iCocos'
);

PHPResponse::xmlEncode(200,’success’,$arrayName);

输入浏览器测试地址可以看到

<?xml version='1.0' encoding='UTF-8'?>
<root>
    <code>200</code>
    <message>返回成功</message>
    <data>
        <id>1</id>
        <name>iCocos<name>
    </data>
</root>

这里如果实际开发坑定没有这么简单,但是复杂的地方也就是数组比较多数组,或分层

到上面位置就可以实现平时开发中最最最简单的接口数据。

综合方式封装通讯数据方法

一:定义一个通用的接口文件,并且定义一个基类

<?php
/**
* 定义API抽象类
*/
abstract class Api {

    const JSON = 'Json';
    const XML = 'Xml';
    const ARR = 'Array';

    /**
    * 定义工厂方法
    * param string $type 返回数据类型
    */
    public static function factory($type = self::JSON) {
        $type = isset($_GET['format']) ? $_GET['format'] : $type;
        $resultClass = ucwords($type);
        require_once('./Response/' . $type . '.php');
        return new $resultClass();
    }

    abstract function response($code, $message, $data);
}

二:XML数据解析与响应方法,继承自API

<?php
/**
* @author by singwa
* @date
*/

class Xml extends Api {
public function response($code, $message = '', $data = array()) {
    if(!is_numeric($code)) {
        return '';
    }

    $result = array(
        'code' => $code,
        'message' => $message,
        'data' => $data
    );

    header('Content-Type:text/xml');
        $xml = "<?xml version='1.0' encoding='UTF-8'?>\n";
        $xml .= "<root>";
        $xml .= self::xmlToEncode($result);
        $xml .= "</root>";
        echo $xml;
    }

    public static  function xmlToEncode($result) {
        $xml = $attr = '';
        foreach($result as $key => $value) {
            if(is_numeric($key)) {
                $attr = " id='" . $key . "'";
                $key = "item";
            }
            $xml .= "<{$key}{$attr}>";
            $xml .= is_array($value) ? self::xmlToEncode($value) : $value;
            $xml .= "</{$key}>\n";
        }
        return $xml;
    }
}

三:JSON数据解析与响应方法,继承自API

<?php
/**
* 按xml方式输出通信数据
*/
class Json extends Api {
public function response($code, $message = '', $data = array()) {
        if(!(is_numeric($code))) {
            return '';
        }

        $result = array(
            'code' => $code,
            'message' => $message,
            'data' => $data
        );

        echo json_encode($result);
        exit;
    }
}

是不是感觉json比xml简单很多,这也是为什么很多公司都使用的是json的原因。

四:然后就是入口文件,通过入口文件调用方法,根据传入的类型解析成对应的格式,这也是前面讲到的面向对象的特性

<?php

class Response {
const JSON = "json";
/**
* 按综合方式输出通信数据
* @param integer $code 状态码
* @param string $message 提示信息
* @param array $data 数据
* @param string $type 数据类型
* return string
*/
public static function show($code, $message = '', $data = array(), $type = self::JSON) {
    if(!is_numeric($code)) {
        return '';
    }

    $type = isset($_GET['format']) ? $_GET['format'] : self::JSON;

    $result = array(
        'code' => $code,
        'message' => $message,
        'data' => $data,
    );

    if($type == 'json') {
        self::json($code, $message, $data);
        exit;
    } elseif($type == 'array') {
        var_dump($result);
    } elseif($type == 'xml') {
        self::xmlEncode($code, $message, $data);
        exit;
    } else {
        // TODO
    }
}

/**
* 按json方式输出通信数据
* @param integer $code 状态码
* @param string $message 提示信息
* @param array $data 数据
* return string
*/
public static function json($code, $message = '', $data = array()) {

    if(!is_numeric($code)) {
        return '';
    }

    $result = array(
        'code' => $code,
        'message' => $message,
        'data' => $data
    );

    echo json_encode($result);
    exit;
}

/**
* 按xml方式输出通信数据
* @param integer $code 状态码
* @param string $message 提示信息
* @param array $data 数据
* return string
*/
public static function xmlEncode($code, $message, $data = array()) {
    if(!is_numeric($code)) {
        return '';
    }

    $result = array(
        'code' => $code,
        'message' => $message,
        'data' => $data,
    );

    header("Content-Type:text/xml");
    $xml = "<?xml version='1.0' encoding='UTF-8'?>\n";
    $xml .= "<root>\n";

    $xml .= self::xmlToEncode($result);

    $xml .= "</root>";
    echo $xml;
}

public static function xmlToEncode($data) {

    $xml = $attr = "";
    foreach($data as $key => $value) {
        if(is_numeric($key)) {
                $attr = " id='{$key}'";
                $key = "item";
            }
            $xml .= "<{$key}{$attr}>";
            $xml .= is_array($value) ? self::xmlToEncode($value) : $value;
            $xml .= "</{$key}>\n";
        }
        return $xml;
    }

}

五:最后就可以在浏览器输入对应的接口地址,传入对应的参数,就能得到想要的格式的数据

说在最后,实际项目中,我们在开发 API 时应该注意的几个点(仅供参考)

1、单文件实现多接口的形式有很多种,例如:if..elseif.. 或 switch 或 很多框架里用到的统一入口通过调用类函数的形式实现
2、数据输出建议使用json,json具有很强的跨平台性,大多编程语言都支持json解析,json正在逐步取代xml,成为网络数据的通用格式
3、为了保证接口安全,一定要加入鉴权体系
4、对于线上的API,务必关闭所有错误显示,可以把错误写到日志里,PHP中,可以通过 error_reporting(0) 屏蔽所有错误这样做的目的,一方面是保护接口安全,防止输出不该打印的错误信息
    另一方面是保证输出的是正确的数据格式,如json,假如不是标准的json格式,客户端在解析时就会出错,由此影响客户端的正常运转
    PS:我们平时在使用手机APP时,手机会闪退,多半是这个原因,即接口调用异常
5、开发 API 和 WEB 有一定的区别,如果是 WEB 的话,如果程序写的有问题,比如有个notice 或 warning 级别的错误,在 WEB 里可能不会有什么问题,也许就只是导致 WEB 的某个部分错位或乱码。但如果是 API,就会严重调用的客户端了,如果是手机APP,那闪推啥的,是必然的,如果同样也是Web调用,也可能会出现  Server Error 了
6、一定要重点考虑稳定性和响应速度,因为我们在使用手机APP时,都不希望APP经常闪推、而且希望应用很流畅
7、不要随便使用一些 PHP 开源框架,原因概括起来有两点:
    1)如6所述,客户端一般对 API 响应速度有极高要求,目前PHP领域的开源框架非常多,根据笔者的了解,目前比较流行的框架,普遍做的比较重,而且基本都是为WEB而生,因此,框架多了很多 API 用不到的东西,框架在加载和执行冗余文件时,实际是在消耗你的性能
    2)如4和5所述,框架对于WEB开发,是件很幸福的事,但对于 API 而言,你实在不敢想象它会给你出什么岔子,因为很多框架并没有全面的考虑到 API 场景
坚持原创技术分享,您的支持将鼓励我继续创作!