php 开发APP接口

APP模拟器:Start BlueStacks;

第一、APP接口简介

1.1、客户端app通信


这种通信模式类似于BS架构系统相似,但是有区别:

(1):客户端请求地址是不可见的,是封装在APP中的;

(2):BS架构返回的是HTML格式数据,而APP返回的是XML和JSON数据格式。


1.2、app通信格式的区别:

XML定义:扩展标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML格式统一,跨平台和语言,非常适合数据传输和通信。(XML节点不能为数字)

  1. <span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>  
  2. <item>  
  3.     <title>singwa</title>  
  4.     <test id="1"/>  
  5.     <address>beijing</address>  
  6. </item></span>  

JSON定义:JSON一种轻量级的数据交换格式,具有良好的可读和便于 快速编写的特征。可以在不同的平台之间进行数据交换。json数据兼容性高、完全独立与语言文本格式。

(1):可读性方面       --->    XML比较好;

(2):生成数据方面   ---->   json比较好;

(3):传输速度方面   ---->   json比较好;


第二、封装通信接口数据方法:

1.1、PHP生成JSON数据(json_encode只支持UTF-8)

1.2、通信数据标准模式

  1. <span style="font-size:18px;">code         状态码(200,400等)  
  2. message      提示信息(邮箱格式不正确:数据返回成功等)  
  3. data         返回数据</span>  
1.3、封装通信数据方式

JSON封装通信方式:

  1. <span style="font-size:18px;"><?php  
  2. class Pesponse {  
  3.     /** 
  4.      * [通过json方式输出通信数据] 
  5.      * @param integer $code 状态码 
  6.      * @param string $message 提示信息 
  7.      * @param array $data     数据 
  8.      */  
  9.     public static function json($code$message=''$data=array()) {  
  10.         if (!is_numeric($code)) {  
  11.             return '';  
  12.         }  
  13.   
  14.         $result = array(  
  15.             'code'=>$code,  
  16.             'message'=>$message,  
  17.             'data'=>$data  
  18.         );  
  19.         echo json_encode($result);  
  20.         exit;  
  21.     }  
  22. }</span>  
XML封装通信:

  1. <span style="font-size:18px;"><?php  
  2. class Pesponse {  
  3.     /** 
  4.      * [通过json方式输出通信数据] 
  5.      * @param integer $code 状态码 
  6.      * @param string $message 提示信息 
  7.      * @param array $data     数据 
  8.      */  
  9.     public static function xmlEncode($code$message=''$data=array()) {  
  10.         if (!is_numeric($code)) {  
  11.             return '';  
  12.         }  
  13.         $result = array(  
  14.             'code'=>$code,  
  15.             'message'=>$message,  
  16.             'data'=>$data  
  17.         );  
  18.   
  19.         header("Content-Type:text/xml");  
  20.         $xml = "<?xml version='1.0' encoding='UTF-8'?>\n";  
  21.         $xml .= "<root>\n";  
  22.   
  23.         $xml .= self::xmlToEocode($result);  
  24.   
  25.         $xml .= "</root>";  
  26.         echo $xml;  
  27.     }  
  28.   
  29.     public static function xmlToEocode($data) {  
  30.         $xml = $attr = "";   
  31.         foreach($data as $key=>$val) {  
  32.             if (is_numeric($key)) {  
  33.                 $attr = " id='{$key}'";  
  34.                 $key = "item";  
  35.             }  
  36.             $xml .= "<{$key}{$attr}>";  
  37.             $xml .= is_array($val)?self::xmlToEocode($val):$val;  
  38.             $xml .= "</{$key}>";  
  39.         }  
  40.         return $xml;  
  41.     }  
  42. }  
  43.   
  44. $data = array(  
  45.     'id'=>"1",  
  46.     'name'=>'singwa',  
  47.     'type'=>array(1,2,3),  
  48. );  
  49.   
  50. Pesponse::xmlEncode(200,'success',$data);</span>  


综合通信方式封装:(response.php)

  1. <span style="font-size:18px;"><?php  
  2. class Pesponse {  
  3.     const JSON = "json";  
  4.     /** 
  5.      * [通过json方式输出通信数据] 
  6.      * @param integer $code   状态码 
  7.      * @param string $message 提示信息 
  8.      * @param array $data     数据 
  9.      * @param string $type    数据类型 
  10.      */  
  11.     <span style="color: rgb(255, 0, 0);">public static function show($code$message=''$data=array(), $type=self::JSON) {  
  12.         if (!is_numeric($code)) {  
  13.             return "";  
  14.         }  
  15.   
  16.         $type = isset($_GET['type']) ? $_GET['type'] : self::JSON;  
  17.   
  18.         $result = array(  
  19.             'code'=>$code,  
  20.             'message'=>$message,  
  21.             'data'=>$data,  
  22.         );  
  23.   
  24.         if ($type == "json") {  
  25.             self::json($code$message$data); exit;  
  26.         } elseif($type == "array") {  
  27.             var_dump($result);  
  28.         } elseif($type == "xml") {  
  29.             self::xmlEncode($code$message$data);  
  30.             exit;  
  31.         } else {  
  32.             //TODO  
  33.         }  
  34.     }</span>  
  35.   
  36.     /** 
  37.      * [通过json方式输出通信数据] 
  38.      * @param integer $code 状态码 
  39.      * @param string $message 提示信息 
  40.      * @param array $data     数据 
  41.      */  
  42.       
  43.     public static function json($code$message=''$data=array()) {  
  44.         if (!is_numeric($code)) {  
  45.             return '';  
  46.         }  
  47.   
  48.         $result = array(  
  49.             'code'=>$code,  
  50.             'message'=>$message,  
  51.             'data'=>$data  
  52.         );  
  53.         echo json_encode($result);  
  54.         exit;  
  55.     }  
  56.   
  57.     public static function xmlEncode($code$message=''$data=array()) {  
  58.         if (!is_numeric($code)) {  
  59.             return '';  
  60.         }  
  61.         $result = array(  
  62.             'code'=>$code,  
  63.             'message'=>$message,  
  64.             'data'=>$data  
  65.         );  
  66.   
  67.         header("Content-Type:text/xml");  
  68.         $xml = "<?xml version='1.0' encoding='UTF-8'?>\n";  
  69.         $xml .= "<root>\n";  
  70.   
  71.         $xml .= self::xmlToEocode($result);  
  72.   
  73.         $xml .= "</root>";  
  74.         echo $xml;  
  75.     }  
  76.   
  77.     public static function xmlToEocode($data) {  
  78.         $xml = $attr = "";   
  79.         foreach($data as $key=>$val) {  
  80.             if (is_numeric($key)) {  
  81.                 $attr = " id='{$key}'";  
  82.                 $key = "item";  
  83.             }  
  84.             $xml .= "<{$key}{$attr}>";  
  85.             $xml .= is_array($val)?self::xmlToEocode($val):$val;  
  86.             $xml .= "</{$key}>";  
  87.         }  
  88.         return $xml;  
  89.     }  
  90. }  
  91.   
  92. $data = array(  
  93.     'id'=>"1",  
  94.     'name'=>'singwa',  
  95.     'type'=>array(1,2,3),  
  96.     'test'=>array(4,5,6=>array(123,'ssss'))  
  97. );  
  98.   
  99. Pesponse::show(200,'success',$data);</span>  



2.1、PHP生成XML数据:

2.1.1、组装字符串

  1. <span style="font-size:18px;"><?php  
  2. class Pesponse {  
  3.     public static function xml() {  
  4.         header("Content-Type:text/xml");  
  5.         $xml = "<?xml version='1.0' encoding='UTF-8'?>\n";  
  6.         $xml .= "<root>\n";  
  7.         $xml .= "<code>200</code>\n";  
  8.         $xml .= "<message>数据返回成功</message>\n";  
  9.         $xml .= "<data>\n";  
  10.         $xml .= "<id>1</id>\n";  
  11.         $xml .= "<name>singwa</name>\n";  
  12.         $xml .= "</data>\n";  
  13.         $xml .= "</root>";  
  14.   
  15.         echo $xml;  
  16.     }  
  17. }  
  18.   
  19. Pesponse::xml();</span>  

2.1.2、使用系统类(PHP开发手册中查找)

              DOMDocument                  XMLWriter                    SimpleXML

第三、核心技术

3.1、静态缓存(文件,file.php)

  1. <span style="font-size:18px;"><?php  
  2. class File {  
  3. <span style="white-space:pre">  </span>private $_dir;  
  4.   
  5.   
  6. <span style="white-space:pre">  </span>const EXT = '.txt';  
  7. <span style="white-space:pre">  </span>public function __construct(){  
  8. <span style="white-space:pre">      </span>$this->_dir = dirname(__FILE__).'/file/';  
  9. <span style="white-space:pre">  </span>}  
  10. <span style="white-space:pre">  </span>/**  
  11. <span style="white-space:pre">  </span> * @param  [string] $key   [文件名] 
  12. <span style="white-space:pre">  </span> * @param  string $value   [数据] 
  13. <span style="white-space:pre">  </span> * @param  string $path    [文件路径] 
  14. <span style="white-space:pre">  </span> * @return [return]        [字节数 或者false] 
  15. <span style="white-space:pre">  </span> */  
  16. <span style="white-space:pre">  </span>public function cacheData($key$value = ''$cacheTime = 0) {  
  17. <span style="white-space:pre">      </span>$filename = $this->_dir.$key.self::EXT;  
  18.   
  19.   
  20. <span style="white-space:pre">      </span>if ($value !== "") {//将value值写入缓存  
  21. <span style="white-space:pre">          </span>if (is_null($value)) {//当 $value为null时,删除缓存  
  22. <span style="white-space:pre">              </span>return @unlink($filename);  
  23. <span style="white-space:pre">          </span>}  
  24. <span style="white-space:pre">          </span>$dir = dirname($filename);  
  25. <span style="white-space:pre">          </span>if (!is_dir($dir)) {  
  26. <span style="white-space:pre">              </span>mkdir($dir,0777);  
  27. <span style="white-space:pre">          </span>}  
  28.   
  29.   
  30. <span style="white-space:pre">          </span>//"%011d"表示不是11位,补0   
  31. <span style="white-space:pre">          </span>$cacheTime = sprintf('%011d'$cacheTime);  
  32.   
  33.   
  34. <span style="white-space:pre">          </span>//如果成功返回数据的字节数,没有成功返回false  
  35. <span style="white-space:pre">          </span>return file_put_contents($filename$cacheTime.json_encode($value));  
  36. <span style="white-space:pre">      </span>}  
  37.   
  38.   
  39. <span style="white-space:pre">      </span>//读取缓存数据(在调用cacheData方法$value不写时)  
  40. <span style="white-space:pre">      </span>if (!is_file($filename)) {  
  41. <span style="white-space:pre">          </span>return FALSE;  
  42. <span style="white-space:pre">      </span>}  
  43. <span style="white-space:pre">      </span>//获取缓存内容  
  44. <span style="white-space:pre">      </span>$contents = file_get_contents($filename);  
  45. <span style="white-space:pre">      </span>//获取缓存时间  
  46. <span style="white-space:pre">      </span>$cacheTime = (int)substr($contents,0,11);  
  47. <span style="white-space:pre">      </span>//获取缓存内容  
  48. <span style="white-space:pre">      </span>$value = substr($contents,11);  
  49. <span style="white-space:pre">      </span>//判断缓存失效时间  
  50. <span style="white-space:pre">      </span>if($cacheTime != 0 && $cacheTime+filemtime($filename)<time()) {  
  51. <span style="white-space:pre">          </span>unlink($filename);  
  52. <span style="white-space:pre">          </span>return FALSE;  
  53. <span style="white-space:pre">      </span>}  
  54. <span style="white-space:pre">      </span>return json_decode($value,true);  
  55. <span style="white-space:pre">      </span>  
  56. <span style="white-space:pre">  </span>}  
  57. }</span>  

第三、定时任务

1.定时任务命令

  1. 1.定时任务服务提供crontab命令来设定服务  
  2. 2.crontab  -e       //编辑某个用户的cron服务  
  3. 3.crontab  -l       //列出某个用户cron服务的详细内容  
  4. 4.crontab  -r       //删除某个用户的cron服务  
2、定时任务crontab格式



3、定时任务的crontab例子


第四、APP接口实例

1、单例模式链接数据库(db.php)

1.1、单例模式三大原则
    (1):构造函数需要标记为非public(防止外部使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化;
    (2):拥有一个保存类的实例的静态成员变量$_instance;
    (3):拥有一个访问这个实例的公共的静态方法。

  1. <?php  
  2. class Db {  
  3.     static private $_instance;  
  4.     static private $_connectSource;  
  5.     private $dbConfig = array(  
  6.         'host' => '127.0.0.1',  
  7.         'user' => 'root',  
  8.         'password'=> 'root',  
  9.         'database'=> 'video',  
  10.     );  
  11.     private function __construct() {  
  12.     }  
  13.   
  14.     //公共的静态方法  
  15.     static public function getInstance() {  
  16.         if (!(self::$_instance instanceof self)) {  
  17.             self::$_instance = new self();  
  18.         }  
  19.         return self::$_instance;  
  20.     }  
  21.   
  22.     //连接数据库  
  23.     public function connect() {  
  24.         if (!self::$_connectSource) {  
  25.             self::$_connectSource = @mysql_connect($this->_dbConfig['host'], $this->_dbConfig['user'], $this->_dbConfig['password']);  
  26.             if (self::$_connectSource) {  
  27.                 throw new Exception('mysql connect error'.mysql_error());  
  28.             }  
  29.             mysql_select_db($this->_dbConfig['database'], self::$_connectSource);  
  30.             mysql_quert('set names UTF-8', self::$_connectSource);  
  31.         }  
  32.         return self::$_connectSource;  
  33.     }  
  34. }  
  35. //连接数据库  
  36. $connect = Db::getInstance()->connect();  

2、首页APP接口开发

方案一、 读取数据库方式开发 首页接口(应用场景:数据时效性比较高的系统)

  1. <?php  
  2. require_once('./response.php');  
  3. require_once('./db.php');  
  4.   
  5. //判断链接合法性  
  6. $page = isset($_GET['page']) ? $_GET['page'] : 1;  
  7. $pageSize = isset($_GET['pagesize']) ? $_GET['pagesize'] : 1;  
  8. if (!is_numeric($page) || !is_numeric($pageSize)) {  
  9.     return Response::show(401,'数据不合法');  
  10. }  
  11.   
  12. $offset = ($page-1) * $pageSize;  
  13. $sql = "select * from video where status = 1 order by orderby desc limit ".$offset.",".$pageSize;  
  14.   
  15. //连接数据库  
  16. try {  
  17.     $connect = Db::getInstance()->connect();  
  18. } catch(Exception $e) {  
  19.     return Response::show(403, '数据库链接失败');  
  20. }  
  21.   
  22. $result = mysql_query($sql$connect);  
  23. $videos = array();  
  24.   
  25. while ($video = mysql_fetch_assoc($result)) {  
  26.     $videos[] = $video;  
  27. }  
  28.   
  29. if ($videos) {  
  30.     return Response::show(200, '首页获取数据成功'$videos);  
  31. else {  
  32.     return Response::show(400, '首页获取数据失败'$videos);  
  33. }  

方案二、读取缓存方式开发首页接口(用途:减少数据库压力)(文件缓存)

  1. <?php  
  2. require_once('./response.php');  
  3. require_once('./db.php');  
  4. require_once('./file.php');  
  5. //判断链接合法性  
  6. $page = isset($_GET['page']) ? $_GET['page'] : 1;  
  7. $pageSize = isset($_GET['pagesize']) ? $_GET['pagesize'] : 1;  
  8. if (!is_numeric($page) || !is_numeric($pageSize)) {  
  9.     return Response::show(401,'数据不合法');  
  10. }  
  11.   
  12. $offset = ($page-1) * $pageSize;  
  13. $sql = "select * from video where status = 1 order by orderby desc limit ".$offset.",".$pageSize;  
  14.   
  15. $cache = new File();  
  16. $videos = array();  
  17. if (!$videos = $cache->cacheData('index_cache'.$page.'-'.$pageSize)) {  
  18.     //连接数据库  
  19.     try {  
  20.         $connect = Db::getInstance()->connect();  
  21.     } catch(Exception $e) {  
  22.         return Response::show(403, '数据库链接失败');  
  23.     }  
  24.   
  25.     $result = mysql_query($sql$connect);  
  26.   
  27.     while ($video = mysql_fetch_assoc($result)) {  
  28.         $videos[] = $video;  
  29.     }  
  30.   
  31.     if ($videos) {  
  32.         $cache->cacheData('index_cache'.$page.'-'.$pageSize,$videos,1200);  
  33.     }  
  34. }  
  35.   
  36. if ($videos) {  
  37.     return Response::show(200, '首页获取数据成功'$videos);  
  38. else {  
  39.     return Response::show(400, '首页获取数据失败'$videos);  
  40. }  

方案三、定时读取缓存方式开发首页接口

  1. <?php  
  2. //让crontab定时执行的脚本程序------ */5 * * * * /usr/bin/php /data/www/app/corn.php  
  3.   
  4. require_once('./db.php');  
  5. require_once('./file.php');  
  6.   
  7. $sql = "select * from video where status = 1 order by orderby desc";  
  8.   
  9. try {  
  10.     $connect = Db::getInstance()->connect();  
  11. } catch(Exception $e) {  
  12.     file_put_contents('./logs/'.date('y-m-d').'.txt',$e->getMessage());  
  13.     return;  
  14. }  
  15. $result = mysql_query($sql$connect);  
  16.   
  17. $videos = array();  
  18. while($video = mysql_fetch_assoc($result)) {  
  19.     $videos[] = $video;  
  20. }  
  21.   
  22. $file = new File();  
  23.   
  24. if($videos) {  
  25.     $file->cacheData('index_cron_cache',$videos);  
  26. else {  
  27.     file_put_contents('/logs/'.date('y-m-d').'.txt',"没有相关数据");  
  28. }  
  29. return;  


第四、APP版本升级以及APP演示

1、APP版本升级分析以及数据表设计

检测升级:首先开启APP请求初始化接口init.php,检测是否更新,如果更新下载最新的源码包,替换原来的APK,否的话直接返回首页;

初始化接口init.php要传递的参数:app_id:客户端id(1.安卓,2.iPhone)、version_id:(版本号) 




 2、升级接口开发和演示


处理接口业务(common.php)

  1. <?php  
  2. /** 
  3.  * 处理接口公共业务 
  4.  */  
  5. require_once('./response.php');  
  6. require_once('./db.php');  
  7.   
  8. class Common {  
  9.     public $params;  
  10.     public $app;  
  11.     public function check() {  
  12.         $this->params['app_id'] = $appId = isset($_POST['app_id']) ? $_POST['app_id'] : '';  
  13.         $this->params['version_id'] = $versionId = isset($_POST['version_id']) ? $_POST['version_id'] : '';  
  14.         $this->params['version_mini'] = $versionMini = isset($_POST['version_mini']) ? $_POST['version_mini'] : '';  
  15.         $this->params['did'] = $did = isset($_POST['did']) ? $_POST['did'] : '';  
  16.         $this->params['encrypt_did'] = $encryptDid = isset($_POST['encrypt_did']) ? $_POST['encrypt_did'] : '';  
  17.   
  18.         if (!is_numeric($appId) || !is_numeric($versionId)) {  
  19.             return Response::show(401, '参数不合法');  
  20.         }  
  21.   
  22.         //判断APP是否需要加密  
  23.         $this->app = $this->getApp($appId);  
  24.         if (!$this->app) {  
  25.             return Response::show(402, 'app_id不存在');  
  26.         }  
  27.         if ($this->app['is_encryption'] && $encryptDid != md5($did . $this->app['key'])) {  
  28.             return Response::show(403, '没有权限');  
  29.         }  
  30.     }  
  31.   
  32.     public function getApp($id) {  
  33.         $sql = "SELECT * FROM 'app' WHERE id = ".$id." AND status = 1 LIMIT 1";  
  34.         $connect = Db::getInstance();->connect();  
  35.         $result = mysql_query($sql$connect);  
  36.         return mysql_fetch_assoc($result);  
  37.     }  
  38. }  

 判断是否升级(init.php)

  1. <?php  
  2. require_once('./common.php');  
  3. require_once('./');  
  4. class Init extends Common{  
  5.     public function index() {  
  6.         $this->check();  
  7.         //获取版本升级信息  
  8.         $versionUpgrade = $this->getversionUpgrade($this->app['id']);  
  9.         if ($versionUpgrade) {  
  10.             if ($versionUpgrade['type'] && $this->params['version_id'] < $versionUpgrade['version_id']) {  
  11.                 //需要升级  
  12.                 $versionUpgrade['is_upload'] = $versionUpgrade['type'];  
  13.             } else {  
  14.                 //不需要升级  
  15.                 $versionUpgrade['is_upload'] = 0;  
  16.             }  
  17.             return Response::show(200, '版本升级信息获取成功'$versionUpgrade);  
  18.         } else{  
  19.             return Response::show(400, '版本升级信息获取失败');  
  20.         }  
  21.     }  
  22. }  

第五、APP错误日志

1、面临的错误问题

1.1、APP强退;

1.2、数据加载失败;

1.3、APP潜在问题;

错误日志表:


错误日志类:

  1. <?php  
  2. require_once('./common.php');  
  3. require_once('./db.php');  
  4. class ErrorLog extends Common {  
  5.     public function index() {  
  6.         $this->check();  
  7.   
  8.         $errorLog = isset($_POST['error_log']) ? $_POST['error_log'] : '';  
  9.         if (!$errorLog) {  
  10.             return Response::show(401, '日志为空');  
  11.         }  
  12.   
  13.         $sql = "INSERT INTO   
  14.                     error_log(  
  15.                         'app_id',  
  16.                         'did',  
  17.                         'version_id',  
  18.                         'version_mini',  
  19.                         'error_log',  
  20.                         'crete_time')  
  21.                     VALUES(  
  22.                         ".$this->params['app_id'].",  
  23.                         '".$this->params['did']."',  
  24.                         ".$this->params['version_id'].",  
  25.                         ".$this->params['version_mini'].",  
  26.                         '".$error_log."',  
  27.                         ".time()."  
  28.                     )";  
  29.         $connect = Db::getInstance()->connect();  
  30.         if (mysql_quert($sql$connect)) {  
  31.             return Response::show(200, '错误信息插入成功');  
  32.         } else {  
  33.             return Response::show(200, '错误信息插入失败');  
  34.         }  
  35.     }  
  36. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值