PHP获取cookie、Token、模拟登录、抓取数据、解析生成json

0. 设置Cookie路径

set_time_limit(0);

//使用的cookie路径,
if (isset($_SERVER['HTTP_APPNAME'])){
    $cookie = SAE_TMP_PATH."/cookie.txt";
}else {
    $cookie = dirname(__FILE__)."/cookie.txt";
}

1、打开页面,获取COOKIEJAR,以及 token,并保存

$url = "http://www.fangbei.org/#agent/login";
$headers = array(
"User-Agent: 来源 方倍工作室 www.fangbei.org",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"Accept-Language: zh-CN,zh;q=0.9,en;q=0.8",
);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,false);
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie); //首次只接收
$result = curl_exec($curl);
curl_close($curl);

$pattern = '/name="_token" value="(.*?)"/is';
preg_match_all($pattern, $result, $matches);
if (isset($matches[1][0])){
    $token = $matches[1][0];
}else{
    die("获取token失败");
}

2、登录

 #2. 登录
$url = "http://www.fangbei.org/#/agent/login";
$headers = array(
"User-Agent: 来源 方倍工作室 www.fangbei.org",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"Accept-Language: zh-CN,zh;q=0.9,en;q=0.8",
"Origin: http://www.fangbei.org/#",
"Referer: http://www.fangbei.org/#/agent/login",
);

$fields = '_token='.$token.'&username=fangbei&password=fangbei.org';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,false);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $fields);
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie);    //发送cookie
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie);     //接收 cookie
curl_exec($curl);
curl_close($curl);
复制代码

3. 取数据

$url = "http://www.fangbei.org/#agent/AgentProductLink";
$headers = array(
"User-Agent: 来源 方倍工作室 www.fangbei.org",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"Accept-Language: zh-CN,zh;q=0.9,en;q=0.8",
"Referer: http://www.fangbei.org/#agent/welcome",
);

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,false);
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie);    //发送cookie
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie);     //接收 cookie
$content = curl_exec($curl);
curl_close($curl);

4、解析数据,生成json

require_once('simple_html_dom.php');
// var_dump($content);
$html_main = str_get_html($content);
if (!isset($html_main)){
    $html_main->clear();
    die("页面载入出错!");
}
$tjarray = array();
foreach($html_main->find('tr[class="cot"]') as $item)
{
    $id = @$item->find('td', 0)->plaintext;
    $title = @$item->find('td', 1)->plaintext;
    $button = @$item->find('div[class="btn btn-fill"]', 0)->outertext;
    $pattern = "/\(\'(.+?)\'\)/"; // copyUrl('http://www.fangbei.org/#top-apply/Affection-28679')
    preg_match_all($pattern, $button, $matches);
    $bturl = $matches[1][0];
    $tjarray[$id] = array("title"=>urlencode($title),"url"=>urlencode($bturl));
    // break;
}
$html_main->clear();
echo urldecode(json_encode($tjarray));

php服务端处理 ios内购充值

app一直没有接入iOS内购充值,随着业务支付功能越来越多,ios内购充值就提到日程上来了。那么,ios内购充值怎么做呢?

其实iOS内购充值是通过客户端接入iOS的IAP模块(In-AppPurchase)后,由客户端发起充值,然后再把充值数据(receipt)发给服务端,最后由服务端远程调用AppStore服务器验证。

具体的流程如图:

111.png

服务端连接AppStore验单

验单的过程是,服务端发起HTTP Post请求,将以下字段的数据以json格式请求 AppStore 服务器,解析返回数据来验证。

字段:receipt-data

来源:ios端内置的生成base64编码的token。

AppStore 服务器有两个,对应测试环境(沙盒测试)和正式环境:

测试环境: https://sandbox.itunes.apple.com/verifyReceipt

正式环境: https://buy.itunes.apple.com/verifyReceipt

// $verification_uri = 'https://buy.itunes.apple.com/verifyReceipt';$verification_uri = 'https://sandbox.itunes.apple.com/verifyReceipt'; $post_data = array(    'receipt-data'=>$receipt_data // 此处的值 是ios客户端生成的验签token);$ch = curl_init($verification_uri);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data)); $response = curl_exec($ch);$errno    = curl_errno($ch);$errmsg   = curl_error($ch);curl_close($ch); if ($errno != 0) {throw new Exception($errmsg, $errno);}$data = json_decode($response, 1);

服务端验证返回数据

iOS发起票据验证请求后,通过处理AppStore返回数据来验单。下面举两个示例,同时说明不同iOS版本的返回数据不同,服务端要做好区别。

1、iOS7及以上获取的票据返回数据:

{receipt =  {        "adam_id" = 0,        "app_item_id" = 0,        "application_version" = 1,        "bundle_id" = "com.test",        "download_id" = 0,        "in_app" = {{    "is_trial_period" = false,    "original_purchase_date" = "2017-01-01 01:01:01 Etc/GMT",    "original_purchase_date_ms" = 1483203661000,    "original_purchase_date_pst" = "2017-01-01 01:01:01 America/Los_Angeles",    "original_transaction_id" = 1000000000000001,    "product_id" = "com.test.10",    "purchase_date" = "2017-01-01 01:01:01 Etc/GMT",    "purchase_date_ms" = 1483203661000,    "purchase_date_pst" = "2017-01-01 01:01:01 America/Los_Angeles",    "transaction_id" = 1000000000000001},//......},        "receipt_type" = ProductionSandbox,        "request_date" = "2017-01-01 01:01:01 Etc/GMT",        "request_date_ms" = 1483203661000,        "request_date_pst" = "2017-01-01 01:01:01 America/Los_Angeles",        "version_external_identifier" = 0,    },    status = 0}

2、iOS7以下获取的票据返回数据(不包括iOS7):

{    receipt = {        "bid" = "com.test",        "bvrs" = 1,        "item_id" = 573837050,        "original_purchase_date" = "2017-01-01 01:01:01 Etc/GMT",        "original_purchase_date_ms" = 1483203661000,        "original_purchase_date_pst" = "2017-01-01 01:01:01 America/Los_Angeles",        "original_transaction_id" = 1000000000000001,        "product_id" = "com.test.10",        "purchase_date" = "2017-01-01 01:01:01 Etc/GMT",        "purchase_date_ms" = 1483203661000,        "purchase_date_pst" = "2017-01-01 01:01:01 America/Los_Angeles",        "transaction_id" = 1000000000000001    },    status = 0}

验证订单是否成功,关键看这几个数据:

1、status为 0 表示成功;其他都为失败,表示失败原因

2、根据 receipt.in_app 字段判断iOS版本,验证方法也不同

iOS7及以上:有in_app字段,验证 receipt.bundle_id 是否为你 App 的 bundle id,根据 in_app 处理充值的每一笔订单, 根据 product_id 判断用户充值了哪个档位,同时取出 transaction_id

iOS7以下:没有in_app字段,验证 receipt.bid 是否为你 App 的 bundle id,根据 product_id 判断用户充值了哪个档位,同时取出 transaction_id

3、根据 transaction_id 对比数据库历史订单判断是否已处理过,没有则认为本次充值是有效的。

iOS充值坑点: in_app 究竟是什么

receipt.in_app 是请求AppStore验单后返回的数据,前面有提及,为用户的充值订单数据。

有两个问题要注意:

1、iOS内购充值时,客户端充值后从iOS得到的票据 receipt_data 不是针对本次充值的,而是相当于给一个授权 token, 获取用户 appleid 账号在本 App 中所有未关闭的充值记录,包括刚刚发起的充值。

2、根据这个票据查到的充值数据(receipt.in_app) ,除了最近发起的充值,还包括了非消耗品型,订阅型的充值数据。其中,最近发起的充值,不只是刚刚发起的充值,还可能是最近的几笔充值。特别是沙盒测试,还可能拿到已经确认关闭了的充值订单

所以,取到充值数据,不是取 receipt.in_app 中的第一个数据、或最后一个,而是在客户端完成充值后,将AppStore回调给到的 transaction_id 拿来做匹配。

iOS充值坑点:App审核不通过

苹果审核App时,是在沙盒环境下测试。所以,当App提交苹果审核时,服务端需换成沙盒环境,否则就无法通过苹果审核。通常游戏开发商都会搞一个审核服来给苹果审核,这样,审核服用沙盒环境,正式服用正式环境。

但对于很多App应用开发商来说,专门搞一个服务器显然增加了不少成本。其实还是有办法处理的,方法如下:

根据验单返回的 status 字段:

222.png

当 status = 21007 时,把请求地址换成沙盒测试地址,再次请求验单。

php苹果内购支付验证

/**

  • 验证AppStore内付
  • @param string $receipt_data 付款后凭证
  • @return array 验证是否成功
    / function validate_apple_pay($receipt_data){ /*
    • 21000 App Store不能读取你提供的JSON对象
    • 21002 receipt-data域的数据有问题
    • 21003 receipt无法通过验证
    • 21004 提供的shared secret不匹配你账号中的shared secret
    • 21005 receipt服务器当前不可用
    • 21006 receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送
    • 21007 receipt是Sandbox receipt,但却发送至生产系统的验证服务
    • 21008 receipt是生产receipt,但却发送至Sandbox环境的验证服务
      */
      function acurl($receipt_data, $sandbox = 0){
      //小票信息
      $POSTFIELDS = array(‘receipt-data’ => $receipt_data);
      $POSTFIELDS = json_encode($POSTFIELDS); //正式购买地址 沙盒购买地址
      $url_buy = ‘https://buy.itunes.apple.com/verifyReceipt’;
      $url_sandbox = ‘https://sandbox.itunes.apple.com/verifyReceipt’;
      $url = $sandbox ? $url_sandbox : $url_buy;
      // dump($url);die;
      // $url = $url_sandbox;
      //简单的curl
      $ch = curl_init($url);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_POST, 1);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $POSTFIELDS);
      curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0); //这两行一定要加,不加会报SSL 错误
      curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
      $result = curl_exec($ch);
      curl_close($ch);
      return $result;
      }
      // 验证参数
      if (strlen($receipt_data)<20){ $result=array( ‘status’=>false,
      ‘message’=>’非法参数’
      );
      return $result;
      }
      // 请求验证
      $html = acurl($receipt_data);
      $data = json_decode($html,true);
      // dump($data);die;
      // 如果是沙盒数据 则验证沙盒模式
      if($data[‘status’]==’21007′){
      // 请求验证
      $html = acurl($receipt_data, 1);
      $data = json_decode($html,true);
      $data[‘sandbox’] = ‘1’;
      // dump($data);die;
      }
      if (isset($_GET[‘debug’])) {
      exit(json_encode($data));
      }
      // 判断是否购买成功
      // if(intval($data[‘status’])===0){
      // $result=array(
      // ‘status’=>true,
      // ‘message’=>’购买成功’
      // );
      // }else{
      // $result=array(
      // ‘status’=>false,
      // ‘message’=>’购买失败 status:’.$data[‘status’]
      // );
      // }
    return $data;
    }

PHP后端处理苹果内购对接

苹果内购流程:

iOS App上次苹果商店审核对于虚拟金币类必须要用苹果支付,不能使用第三方支付,苹果支付还要3/7分成,呵呵…

1、前六步有IOS端处理,最终获取购买凭证

2、POST请求,发送购买凭证receipt-data到服务端接口

复制代码
    /**
     * 苹果内购
     * @param receipt-data 购买凭证(必传)
     * @param is_test 是否沙盒数据(选填,1是 0否,默认否)
     * @return json
     **/
    public function actionsApple_pay(){

        if (!framework::post('is_test')) {    //沙盒购买地址
            $url = "https://sandbox.itunes.apple.com/verifyReceipt";
        }else{  //正式购买地址
            $url = "https://buy.itunes.apple.com/verifyReceipt";
        }

        $receipt_data = framework::post('receipt-data');
        // 验证参数
        if (strlen($receipt_data) < 20){
            $result = array(
                'status'=>false,
                'message'=>'非法参数'
            );
            echo json_encode($result);
            return false;
        }

        $post_data = json_encode(array("receipt-data" => $receipt_data));
        $response = https::curlHttps($url, $post_data);
        $res = json_decode($response, true);

        $err_msg = array(
            '21000' => 'App Store不能读取你提供的JSON对象',
            '21002' => 'receipt-data域的数据有问题',
            '21003' => 'receipt无法通过验证',
            '21004' => '提供的shared secret不匹配你账号中的shared secret',
            '21005' => 'receipt服务器当前不可用',
            '21006' => 'receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送',
            '21007' => 'receipt是Sandbox receipt,但却发送至生产系统的验证服务',
            '21008' => 'receipt是生产receipt,但却发送至Sandbox环境的验证服务'
        );

        // 判断是否购买成功   
        if(intval($res['status']) === 0){   
            $result = ['status'=>true, 'message'=>'正式购买成功'];   
        }else{   
            $result = ['status'=>false, 'message' => '购买失败 status:'.$res['status'].' - '.@$err_msg[$res['status']] ];
            framework::logWrite('苹果支付失败 ---res---'.json_encode($result));
        }

        echo json_encode($result);
        return false;
    }
复制代码

PHP判断是手机QQ内置浏览器还是QQ浏览器

if(isQQBrowser() == ‘QQ’){
echo “QQ内置浏览器”;
}elseif(isQQBrowser() == ‘QQBrowser’){
echo “QQ浏览器”;
}else{
echo “其他浏览器”;
}

function isQQBrowser(){
if(strpos($_SERVER[‘HTTP_USER_AGENT’], ‘QQ’) !== false){
if(strpos($_SERVER[‘HTTP_USER_AGENT’], ‘SQ‘) !== false){
return “QQ”; //QQ内置浏览器
}else{
return “QQBrowser”; //QQ浏览器
}
}
return false;
}

tp5批量更新数据saveAll()

ThinkPHP是国内流行的PHP开发框架之一,对于数据批量更新的问题在Think PHP5的官方文档有说明,但是我估计很多小伙伴看过文档之后可能会存在一点懵逼。因为官方文档讲述数据批量更新采用的是saveAll()的方法。以下是官方文档部分。

ThinkPHP5数据批量更新的问题

文档连接地址:https://www.kancloud.cn/manual/thinkphp5/135189

文档本身没有任何问题,假如我们有一个数据库表表名为“tp_user",其中"tp_"为表前缀。那么我们可以把包含主键的数组通过文档的方法直接批量更新到数据库中。

然而假如有一种情况就是我们的表名没有这么设计,或者我们在一个model中要更新一个特定的数据表的话,那么这个方法就不能直接使用了。否则就会报错。

今天之所以发现这个问题,是因为我在写项目中直接用Db的链式操作update()数组的时候出现了“没有更新数据”的错误后排查时发现的。

发现这一问题后我也百度了一下网上有没有网友遇到同类的问题,其中有部分网友的解决方案是重新封装一个updateAll()的方法。重新封装确实是一种最直接的解决问题的方法。同样的我也弄了个DataService来批量的修改数据,不过既然用了TP框架,我觉得还是最好用官方的方法比较好。经过半个小时研究TP的源代码,找到了最终的解决方法。

这里是think PHP5的方法,估计3.2不太适合。解决方法如下:

我们在任何位置如果想批量对任何一个数据库表执行批量更新的操作,只需要如下两行代码就可以了。

$this->name("数据表名");
$res = $this->saveAll($data);
至于更新最终结果,我们拿$res去判断就可以了。

以上内容就是波波今天遇到的问题及解决方法,希望可以帮助有同样需求的小伙伴。同样的下面是对单条数据更新返回值判断的补充。

我不知道有没有小伙伴写代码类似“$res = Db::name()->where($where)->update($data);”进行单条数据更新的,如果更新的数据和原始数据一样,就是没有改变的前提下,其实$res返回值判断很容易执行到false的逻辑中去。

解决方法:用“===”进行判断。示例如下:

if($res !== false) {
    echo 'success';
}else{
    echo 'false';
}
好了,这篇日记就写这些吧,其实项目中出现问题并不可怕,一步一步排查分析其实所有的问题都很容易解决。

<?php
namespace app\index\controller;
use app\index\model\Staff;

class Index {

  public function index(){

    //创建模型对象
    $model = new Staff;
    
    //创建自定义数据
    $data[] = ['id' => 1010,'name'=>'宋门庆'];
    $data[] = ['id' => 1011,'name'=>'马金莲'];

    //批量更新,自动识别更新和写入
    $result = $model -> saveAll($data,true);

    //反馈执行信息
    echo $result ? '更新成功!<br />' : '更新失败~~<br />' ;

    //查看更新后的信息
    echo '更新后的记录信息:<br />';

    //遍历数据对象数组
    foreach ($result as $list){
      dump($list -> getData());
    }    
  }
}

批量更新

<?php
namespace app\index\controller;
use app\index\model\Staff;

class Index {

  public function index(){

  $dataBefore = Staff::where('name','like','%云%')->select();

  if (!empty($dataBefore)){

      //查看一下更新前的数据对象中的原始数据
      echo '1. 查看一下更新前的数据对象中的原始数据<br />';
      foreach ($dataBefore as $before){
         dump($before->getData());
      }

      //更新数据对象中的原始数据
      foreach ($dataBefore as $list){
         $list -> setAttr('salary','6000');
         $data[] = $list -> getData();
      }

      //用数据对象中的原始数据更新表中对应字段信息
      $dataAfter = (new Staff()) -> saveAll($data);

      if (!empty($dataAfter)){
					echo '更新成功!<br />';
          //查看更新完成后返回的数据对象
          echo '2. 查看一下更新后的数据对象中的原始数据<br />';
          foreach ($dataAfter as $after){
            dump($after->getData());
          }
        }else{
          echo '更新失败!';
        }
  } else {
    echo '没有满足条件的记录!';
  }     
 }
}

输出

1. 查看一下更新前的数据对象中的原始数据
array(6) {
  ["id"] => int(1009)
  ["name"] => string(9) "楚云飞"
  ["sex"] => int(1)
  ["salary"] => float(8100)
  ["dept"] => string(9) "开发部"
  ["hiredate"] => string(10) "2017-01-01"
}
array(6) {
  ["id"] => int(1010)
  ["name"] => string(9) "李云龙"
  ["sex"] => int(1)
  ["salary"] => float(2000)
  ["dept"] => string(9) "开发部"
  ["hiredate"] => string(10) "2017-02-01"
}
更新成功!
2. 查看一下更新后的数据对象中的原始数据
array(6) {
  ["id"] => int(1009)
  ["name"] => string(9) "楚云飞"
  ["sex"] => int(1)
  ["salary"] => string(4) "6000"
  ["dept"] => string(9) "开发部"
  ["hiredate"] => string(10) "2017-01-01"
}
array(6) {
  ["id"] => int(1010)
  ["name"] => string(9) "李云龙"
  ["sex"] => int(1)
  ["salary"] => string(4) "6000"
  ["dept"] => string(9) "开发部"
  ["hiredate"] => string(10) "2017-02-01"
}

PHP语法基础篇——除法取整和取余数

1. ceil — 进一取整函数
函数详解
float ceil ( float value )
返回不小于 value 的下一个整数,value 如果有小数部分则进一位。ceil() 返回的类型仍然是 float,因为 float 值的范围通常比 integer 要大。
示例:

ceil(4.33)  52. floor — 舍去取整函数

函数详解
float floor ( float value )
返回不大于 value 的下一个整数,将 value 的小数部分舍去取整。floor() 返回的类型仍然是 float,因为 float 值的范围通常比 integer 要大。
示例:

echo floor(9.99) 93. round — 四舍五入取整函数

函数详解
float round ( float val [, int precision] )
返回将 val 根据指定精度 precision(十进制小数点后数字的数目)进行四舍五入的结果。precision 也可以是负数或零(默认值)。
例子 1. round() 例子

round(3.4); 3

round(3.5); 4因为我们的取整函数返回的数据类型都是float类型,一般我们可用intval函数,将数据类型强制转化为整数类型。

示例:
intval—将数据强制转化成整数型态
例子intval()

intval(4.3) 4

intval(4.7) 4 好了,我们来尝试下将除法结果分为整数和余数部分吧。

举例:7/3
整数部分:intval(floor(7/3))
余数部分:7%3

【TP3.2】路由匹配和规则

TP3.2框架的路由匹配和规则处理:

包括:静态路由,动态路由,多参数路由、正则路由

复制代码
<?php
return array(
    //'配置项'=>'配置值'
    
    /* 
     * 路由开启和匹配。首先开启路由匹配,然后根据相应的路由规则进行匹配
     * 1、静态路由
     * 2、动态路由
     * 3、动静态结合路由
     * 4、正则路由 
     */
    'URL_ROUTER_ON'   => true, //开启路由
    'URL_ROUTE_RULES' => array( //定义路由规则
        //路由规则          //指向url匹配地址
        'News/top' => 'news/index?type=top',     //静态路由(死的),指向Admin/news/index?type=top
        'News/:id\d$'    => 'News/read',          //动态路由,指向Admin/News/read?id=:id    //$后面再加参数是无效的
        'News/:name'    => 'News/read',          //动态路由,指向Admin/News/read?name=:name,注意这里的name参数一定要和控制器接受的name参数一致
        'News/:year\d/:month\d'  => 'News/archive',
        '/^News\/(\d{4})\/(\d{2})$/' => 'News/archive?year=:1&month=:2',//正则路由,指向Admin/News/archive?year=:1&month=:2
    ),
);

thinkphp3.2.3中设置路由,优化url

需求: 访问这个目录的时候,http://xx.com/p-412313要重定向到(暂且这么叫)http://xx.com/Home/Blog/index/id/412313

就是看着好看

我的应用目录是Application。模块是Home

第一步:知道哪个文件怎么处理的路由
路由处理在think/Route.class.php

// 动态路由处理        $routes =   C('URL_ROUTE_RULES');        // var_dump($routes);         if(!empty($routes)) {            // dump($routes);            //array(1) {                // ["/^p-(\d+)$/"] => string(16) "Blog/index?id=:1"            //}            // echo "rount.class.php\n";            foreach ($routes as $rule=>$route){                if(is_numeric($rule)){                    // 支持 array('rule','adddress',...) 定义路由                    $rule   =   array_shift($route);                }     ...代码多,仅标识位置

第二步:在项目模块的配置文件下,设置配置文件 如下(因为tp是逐级加载配置文件,惯例配置->应用配置->模式配

置->调试配置->状态配置->模块配置->扩展配置->动态配置,这里属于模块配置

<?phpreturn array(      'MODULE_ALLOW_LIST' => array('Home','Admin','Common'),     'DEFAULT_MODULE'       =>    'Home',  // 默认模块     'DEFAULT_CONTROLLER'    =>  'Index', // 默认控制器名称     'DEFAULT_ACTION'        =>  'index', // 默认操作名称         //    路由规则    'URL_ROUTER_ON' => TRUE,    'URL_ROUTE_RULES' => array(        '/^c-(\d+)$/' => 'Index/content?id=:1'    ),	 'URL_ROUTER_ON '=>true,     'URL_MODEL'          => '1',      'URL_ROUTE_RULES'=>array(          '/^p-(\d+)$/' => 'Home/Blog/index?id=:1',//意思是访问x.com/p-34 会访问的是x.com/Blog/index/id/34          ),);

第三部:
如果你没有设置默认的模块 ,会出现找不到p-34这个模块的错误。
那么需要在index.php中设置
define(‘BIND_MODULE’,’Home’);

这样就可以了。

说明:如果没有第三步。默认打开是正常的就是这样。

但是

所以我们操作第三步,就可以实现如下效果了: