zubapita / min
Min - PHP的最小化INter框架
Requires
- php: >=5.5
- apache/log4php: 2.3.0
- hybridauth/hybridauth: 2.5.0
- j7mbo/twitter-api-php: dev-master
- jstayton/google-maps-geocoder: dev-master
- nesbot/carbon: ~1.18
- php-console/php-console: 3.*
- phpoffice/phpexcel: 1.8.1
- smarty/smarty: v3.1.21
- sonrisa/shorturl-service: dev-master
- validator/livr: dev-master
- verot/class.upload.php: dev-master
Requires (Dev)
- fzaninotto/faker: v1.5.0
- phpunit/phpunit: 4.8.10
- phpunit/phpunit-selenium: 1.4.2
This package is not auto-updated.
Last update: 2024-09-28 19:09:30 UTC
README
PHP的最小化INter框架
这是什么?
这是一个针对PHP 5.5以上版本的Ajax Web应用开发框架,旨在最小化开发时的努力。
- 最小化编码工作量:自动生成代码和测试。同时最小化开发者需要编写的代码量。
- 最小化学习工作量:通过结合现有的标准类库和工具,减少学习新框架或工具的难度。
- 最小化试错工作量:通过将测试工具和调试工具集成到框架中,使问题更容易把握。
- 提供简单、可靠的方法,以实现JQuery和PHP之间的通信,从而简化Ajax Web应用的开发。
- 所有数据库的CRUD操作都是Ajax。
- 与Google Chrome的PHP-Console结合使用,可以简化Ajax应用的调试工作。
- 采用Bootstrap 3进行设计。Bootstrap 3模板也易于应用。
- 内置自定义认证库,可以安全、简单地创建登录表单。
使用类库
min使用了以下类库。
- "smarty/smarty":模板类
- "validator/livr":验证类
- "php-console/php-console":Google Chrome的console输出调试类
- "apache/log4php":将执行日志记录到文件的类
- "hybridauth/hybridauth":通过Twitter、Facebook等进行的OAuth认证类
- "verot/class.upload.php":处理上传图像的类
- "phpoffice/phpexcel":操作Excel工作表的类
- "nesbot/carbon":日期时间数据操作类
开发时还使用了以下工具。
- "phpunit/phpunit":测试框架
- "phpunit/phpunit-selenium":Web浏览器测试框架
- "fzaninotto/faker":生成假数据的类
推荐环境
- PHP 5.5+
- Composer
- 操作系统:Mac OS X或Linux
- 网络浏览器:Google Chrome
- 文本编辑器:TextMate或Sublime Text
Windows的使用尚未经过验证。
安装
1. 使用Composer进行安装
$ composer create-project zubapita/min [项目名] -s dev
2. 下载ZIP文件或克隆仓库
创建新的min应用(项目)
$ ./makeNewApp.php -a testApp -r /Users/mydir/workspace
创建新的Min应用。
创建应用:testApp。父路径=/Users/mydir/workspace
请在新的应用根目录下运行'composer install'。
在'/Users/mydir/workspace/testApp'创建,并复制必要的文件。移动到应用程序目录,并使用Composer安装必要的库。
$ cd /Users/mydir/workspace/testApp
$ composer install
应用程序创建步骤
提示
bin以下有应用程序创建和使用的命令集。
不添加参数执行时,将显示使用说明。
$ cd bin
$ ./makeNewApp.php创建新的Min应用。
用法:./makeNewApp.php -a [应用名称] -r [根目录名称(可选)] ex)/Users/user/workspace
创建数据库模型
Min默认使用PDO覆盖的独立类使用数据库。 (当然,你也可以安装并使用自己喜欢的数据库类) 要使用此独立数据库类,需要
- 数据库类
- 各表的类
- 操作各表的模型类 需要分别通过命令自动生成。
创建数据库类
创建MySQL数据库「test」的类
- 用户名:testuser
- 密码:gh67L*K0的情况下,
$ ./makeDbClassFile.php -d test -s mysql -u testuser -p gh67L*K0
类文件将
- 创建在model/_def/db/test.php中。
创建表的类
- 创建数据库「test」中所有表的类。
./makeTableClassFiles.php -d test
类文件将
-
创建在model/_def/db/test/以下。
-
创建数据库「test」的表「users」的类。
./makeTableClassFiles.php -d test -t users
类文件将
- 创建在model/_def/db/test/users.php中。
创建表的模型
- 创建操作数据库「test」的表「users」的模型类。
$ ./makeModelClassFiles.php -d test -t users
类文件将
- 创建model/test/UsersList.php
- 创建model/test/UsersRecord.php
model/test/UsersList.php是用于从users表获取列表数据和搜索结果的类。
使用示例:
$UsersList = new UsersList(); $list = $UsersList->get(); var_dump($list);
model/test/UsersRecord.php是用于向users表插入、更新、删除数据的类。
使用示例:
$data['id'] = 1; $data['name'] = "Tom"; $data['birthday'] = "2001-10-15";
$UsersRecord = new UsersRecord(); $UsersRecord->set($data);
$data = $UsersRecord->get("id=1"); var_dump($data); $data['name'] = "Tom Cat"; $UsersRecord->set($data);
model/_def/db/test/users.php中定义了键列的默认值,默认情况下id列是键。如果不更改id列,只更改其他列的值并执行set(),则会更新行。如果id是表中不存在的值,则会插入行。
调整验证
如果使用模型插入数据不顺利,请检查记录模型(如model/test/UsersRecord.php等)的验证设置。 默认情况下,所有列都设置了['required'](必需)。
请参考以下验证规则。 https://github.com/koorchik/LIVR
模型测试
自动生成模型类文件时,同时会在test/model目录下创建phpunit用测试文件。
以books表为例,
- test/model/books/BooksListTest.php(BooksList类的测试)
- test/model/books/BooksRecordTest.php(BooksRecord类的测试)的2个文件将被创建。
如果已安装phpunit,则可以通过以下命令行进行测试(需要通过phpunit提供执行路径)。
$ phpunit BooksListTest.php
$ phpunit BooksRecordTest.php
但是,BooksRecordTest.php如果直接进行测试将报错。
内部有设置向表中插入数据的dataProvider()方法,因此请调整以输出适当的插入用数据。
创建Web视图和控制台
前提:假设这个Web应用的URL是http://test.mysite.jp/。
另外,为了作为Web应用运行,请参考etc/local_vh.conf来设置VirtualHost。
基本上,需要将htdocs设置为DocumentRoot,然后include etc/rewrite.conf 就可以运行了。
另外,请确保apache能够写入var/compiled。
基本
要创建视图和控制器,请使用 makeNewCtlAndView.php,使用 -m 指定模型名,使用 -p 指定页面名。
创建用于在表格内显示或搜索数据的视图和控制器
$ ./makeCtlAndView.php -m UsersList -p users
控制器类文件将
- 创建在 controller/users/usersCtl.php。
视图模板将
- 创建在 view/users/index.html。
模板使用Smarty规则编写。
并且表格显示的部分在 view/users/includes/ 内。
这个页面可以通过
创建用于在表格中插入或更新数据的视图和控制器
$ ./makeCtlAndView.php -m UsersRecord -p users/record
控制器类文件将
- 将创建在 controller/users/record/usersRecordCtl.php。
视图模板将
- view/users/record/index.html
- view/users/record/add.html
- view/users/record/edit.html。
模板使用Smarty规则编写。
另外,表单显示的部分在 view/users/record/includes/ 内。
这些页面可以通过
- http://test.mysite.jp/users/record/
- http://test.mysite.jp/users/record/add.html
- http://test.mysite.jp/users/record/edit.html 访问。
创建不使用表格的视图和控制器
$ ./makeCtlAndView.php -p about
控制器类文件将
- 将创建在 controller/about/aboutCtl.php。
视图模板将
- view/about/index.html。
模板使用Smarty规则编写。
这个页面可以通过
- 可以通过
http://test.mysite.jp/about/ 访问。
控制器测试
- 创建控制器后,将自动在 test/controller 目录下创建 PHPunit-selenium 的测试文件。
- 例如,对于 UsersCtl:将在 test/controller 目录下创建 /users/UsersCtlTest.php
移动到 test/controller/users
$ phpunit UsersCtlTest.php
即可进行测试(需要通过phpunit执行路径安装selenium-server和chromedriver)。请根据需要修改测试文件的内容。
数据库操作
min内置了具有以下特性的自定义数据库操作类。
- 基于PDO,因此速度快。
- 在描述表操作时,内部将自动生成使用PDO的数据操作SQL,并使用PDO操作数据库。SQL注入防护且安全。
- 如果决定了表上的唯一键,则可以自动判断插入和更新。
- 使用方法链进行智能的描述。
表格操作的基本
前提:假设在数据库“testDB”中有以下结构的表格“books”。
实例化此books表格,然后执行表格操作。
CREATE TABLE
books(
idint(11) unsigned NOT NULL AUTO_INCREMENT,
titlevarchar(50) DEFAULT NULL,
authorvarchar(50) DEFAULT NULL,
isbnvarchar(14) DEFAULT NULL,
priceint(11) DEFAULT NULL,
releaseDatedatetime DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
获取表格实例
$_ = $this;
$->DB = $->getDB('testDB');
$->Books = $->getTable($_->DB, 'books');
$_->Books将包含books表格的实例。
向表格插入行
$_ = $this;
$bookData = [
'title' = '哈姆雷特',
'author = '莎士比亚',
'isbn' = '978-4102020036',
'price' = 497 , 'releaseDate' = '1967/9/27' , ];
$result = $_->Books->saveSet($bookData);
从表格获取行并更新
获取title为'哈姆雷特'的行。
$_ = $this;
$columns = [
'id',
'title',
'author',
'price',
];
$condition = ['title'=>'哈姆雷特'];
$bookData = $_->Books->select($columns)->find($condition)->fetch();
$bookData将包含结果行。
$bookData['author'] = '威廉·莎士比亚';
$result = $_->Books->saveSet($bookData);
取得行的author列被替换。
默认情况下,id列是唯一键,因此要更新行,需要获取id列。
唯一键的设置在 model/_def/(DB名)/(表格名).php 内描述,可以根据需要修改。
从表格获取所有行
$_ = $this;
$columns = [
'id',
'title',
'author',
'price',
];
$condition = [];
$bookDataRows = $_->Books->select($columns)->find($condition)->fetchAll();
如果想要一行一行地获取,请使用 getRows()。
$rows = $_->Books->select($columns)->find($condition)->getRows();
while ($row = $rows->fetch(PDO::FETCH_ASSOC)) {
var_dump($row);
}
getRows()返回PDOstatement,因此之后可以使用PDO的方法进行操作。
描述搜索条件
搜索条件(Where子句的条件)作为find()的参数指定。
$bookDataRows = $_->Books->select($columns)->find($condition)->fetchAll();
在参数$condition中描述,可以按照以下方式使用字符串或数组。
- 字符串
$condition = "title='哈姆雷特'";
$condition = "price>300";
- 数组
$condition = ['title'=>'哈姆雷特'];
$condition = ['title'=>['opr'=>'=', 'val'=>'哈姆雷特']];
$condition = ['price'=>['opr'=>'>', 'val'=>300]];
多列的AND搜索(不支持OR搜索)
$condition = [
'author'=>['opr'=>'=', 'val'=>'莎士比亚'],
'price'=>['opr'=>'<', 'val'=>1000]
];
BETWEEN也可以使用。
$condition = ['price'=>['opr'=>'BETWEEN', 'MIN'=>300, 'MAX'=>1000]];
1.的字符串描述简单,但在生成SQL时,条件会被直接用于Where子句,没有生成占位符,因此建议不要使用,以免危险。
limit、offset、order by
$_ = $this;
$columns = [
'id',
'title',
'author',
'price',
];
$->Books->select($columns);
$->Books->offset(0)->limit(10)->orderBy('price DESC');
$condition = [];
$_->Books->find($condition)->fetchAll();
使用ORDER BY指定多个列时,请按照以下方式指定。
1. 字符串
$order = 'price DESC, title ASC';
$_->Books->orderBy($order);
2. 数组
$order = ['price DESC', 'title ASC']; $_->Books->orderBy($order);
GROUP BY
$_ = $this;
$columns = [
'id',
'title',
'author',
'price',
];
$_->Books->select($columns);
$_->Books->groupBy('author');
$condition = [];
$_->Books->find($condition)->fetchAll();
使用GROUP BY指定多个列时,请按照以下方式指定。
1. 字符串
$group = 'author, price';
$_->Books->groupBy($group);
2. 数组
$group = ['author', 'price'];
$_->Books->groupBy($group);
JOIN
$_->Sales = $_->getTable($_->DB, 'sales');
$_->Books->join($_->Sales)->on('books.isbn=sales.isbn');
INNER JOIN的情况下
$_->Books->innerJoin($_->Sales)->on('books.isbn=sales.isbn');
通过模型进行数据库操作
使用makeModelClass.php可以生成操作表的两个模型类。
- DataList类
- DataRecord类
DataList类
用于获取表内列表或搜索结果的类。
如果表名为books,则生成BooksList类,并在BooksList.php内生成。
在控制器中使用时
$BookList = new BookList();
这样写。根据需要,类文件将被自动加载。
- get($conditions, $currentPage)
从表中获取列表并将其以数组形式返回。如果没有获取结果,则返回0。
最大获取行数默认为10。
@param (array|string) $conditions 使用字符串或数组指定搜索条件。
@param integer $currentPage 指定表格内全行数除以最大获取行数的数字。
当最大获取行数为10时,要获取第11行至第20行,则$currentPage=2。
- setMaxItemsInPage($maxitems)
设置最大获取行数。
@param integer $maxitems 最大获取行数
- getMaxItemsInPage()
返回当前最大获取行数。
DataRecord类
用于对表进行行操作、插入、更新的类。在插入和更新时,还会执行验证。
如果表名为books,则生成BooksRecord类,并在BooksRecord.php内生成。
在控制器中使用时
$BookList = new BookList();
这样写。根据需要,类文件将被自动加载。
- get($conditions)
从表中获取相应的行并返回。
@param (array|string) $conditions 使用字符串或数组指定搜索条件。
- set($data)
将行保存到表中。如果没有指定唯一键或指定了但表中不存在,则插入新行。如果唯一键存在于表中,则更新。
利用内置功能
安装登录表单
etc/template/set/auth 以下包含用于执行用户认证和Twitter、Facebook的OAuth认证的一套工具。
要使用它,首先需要准备用于保存用户认证的数据库,并执行bin/install.php。
如果使用mysql创建名为“mindb”、用户名为“mindb”、密码为空的数据库
$ cd bin
$ ./makeDbClassFile.php -d mindb -u mindb -s mysql
$ cd etc/template/set/auth/bin
$ chmod +x install.php
$ ./install.php -d mindb
这样,所需的模型、视图、控制器的一套都将保存,并可以使用默认头部中的“登录”菜单。
但使用OAuth认证需要获取Twitter或Facebook的API密钥,并将API密钥设置到model/_def/api/下的TwitterApiKey.php等文件中。
安装图片Ajax上传
etc/template/set/uploadImg 以下包含执行图片Ajax上传的一套工具。
要使用它,只需执行bin/install.php即可安装执行图片上传的控制器和视图的套件(不使用模型)。
默认页面名为uploadImg,但可以使用-p 页面名指定页面名。
要将URL设置为http://mydomain/imageupload/,请按以下方式指定。
$ cd etc/template/set/uploadImg/bin
$ chmod +x install.php
$ ./install.php -p imageupload
上传的图片将保存在var/images/uploaded以下。
图片的显示方式为。要将uploaded部分替换掉,请在内置控制器中更改。
但/img/不可用。如果图像路径包含/img/,则自动将htdocs以下的图像文件作为显示目标。这是在etc/rewrite.conf中设置的。
var/images是固定的,但如果要更改,请在lib/Dispatch.php中的sendImage()中进行更改。可显示的图像扩展名是jpeg、JPEG、jpg、JPG、png、PNG、gif、GIF。如果要更改,请在lib/Dispatch.php中的setPathAndAction()中进行更改。
目录结构
- bin
放置应用程序创建使用的各种批处理命令的位置。此外,还有创建批处理命令的模板。 - contoroler
放置Web应用程序控制器的位置。控制器从index.php的端点启动。 - etc
放置各种设置文件的位置。 - htdocs
文档根目录。放置图像文件、favicon、robots.txt等静态文件的位置。
htdocs/index.php是Web应用程序的起点(端点)。URL相应地启动各个控制器。
图像文件应放在htdocs/img/*或htdocs//img/下。此规则可在etc/rewrite.conf中设置。 - lib
放置min操作所需类库的位置。 - model
放置操作数据库的模型类的位置。将数据库之外的api操作或Excel操作也模型化,并放置在此处。模型内的数据库操作通过自定义的数据库操作类实现,无需编写SQL即可简单地编写操作。 - test
放置测试文件的位置。 - var
放置临时文件的位置。
var/compiled放置编译后的视图模板的php。 - vendor
放置由composer安装的各种类库的位置。 - view
放置HTML文件的位置。
view/index.html是顶级页面的HTML。
HTML是Smarty的模板文件。Smarty是支持if〜else语句的条件分支、循环(如foreach)等、变量计算或赋值等的高功能模板类。
在min中,大部分的显示编程使用Smarty和JQuery进行。
安全措施
在框架级别上实施以下安全措施。
防止跨站脚本攻击(XSS)
在所有控制器的构造函数中默认设置了Samrty的escape_html过滤器。
$_->view->escape_html = true;
因此,所有Smarty变量的输出都会进行HTML转义。
如果要禁用转义,请在输出变量时指定nofilter。
{$变量名 nofilter}
防止SQL注入
内置数据库操作类使用PDO的占位符。
这样可以禁用多语句执行等。
输入字符串的转义
为了接收外部输入,准备了以下5个方法代替$_GET和$_POST。
- getGETNumValue('变量名', [默认值]) // 从$_GET['变量名']获取数值。如果不是数值或不存在,则返回默认值。
- getGETStrValue('变量名', [默认值]) // 从$_GET['变量名']获取字符串。字符串会被HTML转义。如果不存在,则返回默认值。
- getPOSTNumValue('变量名', [默认值]) // 从$_POST['变量名']获取数值。如果不是数值或不存在,则返回默认值。
- getPOSTtrValue('变量名', [默认值]) // 从$_POST['变量名']获取字符串。字符串会被HTML转义。如果不存在,则返回默认值。
- getPostedData(boolean $raw=false) // 将$_POST作为一个数组返回。如果不指定$raw为true,则值会被HTML转义。此外,在非生产环境(即开发时)为了便于调试,返回$_REQUEST而不是$_POST(即不仅可以测试POST,还可以测试GET)。
防止跨站请求伪造(CSRF)
默认生成的Ajax POST每次都会嵌入令牌以判断连接来源。
生成令牌时使用openssl_random_pseudo_bytes()。
会话劫持防护
内置登录认证类在登录时执行session_regenerate_id()以重新生成会话ID。
安全密码保存
内置登录认证类使用password_hash()进行密码哈希化。
安全文件上传
内置的Ajax文件上传不会将上传的文件放置在公开目录中。
以下为更新计划