[Laravel] 12 - WEB API : cache implement

前言


Ref: https://www.imooc.com/video/2873

服务端如何为客户端(app)的首页提供数据接口,

本篇用此作为例子演示接口的实现。

[Laravel] 12 - WEB API : cache implement

单例模式


一、三大原则

  • 单例实现
class Db {
  static private $_instance;
  static private $_connectSource;   private $_dbConfig = array(
    'host' => 127.0.0.1',
    'user' => 'root',
    'password' => '',
    'database' => 'video',   );
  private function __construct() { 
  }   static public function getInstance() {
    if (!self::$_instance instanceof self)) {
      self::$_instance = new self();     # 实例化的方法有点小意思
    }      return self::$_instance;
  }
}

该类返回一个可用的数据库连接。

二、单例模式链接数据库

  • 连接类设计

Ref: http://www.runoob.com/php/func-mysqli-select-db.html

Ref: http://www.w3school.com.cn/php/func_mysql_query.asp

public function connect() {

  if (!self::$_connectSource) { # step 1, 连接
    self::$_connectSource = mysql_connect($this->_dbConfig['host'],
                     $this->_dbConfig['user'],
                       $this->_dbConfig['password']);
    if (!self::$_connectSource) {
      die('mysql connect error' . mysql_error());
    }     mysql_select_db($this->_dbConfig['database'], self::$_connectSource)
  
    $sql = "SELECT * FROM Person";
    mysql_query($sql, self::$_connectSource);
  }
  return self::$_connectSource;
}
  • 数据库链接
$connect = Db::getInstance()->connect();
var_dump($connect); Output:
resource(3, mysql link)
  • 查询数据库
$connect = Db::getInstance()->connect();

$sql = "select * from video";
$result = mysql_query($sql, $connect); echo mysql_num_rows($result)
var_dump($result); [Output]
2
resource(4, mysql result)

首页接口


一、大纲

[Laravel] 12 - WEB API : cache implement

[Laravel] 12 - WEB API : cache implement

[Laravel] 12 - WEB API : cache implement

二、方案一

  • 流程

[Laravel] 12 - WEB API : cache implement

  • 代码
<?php

require_once('./response.php');
require_once('./db.php');

# 解析URL
$page = isset($_GET['page']) ? $_GET['page'] : 1;
$pageSize = isset($_GET['pagesize']) ? $_GET['pagesize'] : 1; if (!is_numeric($page) || !is_numberic($pageSize)) {
  return Response::show(401, "数据不合法”);
} # sql语句的构造
$offset = ($page - 1) * $pageSize;
$sql = "select * from video where status = 1 order by orderby desc limit " . $offset. "," . $pageSize; # 连接数据库
$connect = Db::getInstance()->connect();
$result = mysql_query($sql, $connect);
var_dump($result);
  • 测试

URL: app.com/list.php?format=xml&page=xxxxx

page参数可以取到,但是不合法的。

  • 文档

补充:实现接口,当然也要创建相应的接口文档,如下。

[Laravel] 12 - WEB API : cache implement

  • 完整的代码

[list.php]

<?php
// http://app.com/list.php?page-=1&pagesize=12
require_once('./response.php');
require_once('./file.php');
------------------------------------------------------------------
$file = new File();
$data = $file->cacheData('index_cron_cahce');
if($data) {
return Response::show(200, '首页数据获取成功', $data);
}else{
return Response::show(400, '首页数据获取失败', $data);
}
exit; ------------------------------------------------------------------
require_once('./db.php');
require_once('./file.php');
$page = isset($_GET['page']) ? $_GET['page'] : 1;
$pageSize = isset($_GET['pagesize']) ? $_GET['pagesize'] : 6;
if(!is_numeric($page) || !is_numeric($pageSize)) {
return Response::show(401, '数据不合法');
}
------------------------------------------------------------------
$offset = ($page - 1) * $pageSize;
$sql = "select * from video where status = 1 order by orderby desc limit ". $offset ." , ".$pageSize; ------------------------------------------------------------------
$cache = new File();
$videos = array();
if(!$videos = $cache->cacheData('index_mk_cache' . $page .'-' . $pageSize)) {
echo 1;exit; --------------------------------------------------------------
try {
/**
* 连接方法,如果连接失败了,通过异常处理方式解决
*/
$connect = Db::getInstance()->connect();
} catch(Exception $e) {
// $e->getMessage();  仅用于调试模式
return Response::show(403, '数据库链接失败');
} --------------------------------------------------------------
$result = mysql_query($sql, $connect);
while($video = mysql_fetch_assoc($result)) {
$videos[] = $video;
}    /**
* 获得了sql的查询结果,然后在结果中一行行读取构成一个我们熟悉的数组的形式:videos[]
* 这个结果可以之后以缓存的形式存在下去。
*/
if($videos) {
$cache->cacheData('index_mk_cache' . $page .'-' . $pageSize, $videos, 1200);
}
}

------------------------------------------------------------------
if($videos) {
return Response::show(200, '首页数据获取成功', $videos);
} else {
return Response::show(400, '首页数据获取失败', $videos);
}

mysql_fetch_assoc

从结果集中取得一行作为关联数组。返回根据从结果集取得的行生成的关联数组,如果没有更多行,则返回 false。

三、方案二

  • 流程图

进一步地,我们开始考虑如何利用缓存。

[Laravel] 12 - WEB API : cache implement

  • 利用缓存访问首页

[1] 对静态缓存的改进

在我获取的时候:缓存文件时间 + 缓存失效时间 与 当前时间 做个对比。

[Laravel] 12 - WEB API : cache implement

通过以下字符串截取手段获取 cacheTime & value。

$contents  = file_get_contents($filename);

$cacheTime = (int)substr($contents, 0 ,11);  # 把缓存失效时间截取出来
$value = substr($contents, 11);       # 截取value /**
* cacheTime = 0 表示永久有效
*/
if($cacheTime !=0 && ($cacheTime + filemtime($filename) < time())) {
  unlink($filename);             # 删除缓存文件
  return FALSE;
}

[2] 调用静态缓存

<?php
// http://app.com/list.php?page-=1&pagesize=12
require_once('./response.php');
require_once('./db.php');
require_once('./file.php');
------------------------------------------------------------------
$file = new File();
$data = $file->cacheData('index_cron_cahce');
if($data) {
return Response::show(200, '首页数据获取成功', $data);
}else{
return Response::show(400, '首页数据获取失败', $data);
}
exit; ------------------------------------------------------------------
require_once('./db.php');
require_once('./file.php'); $page = isset($_GET['page']) ? $_GET['page'] : 1;
$pageSize = isset($_GET['pagesize']) ? $_GET['pagesize'] : 6; if(!is_numeric($page) || !is_numeric($pageSize)) {
return Response::show(401, '数据不合法');
} ------------------------------------------------------------------
$offset = ($page - 1) * $pageSize;
$sql = "select * from video where status = 1 order by orderby desc limit ". $offset ." , ".$pageSize; ------------------------------------------------------------------
$cache = new File();
$videos = array(); if( !$videos = $cache->cacheData('index_mk_cache' . $page .'-' . $pageSize) ) {
echo 1;exit;  # 说明缓存失效

# If 缓存失效,则如下读取数据库,当然之后也要设置新的缓存
--------------------------------------------------------------
try {
/**
* 连接方法,如果连接失败了,通过异常处理方式解决
*/
$connect = Db::getInstance()->connect(); } catch(Exception $e) {
// $e->getMessage();  仅用于调试模式
return Response::show(403, '数据库链接失败');
} --------------------------------------------------------------
$result = mysql_query($sql, $connect);
while($video = mysql_fetch_assoc($result)) {
$videos[] = $video;
}    /**
* 获得了sql的查询结果,然后在结果中一行行读取构成一个我们熟悉的数组的形式:videos[]
* 这个结果可以之后以缓存的形式存在下去。
*/ if($videos) {
$cache->cacheData('index_mk_cache' . $page .'-' . $pageSize, $videos, 1200);
}
}

# If 缓存已存在,则直接读取缓存数据 in $videos 就好了
------------------------------------------------------------------
if($videos) {
return Response::show(200, '首页数据获取成功', $videos);
} else {
return Response::show(400, '首页数据获取失败', $videos);
}

四、方案三

  • 流程图

1. 掌握如何编写定时脚本程序

2. 理解服务器如何提前准备数据

[Laravel] 12 - WEB API : cache implement

提前准备好,而不是第一次通过数据库的方式。

我们希望的是:第一次就铜鼓缓存获取数据,这个缓存的内容是定时导入的。

  • 定时任务

cron.php定时执行 list.php

[list.php]

<?php

// 让crontab定时执行的脚本程序     */5 * * * * /usr/bin/php /data/www/app/cron.php
// 目的:想获取video表中 6条数据 require_once('./db.php');
require_once('./file.php'); $sql = "select * from video where status = 1 order by orderby desc";
try {
$connect = Db::getInstance()->connect();
} catch(Exception $e) {
// $e->getMessage();
file_put_contents('./logs/'.date('y-m-d') . '.txt' , $e->getMessage());  # 记录日志
return;
}
$result = mysql_query($sql, $connect);
---------------------------------------------------------------------------------------
$videos = array();
while($video = mysql_fetch_assoc($result)) {
$videos[] = $video;
}
---------------------------------------------------------------------------------------
$file = new File();
if($videos) {
$file->cacheData('index_cron_cahce', $videos);  # 默认是永久有效的
} else {
file_put_contents('./logs/'.date('y-m-d') . '.txt' , "没有相关数据");
}
return;
上一篇:laravel 配置路由 api和web定义的路由的区别详解


下一篇:Android文件存储使用参考