极光推送案例

参考:http://docs.jpush.io/server/php_sdk/
Thinkphp推送类(需要下载vendor)

push()
            ->setPlatform(M\Platform('ios'))
            ->setAudience(M\all)
            ->setNotification(M\notification($message))
//             ->printJSON()
            ->send();
            return $result->json;
        } catch (APIRequestException $e) {//推送失败调试时候可以打开
            //             $br = '\n';
//             echo 'Push Fail.' . $br;
//             echo 'Http Code : ' . $e->httpCode . $br;
//             echo 'code : ' . $e->code . $br;
//             echo 'Error Message : ' . $e->message . $br;
//             echo 'Response JSON : ' . $e->json . $br;
//             echo 'rateLimitLimit : ' . $e->rateLimitLimit . $br;
//             echo 'rateLimitRemaining : ' . $e->rateLimitRemaining . $br;
//             echo 'rateLimitReset : ' . $e->rateLimitReset . $br;
            return false;
        } catch (APIConnectionException $e) {
//             $br = "\n";
//             echo 'Push Fail: ' . $br;
//             echo 'Error Message: ' . $e->getMessage() . $br;
//             echo 'IsResponseTimeout: ' . $e->isResponseTimeout . $br;
            return false;
        }
        return false;
    }
    /**
     * 推送信息到指定用户 (备注:一次最多只能推送1000个RegID)
     * @param String $message    消息
     * @param Array  $users    用户编号
     * @param Boolean $all     是否推送该用户所有设备 默认推送所有 否则推送最新的一个 
     * @return boolean
     */
    public static function sendToUser($message, $users, $all = true) {
        if(empty($message) || empty($users) || !is_array($users)) {
            return false;
        }
        $audience = $list =  array();
        $map['user_id'] = array('in', $users);
        if($all) {
            $list = M(self::USER_TABLE)->field(self::USER_REGID_FIELD)->where($map)->select();
        } else {
            $list = M(self::USER_TABLE)->field(self::USER_REGID_FIELD)->where($map)->limit(1)->order(self::USER_TABLE_ORDER)->select();
        }
        if($list) {
            foreach ($list as $v) {
                if(trim($v[self::USER_REGID_FIELD])) {
                    $audience[] = $v[self::USER_REGID_FIELD];
                }
            }
        }
        if(!$audience && $audience[0]) {
            return false;
        }
        return self::sendToRegistrationId($message, $audience);
    }
    /**
     * 推送消息到指定IOS设备 最多一次推送1000
     * 备注参考:http://docs.jpush.io/server/rest_api_v3_push/
     */
    public static function sendToRegistrationId($message,$audience) {
        if(empty($message) || empty($audience) || !is_array($audience)) {
            return false;
        }
        try {
            $client = new JPushClient(self::APP_KEY, self::MASTER_SECRET);
            $result = $client->push()
            ->setPlatform(M\platform('ios'))
            ->setNotification(M\notification($message))
            ->setAudience(M\registration_id($audience))
            //->printJSON()
            ->send();
            return $result->json;
        } catch (APIRequestException $e) {
//             $br = '\n';
//             echo 'Push Fail.' . $br;
//             echo 'Http Code : ' . $e->httpCode . $br;
//             echo 'code : ' . $e->code . $br;
//             echo 'Error Message : ' . $e->message . $br;
//             echo 'Response JSON : ' . $e->json . $br;
//             echo 'rateLimitLimit : ' . $e->rateLimitLimit . $br;
//             echo 'rateLimitRemaining : ' . $e->rateLimitRemaining . $br;
//             echo 'rateLimitReset : ' . $e->rateLimitReset . $br;
            return false;
        } catch (APIConnectionException $e) {
//             $br = "\n";
//             echo 'Push Fail: ' . $br;
//             echo 'Error Message: ' . $e->getMessage() . $br;
//             echo 'IsResponseTimeout: ' . $e->isResponseTimeout . $br;
//             return false;
        }
        return false;
    }
    /**
     * 向消息队列压入推送任务 1 推送所有  2推送指定设备  3推送指定用户
     * @param String $message    推送内容
     * @param Int $type          推送类型
     * @param Array $ext         推送用户编号或RegID
     * @return boolean
     */
    public function pushMessage($message, $type = self::SEND_TO_ALL, $ext = array()) {
        if(empty($message) || !in_array($type, array(self::SEND_TO_ALL,self::SEND_TO_REG,self::SEND_TO_USER))) {
            return false;
        }
        try {
            $redis = new Redis;
            $redis->connect('127.0.0.1', 6379);
            $data['message'] = $message;
            $data['type'] = $type;
            $data['ext'] = $ext;
            $pushData = json_encode($data);
            return $redis->lPush(self::REDIS_PUSH_MESSAGE_KEY, $pushData);//队列左边添加元素
        } catch (\Exception $e) {
//             echo $e->getMessage();
            return false;
        }
        return false;
    }
    
}

 

ThinkPHP3.1.2笔记

1.开启trace

方法一:在配置文件中添加(默认在config.php,如果定义debug模式,可以定义在debug.php
SHOW_PAGE_TRACE => 1,
方法二:在入口文件
defined(“SHOW_PAGE_TRACE”, 1);
方法三:动态设置
C(‘SHOW_PAGE_TRACE’, 1);

使用方法
trace(‘展示代码’,’info’);

2.函数库

系统函数库和项目函数库不需要加载即可试用,扩展函数库需要加载才可以用
加载函数库文件可用配置”LOAD_EXT_FILE”=>’user,db’这样可以加载项目公共目录(common)下的函数库文件user.php和db.php
可以手动加载load(“@.user”);

3.类库

显示导入import(“Think.Util.Array”);//导入基类库Util/Array.class.php文件
导入当前项目类库可用import(“@.Action.UserAction”)或者import(“APP.Action.UserAction”);
可以参考import函数代码

别名导入
在配置目录alias.php中配置别名,即可试用import(“page”);

第三方类库存放在系统扩展目录Extend下的Vendor目录
可以用Vendor(“Zend.Filter.Dir”);导入第三方

自动加载
自动加载优先级从高到底:别名自动加载=》系统规则自动加载=》自定义路径自动加载
可以配置”APP_AUTOLOAD_PATH”=>’@.Common,@Tool’加载自定义下类库

4.URL模式

配置项URL_MODEL
普通模式为0
PATHINOF模式为1
Rewrite模式为2
兼容模式为3

推荐使用PATHINFO模式开发,如果空间不支持,可以试用兼容模式或者普通模式

5.空操作和空模块—方便定义错误处理页
如果定义了空操作那么如果一个方法不存在,即使存在模板文件也会优先定向到空操作
eg:比如一个控制器中定义了_empty方法,那么即使模板中有test.html模板,但是不存在testAction,那么请求test
方法的时候会优先定位到_empty方法中

6.模块分组
配置APP_GROUP_LIST 用逗号分开,设置默认分组DEFAULT_GROUP

7.伪静态配置
‘URL_HTML_SUFFIX’ => ‘shtml|html|xml’, 配置多个伪静态后缀

8.URL路由
开启路由URL_ROUTE_ON=>true

规则路由
格式
规则=> “分组/模块/操作?额外参数=值”
规则=> array(‘分组/模块/操作’, ‘额外参数=值’)
规则=>外部地址
规则=>array(‘外部地址’, ‘重定向代码’)
要点
:开头的是动态变量
外部地址可以引用动态变量采用:1,:2的方式
路由规则支持:id\d表示只能匹配数字
排除非数字变量:cate^add|edit
路由规则中的静态地址不分大小写

9.APACHE隐藏index.php入口文件
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>

10.ULR生成

在控制器中我们可以用U方法生成URL地址
比如U(“News/read?id=1”)
在不同的url模式下生成的url地址不同

在模板中我们可以用{:U(参数1,参数2…)}的方式生成URL

如果设置URL_CASE_INSENSITIVE=>true那么生成的url地址全是小写的

11.URL地址大小写
‘URL_CASE_INSENSITIVE’ =>true 这样就不区分大小写了

12.前置操作和后置操作可以参考手册

13.跨模块调用
A方法可以实现跨模块调用其他分组下的控制器.A[项目名://][分组名]模块名
A(“User”)当前模块下的user控制器
A(“Admin://User)调用admin项目的User模块
A(“Admin/User”)调用admin分组中的User模块
A(“Admin://Tool/User”)调用Admin项目Tool分组中的User模块

R方法可以调用一个模块下的一个操作方法。R[项目名://][分组名]模块名, array(‘参数1′,’参数2’);

14.自定义提示页面模板
TMPL_ACTION_ERROR => ‘Public:error’
TMPL_ACTION_SUCCESS=>’Public:success’
模板中可以用$msgtitle表示操作标题;$message页面提示信息;$status来表示状态 1表示成功;$waitSecond跳转等待时间
$jumpUrl跳转地址
如果是ajax提交,会自动调用ajaxReturn返回

15.重定向
在控制器中用redirect实现页面重定向功能;参数可以参考U方法

17.获取系统变量
在控制器中我们可以使用$this->方法名(“变量名,[过滤方法],[‘默认值’]);
其中方法名有_get,_post,_param,_request(REQUEST参数),_put,_session,_cookie($_COOKIE),_server($_SERVER)
_globals($GLOBALS)

可以设置默认过滤函数
‘DEFAULT_FILTER’ => ‘htmlspecialchars,strip_tags’

支持获取全部变量$this->_get();

可以试用$this->_param(0)获取PATHINFO中的第一个参数,以及获取get和post等参数,推荐使用

18.判断请求类型
isGet()判断是否是GET方式提交
isPost()判断是否是POST方式提交
isPut()判断是否是PUT方式提交
isDelete()判断是否是delete方式提交
isHead()判断是否是Head方式提交
isAjax判断是否是ajax提交,如果用Jquery类库则不需要添加隐藏域,否则需要添加一个隐藏域

19.Ajax返回
status 操作状态
info 提示信息
data 返回数据
$this->ajaxReturn(返回数据,提示信息,操作状态);

支持$data[‘status’] =1;$data[‘info’] = ‘test’;$this->ajaxReturn($data,’JSON’);

20.Action参数绑定
比如/News/read/id/1,绑定read方法,function read($id = 0) {
echo $id;
}

TP入门第十二天

1、RBAC权限管理

使用内置RBAC,最主要是懂得官方提供的四个数据表关系,这里重点说明下四个表的关系

thinkphp中RBAC有四个表access、role、node、role_user

其中role是用户群组表、node是节点表、role_user是用户和群组关系表、

access是群组和节点关系表(也就是在access内的用户组可以访问对应的节点)

,其中access中modul字段我不明白是干嘛的。如果你知道的话可以告诉我,十分感谢

程序和数据库打包了。附件:Code

学习心得:学东西不能着急,我用了十二天(断断续续的大概有20天左右)明白了tp的用法,可是tp还有很多要学的~

如果你也是tp爱好者,你也喜欢tp,我希望你能给我交流讨论学习。。下步就是做项目开发了。

TP入门第十二天

1、模板技术

为何使用模板这里就不罗嗦了,直接介绍模板技术

变量传递和显示:

例如在action里面可以这样写

$title=”变量”;

$arr=array(“标题”,”内容”,’my’=>”时间”);//数组

$this->assign(‘atitle’,$title);

$this->assign(‘content’,’这是内容’);

$this->assign(‘time’,time());

$this->assign(‘mylist’,$arr);

$this->display();

这样就需要在模板里面获取

内容:{$content}

<br>

时间:{$time}

<hr>

数组测试

第一个:{$mylist[0]}<br>

第二个:{$mylist.1}<br>

第三个:{$mylist.my}<br>

如果是对象,那么就需要用:,例如:{$mylist:ff}

模板注释:格式:{/*注释内容 */ }或 {//注释内容 }

说明:在显示页面的时候不会显示模板注释,仅供模板制作的时候参考。

函数使用:在前面制作留言板的过程中,用到date函数格式化时间显示,这里说明。模板变量的函数调用格式为:

{$varname|function1|function2=arg1,arg2,### }

说明:

{和 $符号之间不能有空格,后面参数的空格就没有问题

###表示模板变量本身的参数位置

支持多个函数,函数之间支持空格

支持函数屏蔽功能,在配置文件中可以配置禁止使用的函数列表

支持变量解析缓存功能,重复变量字串不多次解析

使用例子:

{$webTitle|md5|strtoupper|substr=0,3}

编译后的PHP代码就是:

<?php echo (substr(strtoupper(md5($webTitle)),0,3)); ?>

注意函数的定义和使用顺序的对应关系,通常来说函数的第一个参数就是前面的变量或者前一个函数调用的返回结果,如果你的变量并不是函数的第一个参数,需要使用定位符号,例如:

{$create_time|date=”y-m-d”,###}

编译后的PHP是:

<?php echo (date(“y-m-d”,$create_time)); ?>

默认值输出:如果输出的模板变量没有值,但是我们需要在显示的时候赋予一个默认值的话,可以使用default语法,格式:

{$变量|default=”默认值”}

这里的default不是函数,而是系统的一个语法规则,例如:

{$user.nickname|default=”这家伙很懒,什么也没留下”}

对系统变量的输出也可以支持默认值,例如:

{$Think.post.name|default=”名称为空”}

默认值支持Html语法。

Continue reading

TP入门第十一天

1、数据库视图

视图通常是指数据库的视图,视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。对其中所引用的基础表来说,视图的作用类似于筛选。定义视图的筛选可以来自当前或其它数据库的一个或多个表,或者其它视图。分布式查询也可用于定义使用多个异类源数据的视图。如果有几台不同的服务器分别存储组织中不同地区的数据,而您需要将这些服务器上相似结构的数据组合起来,这种方式就很有用。

要定义视图模型,只需要继承ViewModel,然后设置viewFields属性即可

例子:

class BlogViewModel extends ViewModel {

public $viewFields = array(

‘Blog’=>array(‘id’,’name’,’title’),

‘Category’=>array(‘title’=>’category_name’,’_on’=>’Blog.category_id=Category.id’),

‘User’=>array(‘name’=>’username’,’_on’=>’Blog.user_id=User.id’),

);

}

我们来解释一下定义的格式代表了什么。

$viewFields 属性表示视图模型包含的字段,每个元素定义了某个数据表或者模型的字段。

例如:

Continue reading

TP入门第九天

1、验证码

TP2.0的使用网上一大堆教程,这里只是简单介绍下,把org目录拷贝到thinkphp目录的lib目录下,然后导入到生成验证码页面即可

TP3.0需要把org文件存放在tp的Extend/Library目录下

[php]

function yzm()

{

&nbsp;

import(‘ORG.Util.Image’);

Image::buildImageVerify();

}

[/php]

具体参数可以参考手册进行深刻了解

2、图片添加水印

public function mm(){

import(“ORG.Util.Image”);

$Image = new Image();

// 给1.jpg 图片添加logo水印,注意这里的路径问题,我这里的图片都和入口文件相同文件内

$Image->water(“1.jpg”,”logo.jpg”);

echo “成功”;

}

Continue reading

TP入门第十天

1、自动验证

数据对象是由表单提交的$_POST数据创建。需要使用系统的自动验证功能,只需要在Model类里面定义$_validate属性,是由多个验证因子组成的二维数组。

验证因子格式: array(验证字段,验证规则,错误提示,[验证条件,附加规则,验证时间])

验证字段 必须 需要验证的表单字段名称,这个字段不一定是数据库字段,也可以是表单的一些辅助字段,例如确认密码和验证码等等。有个别验证规则和字段无关的情况下,验证字段是可以随意设置的,例如expire有效期规则是和表单字段无关的。
验证规则 必须 要进行验证的规则,需要结合附加规则,如果在使用正则验证的附加规则情况下,系统还内置了一些常用正则验证的规则,可以直接作为验证规则使用,包括:require字段必须、email邮箱、url URL地址、currency货币、number数字。
提示信息 必须 用于验证失败后的提示信息定义
验证条件 可选 包含下面几种情况:Model::EXISTS_VAILIDATE或者0存在字段就验证 (默认)Model::MUST_VALIDATE或者1必须验证

Model::VALUE_VAILIDATE或者2值不为空的时候验证

附加规则 可选 配合验证规则使用,包括下面一些规则:regex 正则验证,定义的验证规则是一个正则表达式(默认)function函数验证,定义的验证规则是一个函数名

callback方法验证,定义的验证规则是当前模型类的一个方法

confirm验证表单中的两个字段是否相同,定义的验证规则是一个字段名

equal验证是否等于某个值,该值由前面的验证规则定义

in验证是否在某个范围内,定义的验证规则必须是一个数组

length验证长度,定义的验证规则可以是一个数字(表示固定长度)或者数字范围(例如3,12表示长度从3到12的范围)

between验证范围,定义的验证规则表示范围,可以使用字符串或者数组,例如1,31或者array(1,31)

expire验证是否在有效期,定义的验证规则表示时间范围,可以到时间,例如可以使用 2012-1-15,2013-1-15表示当前提交有效期在2012-1-15到2013-1-15之间,也可以使用时间戳定义

ip_allow 验证IP是否允许,定义的验证规则表示允许的IP地址列表,用逗号分隔,例如 201.12.2.5,201.12.2.6

ip_deny 验证IP是否禁止,定义的验证规则表示禁止的ip地址列表,用逗号分隔,例如201.12.2.5,201.12.2.6

unique 验证是否唯一,系统会根据字段目前的值查询数据库来判断是否存在相同的值。

验证时间 可选 Model:: MODEL_INSERT或者1新增数据时候验证Model:: MODEL_UPDATE或者2编辑数据时候验证Model:: MODEL_BOTH或者3全部情况下验证(默认)

具体用法可以参考手册进行

Continue reading

TP入门第八天

[小型留言板-增删查改]

1、先建立数据库lyb,然后建立表lyb_notes

建表代码如下:

CREATE TABLE `lyb_notes` (

`id` int(10) NOT NULL auto_increment,

`title` varchar(100) collate utf8_bin NOT NULL,

`time` varchar(11) collate utf8_bin NOT NULL,

`content` text collate utf8_bin NOT NULL,

`clientip` varchar(15) collate utf8_bin NOT NULL,

PRIMARY KEY  (`id`)

) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;

2、书写入口文件

<?php

//入口文件

//定义核心文件夹、项目名称和路径

define(‘THINKPHP_PATH’,’./ThinkPHP/’);

define(‘APP_NAME’, ‘lyb’);

define(‘APP_PATH’, ‘./lyb/’);

//开启调试模式

define(‘APP_DEBUG’,true);

// 加载框架入口文件

require_once (THINKPHP_PATH.”ThinkPHP.php”);

?>

3、编写配置文件

<?php

if(!defined(‘THINKPHP_PATH’)){echo “非法错误!”;exit;}

return array(

//’配置项’=>’配置值’

//很多选项都是默认配置都可以,这里基本配置项目把用的配置都列举出来了

‘URL_MODEL’=>1,//0是普通模式,1是pathinfo模式(默认配置),2是rewrite模式,3是兼容模式

‘DB_TYPE’               => ‘mysql’,     // 数据库类型

‘DB_HOST’               => ‘localhost’, // 服务器地址

‘DB_NAME’               => ‘lyb’,       // 数据库名

‘DB_USER’               => ‘root’,      // 用户名

‘DB_PWD’                => ‘joyous’,    // 密码

‘DB_PORT’               => ‘3306’,      // 端口

‘DB_PREFIX’             => ‘lyb_’,      // 数据库表前缀

‘DB_CHARSET’            => ‘utf8’,      // 数据库编码默认采用utf8

‘APP_DEBUG’=>true,

);

?>

Continue reading

TP入门第七天

Trace信息无法显示,因为信息需要显示在body体内

1、创建数据

我们在phpaction里面当然也可以使用$_POST以及$_GET获取变量,而TP提供了更加便捷的方法。Create方法创建的数据对象是保存在内存中,并没有实际写入到数据库中,直到使用add或者save方法才会真正写入数据库。比如我们提交了表单里面很多数据如果我们都用$_POST或者$_GET获取会把我们给搞疯掉的!而create会自动创建数据。我们直接用add或者save就可以保存到数据库(有人问,那数据库中的信息和提交的如何一一对应?)在进行add或者save操作的时候,数据表中不存在的字段以及非法的数据类型(例如对象、数组等非标量数据)是会自动过滤的,不用担心非数据表字段的写入导致SQL错误的问题。

所以,你提交的表单中需要设置name要和表中字段对应才能用create创建数据

(那岂不暴漏了表中字段信息?TP考虑到了,如果想隐藏字段信息可以看下面信息)

2、字段映射(官方解释)

ThinkPHP的字段映射功能可以让你在表单中隐藏真正的数据表字段,而不用担心放弃自动创建表单对象的功能,假设我们的User表里面有usernameemail字段,我们需要映射成另外的字段,定义方式如下:

Class UserModel extends Model{

protected $_map = array(

‘name’           =>’username’, //把表单中name映射到数据表的username字段

‘mail’             =>’email’, //把表单中的mail映射到数据表的email字段

);

}

Continue reading

TP入门第六天

1、模型

模型类一般位于项目的Lib/Model目录下面,当我们创建一个UserModel类的时候,其实已经遵循了系统的约定。模型类的命名规则是除去表前缀的数据表名称,采用驼峰法命名,并且首字母大写,然后加上模型类的后缀定义Model

模型名(类名) 约定对应数据表(假设数据库的前缀定义是 think_
UserModel think_user
UserTypeModel think_user_type

如果你的数据表和这个不一样,可以使用以下属性进行调正

tableName 不包含表前缀的数据表名称,一般情况下默认和模型名称相同,只有当你的表名和当前的模型类的名称不同的时候才需要定义。
trueTableName 包含前缀的数据表名称,也就是数据库中的实际表名,该名称无需设置,只有当上面的规则都不适用的情况或者特殊情况下才需要设置。
dbName 定义模型当前对应的数据库名称,只有当你当前的模型类对应的数据库名称和配置文件不同的时候才需要定义。

贴出来官方手册中的例子

下面举个例子来加深理解,例如,在数据库里面有一个think_categories表,而我们定义的模型类名称是CategoryModel,按照系统的约定,这个模型的名称是Category,对应的数据表名称应该是think_category(全部小写),但是现在的数据表名称是think_categories,因此我们就需要设置tableName属性来改变默认的规则(假设我们已经在配置文件里面定义了DB_PREFIX为 think_)。

protected $tableName = ‘categories’;

注意这个属性的定义不需要加表的前缀think_

而对于另外一种特殊情况,数据库中有一个表(top_depts)的前缀和其它表前缀不同,不是think_而是 top_,这个时候我们就需要定义 trueTableName属性了

protected $trueTableName = ‘top_depts’;

注意trueTableName需要完整的表名定义

除了数据表的定义外,还可以对数据库进行定义,例如:

protected $dbName = ‘top’;

2、实例化模型

首先说明一下有四种实例化方法

第一种:实例化基础模型类

用法:$user=new Model(‘user’);//或者使用$user=M(‘user’);//这里声明下user的首字母可以大写也可以小写

用途:支持跨项目调用,完成基本的增删查改(CURD)操作

第二种:实例化公共模型类

用法:$user=new CommonModel(‘User’);这里说明下这个CommonModel.class.php是在/APP_PATH/lib/Model目录下建立的,比如user表(省去了前缀)和column表中都需要这样一个简单的方法public function GG(){echo “Joyous学习TP3.0″;}当然一般不会这么简单的逻辑(我这里只是让大家容易理解,如果没有理解话也不要担心~

第三种:实例化自定义模型类

用法:这种情况是使用的最多的,一个项目不可避免的需要定义自身的业务逻辑实现,就需要针对每个数据表定义一个模型类,这个时候需要在项目的lib/model目录下,比如UserModel.class.php。这个时候你可以使用$user=new UserModel();//注意这里没有表名了!!或者使用$user=D(‘User’);//后面会讲解D快捷方法

Continue reading