Simple PHP
简单、干净的php框架
author simple
email gavin6487@gmail.com
version 0.6
changed 2017年07月15日
Explanation
* 重新定义目录结构
* 框架独立目录
* CLI模式支持
* 环境变量对应config子目录功能
* model模型修改
感谢kohana/swoole/thinkphp框架,参考借鉴了许多代码及思路
按目录区分,目录及文件名全部小写
namespace首字母大写
目录 namespace
app App
app\controllers App\Controllers
app\models App\Models
simple Simple
app 项目目录 此目录可移动至任意目录作为独立app项目,需要修改app/index.php
business 业务逻辑层,讲复杂的业务逻辑在此封装,controller总调用此层进行逻辑处理,此层调用model或直接使用DB build进行数据变更
classes 项目特殊定义的class文件目录
configs 配置文件目录
dev 环境变量设置为dev时的配置文件陌路
database.php dev模式下数据库配置文件
database.php 默认环境数据库配置文件
cookie.php cookie配置文件
redis.php redis配置文件
session.php session配置文件
controllers controller
htdocs 静态文件目录及入口文件目录
index.php 入口文件
models 模型文件 一个表对应一个model
views 模板文件
router.php 项目Route自定义
simple 框架
build sql build相关目录
delete.php delete相关SQL
insert.php insert相关SQL
select.php select相关SQL
update.php update相关sql
controller controller相关目录
ajax.php 只用ajax的controller基类
cli.php 脚本运行的基类
template.php 使用模板的controller基类
session session相关目录
mysql.php 使用mysql存储session
redis.php 使用redis存储session
arr.php 常用数组操作
build.php 构造SQL基类 build目录下所有类均继承于此类
config.php 配置文件读取
controller.php controller基类
cookie.php cookie封装
curl.php curl封装
db.php 数据库类
error.php 异常类 TODO 分DB异常和默认异常
http.php response
orm.php 对象关系映射 TODO 完善
redis.php redis封装
route.php 路由
session.php session封装
simple.php 框架核心文件
view.php 模板
index.php 框架入口文件
server {
listen 80;
server_name simple.com;
root /data/www/vhost/simple/app/htdocs/;
index index.php index.html;
access_log /data/logs/nginx/simple.log main;
location / {
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php;
}
}
location ~ \.php$ {
client_max_body_size 128m;
proxy_set_header X-Real-IP $remote_addr;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
#以下默认的welcome和index可以通过route进行配置
url file->function
http://your_host/ app/controllers/welcome.php->action_index()
http://your_host/abc app/controllers/abc.php->action_index()
http://your_host/abc/def app/controllers/abc.php->action_def()
http://your_host/abc/def/123 app/controllers/abc.php->action_def(123)
#需要cli执行的脚本,请继承于\Simple\Controller\Cli 或 在脚本头部判断php_sapi_name
#cd app/htdocs/
shell file->function
#php index.php app/controllers/welcome.php->action_index()
#php index.php abc app/controllers/abc.php->action_index()
#php index.php abc/def app/controllers/abc.php->action_def()
#php index.php abc/def/123 app/controllers/abc.php->action_def(123)
DEBUG bool 调试模式开关,为真时会输出相关错误信息
CFG_PATH string config子目录环境变量,设置后会优先从configs/CFG_PATH/中读取config文件
APP_PATH string app所在目录
SYS_PATH string simple框架核心文件所在目录
PUB_PATH string 框架入口文件所在目录
CLI_MODE bool 是否是CLI模式执行
[1. 框架独立]
将simple目录及index.php[框架入口文件]存放至某独立目录中
eg: /data/public/framework
[2. 项目目录独立]
将app目录完整move/copy至项目所在目录
eg: /data/webroot/test/
[3. 初始化]
修改app/htdocs/index.php
debug 调试模式开关
CFG_PATH 自定义环境变量,用于config子目录,不需要请设置为空字符串
eg: define('CFG_PATH', 'dev');
此时框架会默认从configs/dev/目录下优先读取配置文件,不存在则从configs目录下读取
修改框架入口文件的真实路径
eg: require_once '/data/public/framework/index.php';
[4. 设置路由规则]
修改app/router.php自定义路由规则
不需要自定义请清空文件或删除
[5. DB初始化]
修改configs/database.php 如设置了CFG_PATH,则需要修改configs/CFG_PATH/database.php
eg:
return [
'master' => [
'hostname' => 'localhost',
'username' => 'root',
'database' => 'simple',
'password' => '',
'pconnect' => FALSE,
'charset' => 'utf8mb4',
],
'slave' => [
'hostname' => 'localhost',
'username' => 'root',
'database' => 'simple_test',
'password' => '',
'pconnect' => FALSE,
'charset' => 'utf8mb4',
],
];
此时
DB::instance()->query($sql)
ORM::facotry(table_name)->add($data)
等相关DB操作,会默认读取此配置文件中的master节点的库
如需要访问slave节点的库,则
DB::instance('slave')->query($sql)
ORM::facotry('slave.table_name')->add($data)
Model类需要设置$_table = 'slave.table_name'
[6. Redis初始化]
修改configs/redis.php 如设置了CFG_PATH,则需要修改configs/CFG_PATH/redis.php
eg:
return [
'ip' => '127.0.0.1',
'port' => '6379',
];
[7. Session初始化]
修改configs/session.php 如设置了CFG_PATH,则需要修改configs/CFG_PATH/session.php
eg:
return [
'mode' => 'redis', //mysql or redis
'mysql' => [
'name' => '_session_id',
'table' => 'sessions',
'gc' => 500,
'columns' => [
'session_id' => 'session_id',
'last_active' => 'last_active',
'contents' => 'contents',
],
'expire' => 2592000, //30 day
],
'redis' => [
'name' => '_session_id',
'prefix' => 'SESSION_',
'expire' => 2592000, //30 day
],
];
session支持两种模式存储mysql/redis
mode值用来定义当前选择哪种模式存储
mysql节点用来配置mysql存储时的信息
name cookie名
table 表名
gc 触发回收概率
columns 字段名
expire session过期时间
redis节点用来配置redis存储时的信息
name cookie名
prefix redis存储中的前缀
expire 过期时间
session具体使用方式请参看[常用操作/Session]部分
[8. model初始化]
一个model对应一张表
eg: users表,主键是uid
则创建models/users.php 名字可自定义,需要配置$_table(表名)和$_pk(主键名)的值
<?php
namespace App\Models;
use Simple\Model;
class Users extends Model
{
public $_table = 'users';
public $_pk = 'uid';
}
//使用
//获取一个uid=3的object
$model = Users::factory(3);
//修改该model的值,并使之同步到数据库 接上述
$model->name='abc';
$model->save();
//获取一个空的object
$model = Users::factory();
//新增一条数据 接上述
$model->uid=3;
$model->name='def';
$model->add();
//查询并返回一个object 此时model==一开始获得的有值的model
$model = Users::factory()->where(['name' => ['LIKE', '%abc%'])->find();
//查询并返回一个object的集合
$model_list = Users::factory()->where(['name' => ['LIKE', '%abc%'])->find_all();
foreach ($model_list as $model)
{
//$model == 一开始获得的有值的model
}
[9. Controller建立]
在controllers目录下创建welcome.php
创建方法action_index
此时当用户访问http://your_host/或http://your_host/welcome/index时,会调用此方法执行
[10. 使用View]
//如果该controller继承了Simple\Controller\Template
//设置变量
$this->bind('title', 'this is title');
//绑定模板文件 app/views/welcome/index.php
$this->template = 'welcome/index';
//输出
$this->display()
//模板文件中可以直接使用$title得到您绑定的变量
[数组操作]
use \Simple\Arr;
//$row = isset($array['test']) ? $array['test'] : false;
$row = Arr::get($array, 'test', false);
[DB Build]
use \Simple\Build\SELECT;
//查找articles表中,id=3的一条数据
SELECT::table('articles')->where(3)->find();
//查找articles表中,id!=3且type=1的一条数据
SELECT::table('articles')->where(['id' => ['!=', 3], 'type' => 1])->find();
//查找slave DB中的articles表中,id in (1, 2, 3)且type=1的所有数据,按id ASC排序,获取从第五条开始的10条数据 WHERE条件中的IN/NOT IN/BETWEEN必须为大写
SELECT::table('slave.articles')->where(['id' => ['IN', [1, 2, 3]], 'type' => 1])->order(['id' => 'ASC'])->limit(5, 10)->find_all();
use \Simple\Build\UPDATE;
//修改articles表中,id=3的数据,修改title为new_title,content为new_content SELF::INC自增 SELF::DEC自减 SELF::*2自乘2
UPDATE('articles')->where(3)->save(['title' => 'new_title', 'content' => 'new_content', 'read_count' => 'SELF::INC']);
use \Simple\Build\INSERT;
//新增
$id = INSERT::table('articles')->add(['title' => 'new_title', 'content' => 'new_content']);
//新增一批
$first_id = INSERT::table('articles')->add([['title' => 'new_title1', 'content' => 'new_content1'], ['title' => 'new_title2', 'content' => 'new_content2']]);
use \Simple\Build\DELETE;
//删除
DELETE::table('articles')->where(3)->del();
[Config操作]
use \Simple\Config;
//读取database文件
$database = Config::get('database');
//读取database.php中的master节点
$master = Config::get('database.master');
//只支持以上两种方式 不支持三级节点
[Controller]
//在继承于controller中使用 以下三个函数后两个参数可省略
//获取$_GET['user_id']值,并用intval函数过滤,如果$_GET['user_id']不存在,则返回0
$this->_get('user_id', 'intval', 0);
//获取$_POST['nickname']值,并用trim过滤空格,如果$_POST['nickname']不存在,则返回none
$this->_post('nickname', 'trim', 'none');
//不限制是post或get,有限读post
$this->_r('abc', 'trim', 0);
//在继承于controller\template中使用
//指定模板文件为 app/views/welcome/abc.php 不设置则默认为app/views/controller名/action名.php
$this->_template = 'welcome/abc';
//绑定变量 支持以下两种方式绑定 可在模板中直接使用$title $body获取该值
$this->bind('title', 'this is title');
$this->bind([
'title' => 'this is title',
'body' => 'this is body',
]);
//跳转
$this->redirect('www.qq.com', 301);
[Curl操作]
use \Simple\Curl;
/*默认的curl option值
[
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_SSL_VERIFYHOST => FALSE,
CURLOPT_AUTOREFERER => FALSE,
CURLOPT_HEADER => FALSE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_FOLLOWLOCATION => TRUE,
CURLOPT_CONNECTTIMEOUT => 3,
CURLOPT_TIMEOUT => 3,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.1 (KHTML, like Gecko) Chrome/6.0.440.0 Safari/534.1',
CURLOPT_ENCODING => 'gzip,deflate',
CURLOPT_HTTPHEADER => ['Connection: Keep-Alive'],
];*/
//GET
$obj = Curl::factory('http://www.baidu.com')->get([
'id' => 1,
'abc' => 'def',
]);
//POST
$obj = Curl::factory('http://www.baidu.com')->post([
'id' => 1,
'abc' => 'def',
]);
//传递的参数不需要build
$obj = Curl::factory('http://www.baidu.com')->post('id=1&abc=def', false);
//设置referer
$obj = Curl::factory('http://www.baidu.com')->referer('www.qq.com')->post('id=1&abc=def', false);
//设置cookie
$obj = Curl::factory('http://www.baidu.com')->referer('www.qq.com')->cookie('/data/www/abcdef.cookie')->post('id=1&abc=def', false);
//设置代理
$obj = Curl::factory('http://www.baidu.com')->referer('www.qq.com')->proxy('127.0.0.1', '8080')->post('id=1&abc=def', false);
//获取正文
$body = $obj->body();
//获取返回头
$header = $obj->header();
//省心缩写
$body = Curl::factory('http://www.baidu.com')->post([
'id' => 1,
'abc' => 'def',
])->body();
//手写curl option调用
$result = Curl::single($option);
//并发调用
$options = [$option1, $option2, ... ]
$result = Curl::multi($options);
[Cookie操作]
use \Simple\Cookie;
//增/改
Cookie::set('abc', 'hahaha');
//查
$a = Cookie::get('abc');
//删
Cookie::delete('abc');
//清空
Cookie::clear();
[DB操作]
use \Simple\DB;
//操作master
//执行sql
$query = DB::instance()->query($sql);
//获取一条结果集 数组
$row = DB::instance()->fetch($query);
//获取所有返回值 数组
$list = DB::instance()->fetch_all($query);
//获取插入数据的insert_id
$insert_id = DB::instance()->insert_id();
//数据过滤 real_escape_string
$value = DB::instance()->check($value);
//操作slave
$query = DB::instance('salve')->query($sql);
[HTTP操作]
use \Simple\HTTP;
//设置一条header
HTTP::instance()->header($key, $value);
//设置返回状态码
HTTP::instance()->status(404);
//跳转某url
HTTP::instance()->redirect('www.qq.com');
//输出json并结束 会自动将data转为json格式
HTTP::instance()->ajax($data);
//输出正文并结束
HTTP::instance()->finish($data);
[Model操作]
//创建test.php extends ORM,并设置$table='test',$pk='id'
//获取一个uid=3的object
$model = Users::factory(3);
//修改该model的值,并使之同步到数据库 接上述
$model->name='abc';
$model->save();
//获取一个空的object
$model = Users::factory();
//新增一条数据 接上述
$model->uid=3;
$model->name='def';
$model->add();
//查询并返回一个object 此时model==一开始获得的有值的model
$model = Users::factory()->where(['name' => ['LIKE', '%abc%'])->find();
//查询并返回一个object的集合
$model_list = Users::factory()->where(['name' => ['LIKE', '%abc%'])->find_all();
foreach ($model_list as $model)
{
//$model == 一开始获得的有值的model
}
[Redis操作]
use \Simple\Redis;
//获取
Redis::instance()->get($this->_prefix.$this->_session_id);
[Route操作]
use \Simple\Route;
在app/init.php中配置路由
//访问www.simple.com时进入welcome controller和action_index
Route::add('', [
'controller' => 'welcome',
'action' => 'index',
]);
//访问www.simple.com/index时,进入welcome controller中的action_index方法
Route::add('index', [
'controller' => 'welcome',
'action' => 'index',
]);
//访问www.simple.com/articles/1234类似的网址,进入articles controller的action_detail方法,并传入参数1234
Route::add('articles/(\d+)', [
'controller' => 'articles',
'action' => 'detail',
'param' => ':1',
]);
//自定义404 当404时,使用welcome controller中的action_404方法处理
Route::set_404('welcome', '404');
[Session操作]
use \Simple\Session;
//增/改
Session::instance()->set('abc', 'edf');
//查
Session::instance()->get('abc');
//删
Session::instance()->delete('abc');
//清空
Session::instance()->clear();
[VIEW操作]
use \Simple\View;
//绑定变量
View::bind('test', $abc);
//绑定数组 按key区分变量
View::bind([
'test' => $abc,
'title' => $title,
]);
//输出模板app/views/index.php
View::display('index');
##压测结果
#php7环境下,2.5GHZi7 16G内存 未开启opcache
#siege -c 500 -t 5s http://test/
Lifting the server siege...
Transactions: 7748 hits
Availability: 92.69 %
Elapsed time: 4.97 secs
Data transferred: 0.09 MB
Response time: 0.01 secs
Transaction rate: 1558.95 trans/sec
Throughput: 0.02 MB/sec
Concurrency: 15.78
Successful transactions: 7748
Failed transactions: 611
Longest transaction: 0.18
Shortest transaction: 0.00