PHP开发框架比较

Laravel 是一个简单优雅的 PHP WEB 开发框架,将你从意大利面条式的代码中解放出来。通过简单、优雅、表达式语法开发出很棒的 WEB应用!
但是通过使用我们发现Laravel在开发效率和运行效率上都存在瓶颈。如此优秀的框架都存在诸多问题,基于此我们在公司现有框架的基础上参照诸多框架(不限于php语言也参照java和ruby)的优点完成一个自主设计的框架。
自此,YYUC框架的开发团队征集并完成组建,不断的讨论、编码、测试、内部开发和合作伙伴推广;一个完整的版本就此形成。

特性

codeigniter

laravel

YYUC

比较

路由规则

约定加自定义,视图需要手工指定。

约定加自定义,视图需要手工指定。

约定加自定义。

不利用配置文件的路由规则就可以自由的构建URL格式,一般的路由约定是:

/方法/参数,这种约定不够灵活,YYUC的路由实现上可以更灵活。

laravel的统一分发虽然使路由的定义更加灵活的,但是个人觉得没必要。只要层次设计好有利于SEO和用户感官就好,没有必要独立定义。Laravel3之前开发和维护过程中查着路由表找控制器累不累啊。Laravel3之后解决了这个问题,有了自动路由的方法:Route::controller(Controller::detect());

类加载

手动指定加载的类,分为帮助类,和字典类等等。

自动加载。

插件形式自动加载,分为系统插件和用户插件等。

类较少时三个框架的加载速度相差不大,YYUC是自动加载,不用开发人员手动指定。Laravel也是这一原理,codeigniter调用load方法和直接include差不多,代码不够简洁明快。
对于YYUC插件类较多时如超出500动态加载每次都要从众多文件中抽出所需要的类文件YYUC效率会有所下降。
如果工程特别大,通用类文件特别多考虑以指定包名称的方式加载。如果只是单一模块下用到的类可以将类下载控制器文件夹下,以"_"开头,调用import方法加载该模块的类,父模块和子模块的类可以通过指明路径层级明确调用。

数据校验

校验方式灵活。校验规显得有些杂乱

校验方式灵活,预置的校验种类全面。

建议将提交的数据都封装在模型中,有对应库表的用数据库模型,没有的用简单模型。重写校验方法实现校验。有利于数据的统一管理,与此同时特定校验的扩展性强。

各有优势,codeigniter的类加载本来就很丑了,再加上不同方式的校验规则,代码显的乱七八糟的。

可扩展性

类相对独立,并入框架内部要加一些框架的实例化方法。

框架基本上都是静态风格,太过个性化。把网络上开源的类引入框架中会显得格格不入。最好最为自定义的类放入项目中。要用这些类扩展框架就要对引入的类做大手术。

插件形式引入,对于大多输的类通常只需改下类的文件名就可以自动被调用。

还是喜欢自己写的框架,核心是核心插件是插件,核心越精简越高效越好,插件越强大越灵活越好。网络上这么多优秀的经过验证的类为什么不直接引入其中呢。

安全性

安全机制强大

只包含一般安全校验,如跨站提交等

自认为安全机制强大

codeigniter可以说把能做的安全防范机制都做了,laravel与其说是个框架倒更像一个路由分发的核心。很多安全问题需要自己考虑。YYUC参考了structThinkphp以及codeigniter的安全验证方式,把能加的安全防范规则都加了,可能由于自己底层知识(包括php底层,web服务器底层)的局限性还存在漏洞也是可能的。但是用YYUC发现漏洞可以第一时间改掉。用其他的框架,如果万一有漏洞存在,要么要修改他的核心代码要么要等待版本更新是神被动的。

先进行

传统的MVC模式,但是Model层不够灵活,与库表数据的一一对应并不好。

最新的5.3+支持,先进的语法风格。显得有些另类

传统的MVC模式

laravel运用了最新的5.3规范,引入命名空间的概念,像namespace use等语法都是最新引入,但是部署上有局限性。laravel引入了类似JS的匿名函数回调机制,开发者可能要在思维角度上有所转变。而且大量的回调更利于假设高性能的分发程序,不适合传统的Web网站开发。所以laravel只是底层运用了这些模式,对于开发者来说还是传统的MVC模式。

数据库支持

功能强大,全面支持。

PDO规范支持MysqlSqlserver不支持Oracle

只支持Mysql

YYUC目前只支持Mysql数据库,但是封装的DB类做了很好的多库表,主从表的支持(主要参照的Thinkphp),超大数据量的系统也是可以应对的。对于其他数据库以后版本想以插件的形式。在精而不在多。

效率与开销

相应速度快,内存开销一般。

相应速度较快,内存开销稍大。

生产模式下相应速度快,内存开销很小,开发模式下需要编译速度会稍微慢一些。

个人认为对PHP来说,框架类的层级过多并不一定是好事。

PHP的初衷就是敏捷开发快速相应,Http并不是常连接的,处理好每次请求也就处理好了整个网站,好的框架并不一定要设计成像Spring那样包罗万象。

开发运行效率示例:

下面的例子分别利用三种框架做了个数据插入到Mysql数据库并查询输出的示例,示例只是实现基本的增加查询功能并没有进行数据校验。下面的例子中将展示不同框架代码量的,公平起见运行效率的统计方法没有用框架底层的调试类而是采用原生的php方法计算运行时间和内存使用量:

数据表:

CREATE TABLE `test_article` (

  `id` int(11) NOT NULL auto_increment COMMENT '主键',

  `title` varchar(255) default NULL COMMENT '标题',

  `content` text COMMENT '内容',

  `updated_at` datetime default NULL,

  `created_at` datetime default NULL, --laravel必须这两个字段(Rails的一模一样)

  PRIMARY KEY  (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

代码量展示:

laravel

视图:

新增页面:

<!doctype html>

<html>

<head>

       <meta charset="utf-8">

       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

       <title>测试新增</title>

</head>

<body>

<?php echo Form::open('test/new','POST');?>

标题:<?php echo Form::text('title',$title);?>

内容:<?php echo Form::text('content',$content);?>

<?php echo Form::submit('提交');?>

<?php Form::token()?>

<?php echo Form::close();?>

</body>

</html>

如果要实现表单自动填充的话还是要手动指定的有些麻烦

新增成功页:

<!doctype html>

<html>

<head>

       <meta charset="utf-8">

       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

       <title>保存成功</title>

</head>

<body>

<h1>保存成功</h1>

</body>

</html>

 

展示页面:

<!doctype html>

<html>

<head>

       <meta charset="utf-8">

       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

       <title>显示数据</title>

</head>

<body>

标题:<?php echo $title?><br/>

内容:<?php echo $content?><br/>

</body>

</html>

 

模型:

<?php

class Article extends Eloquent {

       public static $table = 'test_article';

 

}

 

控制器:

<?php

class Test_Controller extends Base_Controller {

      

       /**

        * 页面展示

        */

       public function action_init()

       {

              return View::make('test.new');

       }

       /**

        * 保存数据

        */

       public function action_new()

       {

              $title =  Input::get('title');

              $content = Input::get('content');

              $article = new Article;            

              $article->title = $title;

              $article->content = $content;             

              $article->save();

              return View::make('test.success');

       }

      

       /**

        * 显示数据

        */

       public function action_show($id)

       {

              $article = Article::find($id);

              return View::make('test.show',array('title'=>$article->title,'content'=>$article->content));

       }

 

}

CodeIgniter

视图:

新增页面:

<!doctype html>

<html>

<head>

       <meta charset="utf-8">

       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

       <title>测试新增</title>

</head>

<body>

<?php $this->load->helper('form');?>

<?php echo form_open('test/tonew'); ?>

标题:<?php echo form_input('title');?>

内容:<?php echo form_input('content');?>

<?php echo form_submit('mysubmit', '提交');?>

</form>

</body>

</html>

 

同样的表单自动填充也不省事,不对称的标签格式总让人心里不舒服

新增成功页:

<!doctype html>

<html>

<head>

       <meta charset="utf-8">

       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

       <title>保存成功</title>

</head>

<body>

<h1>保存成功</h1>

</body>

</html>

 

展示页面:

<!doctype html>

<html>

<head>

       <meta charset="utf-8">

       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

       <title>显示数据</title>

</head>

<body>

标题:<?php echo $title?><br/>

内容:<?php echo $content?><br/>

</body>

</html>

 

模型:

 

<?php

class Article_model extends CI_Model {

 

       /**

        * 构造函数

        */

       public function __construct()

       {

              $this->load->database();

       }

       /**

        * 新增函数

        */

       public function to_new()

       {

              $data = array(

                            'title' => $this->input->post('title'),

                            'content' => $this->input->post('content')

              );    

              return $this->db->insert('test_article', $data);

       }

       /**

        * 查询一条数据

        * @param $id

        */

       public function show_one($id)

       {

              $query = $this->db->get_where('test_article', array('id' => $id));

             return $query->row_array();

       }

      

}

无论怎样类初始化后DB连接就建立了,而且数据查询很不方便,完全抛弃了POJO类的概念,要手动加属性这点开发效率上是无法和YYUClaravel相比的。

控制器:

<?php

class Test extends CI_Controller {

       /**

        * 构造函数

        */

       public function __construct()

       {

              parent::__construct();

              $this->load->model('article_model');

       }

      

      

       /**

        * 页面展示

        */

       public function init()

       {

              $this->load->view('test/new');           

       }

       /**

        * 保存数据

        */

       public function tonew()

       {

              $this->article_model->to_new();        

              $this->load->view('test/success');

       }

       /**

        * 显示数据

        */

       public function show($id)

       {

              $data = $this->article_model->show_one($id);

              $this->load->view('test/show',$data);

       }

}

YYUC

视图:

新增页面:

<!doctype html>

<html>

<head>

       <meta charset="utf-8">

       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

       <title>测试新增</title>

</head>

<body>

<form action="new.html" method="post">

标题:{$article->text('title')}

内容:{$article->text('content')}

<button type="submit">提交</button>

{tk()}

</form>

</body>

</html>

 

 

 

新增成功页:

<!doctype html>

<html>

<head>

       <meta charset="utf-8">

       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

       <title>保存成功</title>

</head>

<body>

<h1>保存成功</h1>

</body>

</html>

 

展示页面:

<!doctype html>

<html>

<head>

       <meta charset="utf-8">

       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

       <title>显示数据</title>

</head>

<body>

标题:{h $article->title}<br/>

内容:{h $article->content}<br/>

</body>

</html>

安全起见,视图中转义要输出的字符

模型:

简单的数据处理,没有验证、虚拟字段填充与回填、复杂数据计算等操作,使用自动模型构建就好,所以完全没必要自定义模型

控制器:

初始化和新增:

if(Request::post()){

       //数据提交

       $article = new Model('article');

       if($article->load_from_post()->save()){

              Page::view('success');

       }

}else{

       //初始化显示

       $article = new SampleModel('article');

}

数据显示:

$article = new Model('article');

if(!is_numeric(get(1)) || !$article->find(get(1))->has_id()){

       //数据不合法或者不存在跳转到404页面 上两个框架判断起来稍显麻烦就没写 如果有这种情况上两个框架会直接抛异常的

       goto_404();

}

已经自动集成阻止跨站提交模块

性能消耗:

三个框架均设置为生产模式。

laravel

新增展示:

内存使用情况:
2989432bytes
运行时间:
0.0533249378204

数据保存:

内存使用情况:
3433792bytes
运行时间:
0.130746126175

数据显示:

内存使用情况:
3374368bytes
运行时间:
0.0524969100952

 

 

CodeIgniter

新增展示:

内存使用情况:
2643704bytes
运行时间:
0.054661989212

数据保存:

内存使用情况:
2471400bytes
运行时间:
0.158566141129

数据显示:

内存使用情况:
2572744bytes
运行时间:
0.0491800308228

 

YYUC

新增展示:

内存使用情况:
1850760bytes
运行时间:
0.0474209499359

数据保存:

内存使用情况:
2076544bytes
运行时间:
0.090379867554

数据显示:

内存使用情况:
2075152bytes
运行时间:
0.0683400440216

综述:

laravel是非常优美和整洁的php框架,路由功能非常强大,更像一个路由核心,有着良好的请求分发和路由控制,代码风格整齐划一。但是似乎laravel扩展的功能太过简单,没有太多的具体实现。最重要的是所有请求都要走路由,看了它的2.x3.x版新版本才有默认规则,最新版简直就和ROR一模一样,比如数据表结构什么的连字段的要求都是一样的,Rails虽好也不至于模仿的这么真真切切。基于laravel的前台的各种控件很少,网上甚至没有一个基于laravel的完整的例子。中文文档还在翻译中对于新人来说用laravel开发效率可能会大打折扣,而且laravel在安全性方面考虑的并不多这也是让人头疼的一部分,好像只有一个防止跨站提交的过滤器。个人认为最重要的是选择使用laravel人现在并不多。框架结构设计的非常优秀,但是还是稍显复杂的,引入了最新的命名空间,和闭包回调的机制,每次请求要加载的文件太多了或多或少的拖了性能,所以内存消耗方面laravel是最大的。

Codeigniter功能强大但是显得又过于杂乱了,特别是控制器和视图的对应上完全背离了约定大于配置这一原则,没有Rails的外部包裹机制,内部引入也显得页面和代码不分家。Codeigniter没有模型类的自动装载功能,实际开发起来效率就会有些低,视图代码不讲究对称让人看了不顺心。好像Codeigniter并没有自动的POJO类的概念,Model类侧很重Active Record模式,数据库的操作很大程度上依赖了手写。还有就是开发的时候没有显示的类调用,这样就得不到IDE友好提示,开发效率上多少会有影响的。

其实所有MVC的框架机制是一样,但是YYUC其中一个特点是按需加载,控制器是程序片段而不是一个类,通常的面向类的控制器如果对应10个请求的话那么每次页面请求都会无端的加载9段多余的其他代码。php不像Java常驻内存,每次请求能少加载些就少加载些。YYUC控制器中的变量是不需要显示的声明注入到视图中的,视图和控制器在同一个级别之下,这样即提高了开发效率又加快了代码的执行效率。YYUCModel既有原始POJO类的特点也可以通过子类实现Active Record模式,可以在开发时灵活选择。通过插件规则YYUC内置了很多常用控件,像分页、日期,上传,图片截取,验证码、颜色选取、富文本编辑器、HTML5的视频音频兼容播放、HTML5WebSocket兼容支持等等。