概览
1、MVC
主流的设计模式,分离界面与逻辑,高效的协作开发。2、模块化
采用模块形式组织控制器。解决大型项目文件多、难管理的难题,避免后期迭代文件增多导致代码管理混乱的场面。小项目同样可以采用简单的但模块化的架构组织。3、组件式
框架所有功能都是以组件形式工作,您可以根据自己的需求对各个组件进行改进升华,以适应自己的开发规则,同时可以添加自己的功能组件到框架中,过程简单易用。4、易使用
在控制器以及模型中可以自动的加载所有组件,省去配置、加载等繁琐的操作,一切都是如此简单$this->组件名5、高效率
框架根据php语言的特性,在特定部分采用单例的设计模式以节省内存的使用。采用控制反转(IoC)的设计模式实例化类,以降低模块之间的耦合度。6、数据库
数据库提供了三种操作形式。1 直接执行sql,2 通过连贯操作组合sql语句,3 ORM操作数据库,简单快捷。7、安全性
1、用户发送的数据全部进行初步检测,并且销毁全局数组,防止一句话脚本的攻击2、提供数据过滤,清除非打印字符,文件名不合法,XSS字符串。让网站免受跨站攻击
3、防止sql注入,数据库在执行前都会对sql字符串进行合法性检测
4、提供数据格式验证组件,对用户提交的数据类型进行检测,防止数据表字段溢出 5、提供验证码以及表单CSRF防御机制,以应对互联网的'洪水'攻击
项目
创建项目文件夹
我们创建自己的项目文件夹叫做 App,然后在文件夹里面创建我们项目需要的各个文件App controllers放置控制器类 models 放置模型类 config 放置配置文件 view 放置模版文件 index.php 入口文件 其他文件夹用户可自行创建,建议您将项目文件(控制器、模型类、配置文件)与可访问的文件(入口文件、图片、css、js)分开存放,并且设置不同的读写权限。
入口文件
入口文件内容仅仅需要下面的三行代码<?php define('APP_PATH', dirname(__DIR__)); // 指定项目文件夹 include dirname(__DIR__).'/src/App.php'; // 加载框架入口文件 App::run(); // 执行框架
配置
设置你的配置文件 参照这里 配置文件配置
配置文件
下面是配置文件夹的内容: config configs.php核心配置文件 rules.php表单自动验证定义的规则 hooks.php定义的钩子程序 datas.php自定义的配置参数 具体请参阅源代码中configs.php文件的注释主配置文件
<?php return [ // 全局的应用程序配置项 'application'=>[ 'id'=>'app', // 应用程序的id,项目的命名空间会用到 'timezone'=>'RPC', // 设置时区 'hooks'=>['file'=>'config/hooks.php','class'=>'Hooks'], // 指定钩子程序的位置 ], // 路由配置 // 'router'=>[ // 0 自动识别url // 1 ?m=Admin&c=Access&a=login&arg1=1.... // 2 Admin/Access/login/arg1/arg2... // 3 ?r=Admin/Access/login/arg1/arg2... // 4 'urlmode'=>0, 'defaultController'=>'Index', // 默认控制器 'defaultAction'=>'index', // 默认方法 'modules'=>['Api/WeiXin','Admin'], // 存在的模块名 'regex'=>[ // 正则匹配url规则 'pattern'=>'Index', ], ], // 数据库配置 'database'=>[ // 'dsn'=>'pdo-mysql://root@127.0.0.1/test', 'dsn'=>'mysql://root@127.0.0.1/test', // dsn形式 'scheme'=>'pdo-mysql', // 数据库类型(pdo类型的要以 pdo-模型 的形式指定) 'host'=>'127.0.0.1', // 地址 'port'=>3306, // 端口 'dbname'=>'test', // 数据库名称 'user'=>'root', // 帐号 'passwd'=>'321321', // 密码 'charset'=>'utf8', // 数据表编码 'prefix'=>'' // 数据表前缀 ], // 内存缓存 'cache'=>[ 'dsn'=>'memcache://127.0.0.1:11211', // dsn字符串形式定义 'scheme'=>'memcache', // 缓存类型 'host'=>'127.0.0.1', // 地址 'port'=>11211, // 端口 ], // session 'session'=>[ 'auto_start'=>false, // 自动加载 'passwd'=>'321321', // 连接store的密码 // 'dsn'=>'pdo-mysql://root:@127.0.0.1:3306/session/sess_tab', 'dsn'=>'memcache://127.0.0.1:11211', // 字符串形式 'scheme'=>'pdo-mysql', // 存储session数据库的模型 'host'=>'127.0.0.1', // 地址 'port'=>3306, // 端口号 'user'=>'root', // 用户名 'dbname'=>'session', // 存储session的数据库名称 'tbname'=>'sess_tab', // 存储session的数据表名称 'charset'=>'utf8', // 编码方式 'prefix'=>'', // 表前缀 'sess_name'=>'__SESSIONID__', 'sess_expire'=>3600*24, // 默认session过期时间 'alive_time'=>3600, // 用户活跃时间间隔 这个时间内没有任何操作视为下线 'cookie_path'=>'/', // cookie 路径 'cookie_domain'=>'', // cookie 域名 ], // 模版配置 'view'=>[ 'drive'=>'template', // 模板引擎 'skin'=>'default', // 默认皮肤 'tpl_ext'=>'php', // 模版文件后缀 'form_hash_name'=>'__hash__', // 表单hash字段名 'form_hash_keys'=>'fantasy', // 表单hash的key ], ///////////// // 加载用户数据 // ///////////// 'datas'=>include 'datas.php', 'alias'=>[], ];
钩子程序
默认的钩子程序是在 项目文件夹/config/hooks.php,你也可以在配置文件中指定其他的文件作为钩子程序。# | 方法名 | 作用 |
---|---|---|
1 | preSystem | 框架初始化之后调用执行 |
2 | preRoute | 在路由解析url之前调用 |
3 | preController | 在url解析之后,调用执行指定的控制器之前调用 |
4 | preResponse | 在发送内容到用户客户端之前调用 |
5 | endSystem | 整个交互过程完成之后执行 |
<?php
use frameworkbaseBase;
class Hooks extends Base{
public function __construct(){
$this->preSystem();
}
// 框架开始执行之前 初始化之前
public function preSystem(){}
// 路由开始解析之前
public function preRoute(){
// echo 'hello';
}
// 路由解析之后 调用用户控制器之前
public function preController(){
// echo "你请求的控制器是:".$this->dispatch->getControllerName()."
";
// echo "你请求的控制器方法是:".$this->dispatch->getActionName()."
";
}
//发送内容到用户浏览器之前
public function preResponse(){}
框架结束
public function endSystem(){}
}
路由解析规则
框架支持多种的url风格 ?m=模块名&c=控制器名&a=方法&args.... /模块名/控制器名/方法/args.... ?r=模块名/控制器名/方法/args....模块名是为了指明你的控制器所在的文件夹目录,未指定则指定是 项目/controllers/ 这个目录,指定的话需要你事先在配置文件中 ['router']['modules'] => [模块1,模块2,模块3] 声明。指定模块名的话,框架所调用的控制器文件路径就是 项目/controllers/模块名/ 这个目录了。
比如我们需要访问一个控制器,这个控制器文件所在目录路径 App/controllers/Pay/Taobao/CashController.php 如下图: App controllers Pay 嵌套的模块 Taobao 嵌套的模块 CashController.php 控制器类文件 models config 我们可以知道,要访问的控制器 CashController.php 在文件夹 controllers/Pay/Taobao 下,而 Pay/Taobao 则是这个控制器的模块名。URL中的参数部分应该是这样的 /Pay_Taobao/Cash/index Pay_Taobao 会被框架自动转义成 Pay/Taobao ,URL中的模块名 控制器名都会被自动转义,规则如下
URL部分 | 原来的 | 转义后 | 转义规则 |
模块名 | foo | Foo | 在没有 '-' '_' 字符串时,将模块名字符串首字母大写 |
模块名 | foo_bar | Foo/Bar | 对于中间有下划线的,会依据下划线分割字符串,再将每个字符串首字母大写然后用 '/' 将字符串拼接 |
模块名 | foo-bar | FooBar | 对于中间有横线的,会依据横线分割字符串,再将每个字符串首字母大写然后直接将字符串拼接 |
控制器 | bar | Bar | 在没有 '-' 字符串时,将控制器的首字母大写。(所以在类以及类文件的命名规则都要首字母大写) |
控制器 | foo-bar | FooBar | 对于中间有横线的,会依据横线分割字符串,再将每个字符串首字母大写然后直接将字符串拼接 |
控制器
命名规则
我们采用流行的驼峰命名法对文件名、类名进行命名规范控制器文件名首字母要大写且要连接上字符串Controller,后缀为php。比如我们的控制器名称为Index,则文件名为 IndexController.php。若我们要定义的控制器名称是两个单词(customer 、analysis)组成的 则文件名应该是 CustomerAnalysisController.php 。值得注意的是 文件名要和类名一致,包括大小写。
命名空间
我们采用命名空间对用户的类进行管理,这样您就不必担心类命名冲突的问题啦!如何使用命名空间?1、在文件的最开始定义命名空间 namespace 自定义的名字
2、需要使用一个类的时候 use 自定义的命名空间类名 更多关于命名空间的用法可以到这里查看 php5增加的命名空间以及异常
3、命名空间的名称是以 foobarclass 这样的形式来命名的,一般这个字符串要反映出所属模块以及文件路径的 模块路径路径..
创建我们的第一个控制器 IndexController.php
在controllers目录创建一个文件名称为 IndexController.php 文件内容如下:<?php namespace appcontrollers; // 命名空间 use frameworkbaseController; // 继承框架的控制器 class IndexController extends Controller{ // 定义类名 public function show(){ // 创建一个方法 echo "Hello World!"; } } 对于命名空间 appcontrollers app指明模块是我们的项目 ,controllers是我们文件的存放路径。注意,这里的 app 是你在配置文件中定义的 ['application']['id'] 项。在你的项目中的所有类定义命名空间都要以这个id为开头,来表示文件所属的模块。 框架的命名空间是以 framework 为开始的。并且控制器要继承框架的控制器,这样你就能方便的调用各个组件啦!
// 常用的页面显示函数 $this->assign('key','val') 为模版赋值 $this->display('tpl_name') 显示模版
数据库
连贯操作
无论是在控制器还是在模型中进行编码,我们都可以随时使用数据库,只需要你简单的直接使用 $this->db 。 $this->db->select(查询的字段)->where(查询条件)->limit(条数限制)->all() $this->db->insert(表名,存储的数据) $this->db->where(条件)->update(表名,修改的数据) $this->db->update(表名,修改的数据,条件) $this->db->where(条件)->delete(表名) $this->db->delete(表名,条件)1、查询
一个查询$this->db->select()->from('tests')->where('level',2)->order('name','DESC')->limit(10,15)->all();最终执行的sql语句是这样的
select * from `tests` where level=2 order by name desc limit 10,15 对于where条件语句值得注意,你可以用三种形式构造你个查询条件(或简单或复杂) 1、where(field,value) 简单的就是两个值,field=value 2、where(field=>value,比较符,连接符) 多个条件的情况 3、where('field1=? and field2>?',['name',3]) 以statement的形式传递参数 举例如下:
$this->db->where([ ['name'=>'fantasy','=','and'], ['date'=>'12-01','>','or'], ['date'=>'12-31','<'], ]) 对应的SQL语句: where name='fantasy' and date>'12-01' or date<'12-31'
2、添加
添加数据就是 $this->db->insert(tablename,data) tablename 就是表名成,对于data是添加的数据,形如 [field1=>val1,field2=>val2,field3=>val3.....]。若要增加多条记录data需要是多维数组的形式[ [field1=>val1-1,field2=>val1-2,field3=>val1-3.....], // 第一条数据 [field1=>val2-1,field2=>val2-2,field3=>val2-3.....], // 第二条数据 [field1=>val3-1,field2=>val3-2,field3=>val3-3.....], // 第三条数据 [field1=>val4-1,field2=>val4-2,field3=>val4-3.....], // 第四条数据 ........ // 更多 ]
3、修改
更新数据 $this->update(tablename,data[,condition])tablename 要更新的表名称,data 更新的数据,更新的条件(这里可以不填,在$this->db->where() 处指明条件)。 数据部分的形式多为这样
data = [field1=>newValue1,field2=>newValue2,field3=>newValue3,.......]
4、删除
$this->delete(表名称,条件) or $this->where(条件)->delete(表名称)ORM
值得注意的是目前的ORM仅限于在model层使用,ORM的操作会让你的开发效率更上一层楼。当我们想要映射一张表的时候只需要在模型(model)的方法里这样写 $表的实例化对象 = $this->orm(表名称) 。我们创建这样一张表
字段名称 | 类型 | 注释 |
id | unsigned int | 记录id |
name | varchar(255) | 名称 |
varchar(255) | 邮箱 | |
addr | text | 地址 |
add_time | unsigned int | 添加记录的时间 |
ip | unsigned int | 用户的ip |
1、添加数据
public function testOrm(){ $tests = $this->orm('tests'); // 声明一个表的映射 $tests->name='orm'; // 赋值 $tests->email='orm@oa1024.com'; $tests->addr='jinhua'; $tests->add_time=time(); $tests->ip = sprintf('%u',ip2long('192.168.0.12')); var_dump($tests->add()); /// 调用add方法添加数据 成功返回true 失败返回false }
2、修改数据
$orm->save(条件) 这个条件跟非orm模式的条件格式一样。不同的是,为了安全起见,如果在更新的时候不想设置条件,需要在条件的部分填写false,否则方法返回false$tests = $this->orm('tests'); $tests->name = 'fantiq'; $tests->email = 'fantiq@163.com'; var_dump($tests->save(['id',1]));
3、删除
$orm->delete(条件) 条件跟save方法的用法一样。4、查询数据
ORM模块提供了方法的查询方法,满足您各种的查询需求。查询结果都是以对象的形式返回,默认是只去结果集的前20条的,你可以通过setLimit(...)来修改这个参数;查询条件中如果只传递一个只的话,框架会将这个值使用在表的主键字段上,默认的主键字段是 id ,你可以通过 setPrimaryKey 来修改这个参数。下面是ORM查询方面的方法: get([fields...]) 获取指定字段的所有数据 getOne([fields...]) 获取指定字段的一条数据 getWhere(条件) 根据条件查询数据 getBy(排序规则[order/group],排序字段) 对查询结果进行排序 getWhereBy(条件,排序规则,排序字段) 根据条件查询数据并根据排序规则将结果排序 setLimit() 修改limit的参数 setPrimaryKey() 设置主键模版
控制器调用模版
在控制器里面我们常用的是assign(key,val) 方法,对模版进行赋值,display([path]) 方法进行显示页面信息,若display指定参数则会调用指定路径的页面,若未指定这调用默认页面 项目/views/皮肤/控制器名称/方法名.模版后缀。 cache(时间min) 方法可以设置页面静态缓存,参数单位为分钟,表示缓存过期时间。public function index(){ $this->assign('name','fantasy'); $this->assign('lists',['fantasy','addr','time']); // $this->cache(1); // 一分钟的缓存 $this->display(); // $this->display('ad/main'); }
模版输出
你可以通过 setLeftTag() 、 setRightTag() 这些方法定义模版标签的界定符,默认是 "<{" 和 "}>" 。模版支持皮肤功能功能,你可以通过 setSkin() 方法切换皮肤,默认的皮肤是 'default' 。输出
<{变量名}> <!-- 这样会直接输出变量 -->
<{foreach $data->$val}> <!-- 遍历数字索引的数组 --> <{val}> <{/foreach}> <{foreach $data=$key->$val}> <!-- 遍历字符串索引的数组 --> <{key}>---><{val}> <{/foreach}>
<{if 判断条件}> <!-- 分支判断 --> .... <{else}> .... <{/if}>
模版功能
页面可被分为多个模块,可以通过模版提供的命令加载模版@@ layout 模版路径(不要写文件后缀) css css资源 js js资源 @@ layout 可以让你指定模版文件,然后当前模版的内容会填充到指定模版的位置( 指定模版的标签 <{tag-content}>)处。css 、js 会将指定的资源引用一并注入到模版中(模版中对应的标签是 <{tag-assets}>)。
组件
Session
框架中session的使用非常简单,你只需要 $this->session->start() session数据就加载成功并且能够提供给你使用了,并且框架会在最后更新数据并持久化存储,常用的方法有如下几种,使用非常简单: $this->session->set(key,val) 设置或修改session数据 $this->session->get(key) 获取session数据,若设置key值,则返回所有的session数据 $this->session->del(key) 删除一项session数据 $this->session->isOnline(user_id) 查询某个uid是否在线 $this->session->countOnline() 返回总在线用户数 值得注意的是你需要在配置文件中指明你需要存储session的数据库(mysql memcache redis),建议您使用memcache redis的内存型缓存数据库效率会高,mysql或者php文件型的存储在大访问量下过多的IO使项目效率下降。如若你使用php原生的session机制,可以直接使用 $_SESSION 数据进行操作。数据验证
框架提供了web应用中最常用的几个数据格式验证 ,你可以通过 $this->verify->验证函数(参数) 直接使用,下面列出这些方法以及用法1、字段不能为空
$this->verify->required(string $str); 方法会先过滤用户提交的不可打印的字符,其次过滤掉空格,最后检测是否是空字符串。2、邮箱格式验证
$this->verify->email(string $email) 内部采用的是php的过滤函数进行的验证,字符串太长(超过1000字符)也会返回false3、url链接格式验证
$this->verify->url(string $url) 由于php自带的验证不太灵活(不带协议会返回false),采取新的验证格式。4、ip地址验证
$this->verify->ip(string $ip) 采用php内部过滤函数的验证方法。5、身份证号码验证
$this->verify->id(string/int $id) 采用身份证的数据验证算法对身份证数字格式进行验证。6、手机号(中国)格式验证
$this->verify->phone(string/int $phone) 手机号码验证,目前只支持中国的手机号。7、数组验证
$this->verify->number(int/string number,int min,int max) 检测给定的数字是否在 min max的范围内,如果仅需要检测数字是否小于某个数只需要,$num=10;$this->verify->number($num,null,100) 这个是检测数字$num是否小于 100。8、检测字符串格式
$this->verify->string(string $str,string $rule) 其中$rule 可以是 alpha、num、zh 以及其他的。alpha表示仅允许字符串,num仅允许数字,zh仅允许汉字。若我们需要字符串允许数字级字母就要这样写 $rule = "alpha,num" $this->verify->string($str,"alpha,num")。若我们需要允许其他的字符只需要在$rule字符串后面跟上需要允许的字符并用 ',' 隔开即可。比如 $this->verify->string('fanyilong@sina.com','alpha,num,@,.') 这个将返回true9、检测字符串长度
$this->verify->len(string $str,int min,int max)10、检测是否存在一个列表中
$this->verify->in(mixed $var,string $lists) 变量 $lists 是一列数据的字符串,这些数据用 ',' 隔开。如同这样的数据 $lists = "android,iOS,linux,centos,windows"; 方法就是检测给定的数值是否存在于这个列中。11、匹配
$this->verify->match(mixed $var,string $field) 这个功能最常用在在注册的时候检测两次密码是否一致。$var 是值,$field是需要检测值是否一致的字段名称。配置
配置的用法最简单 当我我们想要获取某项值的时候 $this->config->get(key); 同样在需要设置修改某项值的时候 $this->config->set(key,val);HTTP数据
在web交互方面这个用的很频繁,但是又十分容易遭到攻击(XSS),框架最这些数据进行了初步的过滤并删除全局变量,防止在不正当的使用中导致攻击。 $this->request->get(key) 获取GET形式的数据 $this->request->post(key) 获取POST形式的数据 $this->request->cookie(key) 获取COOKIE数据 $this->request->files(key) 获取上传文件 $_FILES 数据 $this->setGet(key,val) 设置修改GET的某项数据 $this->setPost(key,val) 设置修改POST的某项数据 $this->setCookie(key,val) 设置修改COOKIE的某项数据工具
工具类组件中提供了丰富的类供您使用,您只需要 $upload = $this->utils->getUpload(); 就可以使用上传类了。其他的有图片,验证码,文件上传,分页,文件系统 等等...工具-上传文件
下面一段代码是文件上传,非常简单:public function upload(){ $upload = $this->utils->getUpload(); // 实例化上传组件 $config = [ // 设置配置项 'type'=>['txt','jpg','png','gif'], 'size'=>2048, 'path'=>'./uploads', 'rename'=>true ]; if($upload->run(field)){ // run(field,config) 开始上传 // 上传成功 返回成功相关信息(上传后的文件路径) print_r($upload->getInfo()); }else{ // 上传失败 获取失败信息 print_r($upload->getError()); } }配置部分: type =>[...] 指定允许的文件后缀;size=>2048 指定文件最大尺寸 单位是KB;path=>'./....' 指定上传文件的存储位置,注意这个文件夹要可写(chmod 777);rename=>true/false 是否将文件名重命名
工具-图片 / 验证码
同样通过 $img = $this->utils->getImage(); 实例化图片组件,这个组件主要有三个功能: captcha()生成验证码 ;thumb(缩放比例,保存路径,缩放参照)生成图片缩略图;crop()截取图片;验证码: $image->captcha(string $h,number $n,array $bg,array $color)
你可以参考源代码里面的代码示例 验证码示例参数列表:
$h 验证码的图片高度 $n 验证码字符数量 $bg 验证码图片背景色(rgb) $color 验证码字符颜色(rgb)图片缩放:$image->thumb(int $refer,string $savePath,int $order)
参数说明:
$refer缩放比例 $savePath处理后的图片保存路径 $order参照标准,0 参照宽度缩放,1 参照高度缩放图片截取:$image->crop(int $start_x,int $start_y,int $x_len,int $y_len,int $dst_w,int $dst_h,string $savePath)
$start_xx轴开始截取的位置 $start_yy轴开始截取的位置 $x_lenx轴截取长度 $y_leny轴截取长度 $dst_w粘贴到的图片宽度 $dst_h粘贴到的图片高度 $savePath图片保存地址工具-分页
使用分页工具的时候我们需要这样 $page = $this->utils->getPagination(int count,int listNum,int page) 解释下方法 getPagination的三个参数: count 要分页的数据的总条数 listNum 每页显示的数据的条数 page 要显示哪页的数据 每页显示的条数我们可以通过 $page->setListNum(int n) 来动态设置,也可以在配置文件中设置['application'=>[ ..... 'page_lists'=> 每页显示的条数, .... ] ]分页中的数据在技术上是反映在sql语句的limit部分的参数的写法,这个分页类通过计算为你提供的这些参数,$page->getStart() 返回limit要开始的位置,$page->getLimitNum() 返回取出显示的条数,在使用中就是下面这样:
public function list($p=1){ $page = $this->utils->getPagination($count,$listNum,$p); sql..... limit .$page->getStart.','.$page->getListNum(); // 或者 用getLimit() 方法,这个方法直接返回的是limit参数的组合 sql..... limit $page->getLimit(); } 下面是前端框架的分页css的一个示例: 上一页 1 2 3 4 5 下一页
工具-文件
版权声明:
1、该文章(资料)来源于互联网公开信息,我方只是对该内容做点评,所分享的下载地址为原作者公开地址。2、网站不提供资料下载,如需下载请到原作者页面进行下载。
3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考学习用!
4、如文档内容存在违规,或者侵犯商业秘密、侵犯著作权等,请点击“违规举报”。