yii 1 和 yii2 什么区别呢
yii 1 和 yii2 什么区别呢
yii 1 和 yii2 什么区别呢
2015-07-02
大致思路不会变,开发流程变化也不是很大。
有变化的是
1、yii2带入的PHP5.4的特性,引入了namespace解决命名冲突,因此基类不会再C字开头了
2、不再所有类都继承自组件Component,而是选择继承object和component(也继承自object,但带有事件功能、以及用于扩展的Behavior功能)
3、更加的MVC,原先的view层其实基本算是controller直接include进来的,现在有了view的类用来控制,因此View层在使用Controller带来的参数的方式稍有不同。
4、yii2分基本版(看上去和1差不多)和高级版(分前台和后台),高级版更加适合开发大型项目。
5、其他的都是细节方面的变化,比如块赋值(基本用于收集表单数据)更加方便了。安装完毕界面就自带bootstrap风格了,等等等等。
当然还有许多其他的特性,可以直接参看yii在git上更新的文档:
yii2/docs/guide/upgrade-from-v1.md at master 路 yiisoft/yii2 路 GitHub
--update--
1、加入了Dependency Injection(依赖注入,理论可以看经典翻译文IoC容器和依赖注入模式(转)-redcoffee-ChinaUnix博客,yii的具体实现看/vendor/yiisoft/yii2/di下的container和instance就行),以后创建对象时基本都可以用容器的get方法替代new了,很不错很赞哟~
自己不会百度下
这部分内容是专门为已经有Yii1.1基础的读者朋友写的。将Yii2.0与Yii1.1的不同点着重写出来,对比学起来会快得多。 而对于从未接触过Yii的读者朋友,这部分内容扫一扫就可以了,作为对过往历史的一个了解就够了。 如果有的内容你一时没看明白,也不要紧,本书的正文部分会讲清楚的。 另外,没有Yii1.1的经验,并不妨碍对Yii2.0的学习。
Yii官方有专门的文档归纳总结1.1版本和2.0版本的不同。以下内容,主要来自于官方的文档,我做了下精简, 选择比较重要的变化,并加入了一些个人的经验。
PHP新特性
从对PHP新特性的使用上,两者就存在很大不同。Yii2.0大量使用了PHP的新特性,这在Yii1.1中是没有的。因此,Yii2.0对于PHP的版本要求更高,要求PHP5.4及以上。Yii2.0中使用到的PHP新特性,主要有:
命名空间(Namespace)
匿名函数
数组短语法形式: [1,2,3] 取代 array(1,2,3) 。这在多维数组、嵌套数组中,代码更清晰、简短。
在视图文件中使用PHP的 <?= 标签,取代 echo 语句。
标准PHP库(SPL) 类和接口,具体可以查看 SPL Class and Interface
延迟静态绑定, 具体可以查看 Late Static Bindings
PHP标准日期时间
特性(Traits)
使用PHP intl 扩展实现国际化支持, 具体可以查看 PECL init 。
了解Yii2.0使用了PHP的新特性,可以避免开发时由于环境不当,特别是开发生产环境切换时,产生莫名其妙的错误。 同时,也是让读者朋友借机学习PHP新知识的意思。
命名空间(Namespace)
Yii2.0与Yii1.1之间最显著的不同是对于PHP命名空间的使用。Yii1.1中没有命名空间一说, 为避免Yii核心类与用户自定义类的命名冲突,所有的Yii核心类的命名,均冠以 C 前缀,以示区别。
而Yii2.0中所有核心类都使用了命名空间,因此, C 前缀也就人老珠黄,退出历史舞台了。
命名空间与实际路径相关联,比如 yii\base\Object 对应Yii目录下的 base/Object.php 文件。
基础类
Yii1.1中使用了一个基础类 CComponent ,提供了属性支持等基本功能,因此几乎所有的Yii核心类都派生自该类。 到了Yii2.0,将一家独大的 CComponent 进行了拆分。拆分成了 yii\base\Object 和 yii\base\Component 。 拆分的考虑主要是 CComponent 尾大不掉,有影响性能之嫌。 于是,Yii2.0中,把 yii\base\Object 定位于只需要属性支持,无需事件、行为。 而 yii\base\Component 则在前者的基础上,加入对于事件和行为的支持。 这样,开发者可以根据需要,选择继承自哪基础类。
这一功能上的明确划分,带来了效率上的提升。在仅表示基础数据结构,而非反映客观事物的情况下, yii\base\Object 比较适用。
值得一提的是, yii\base\Object 与 yii\base\Component 两者并不是同一层级的,前者是后者他爹。
事件(Event)
在Yii1.1中,通过一个 on 前缀的方法来创建事件,比如 CActiveRecord 中的 onBeforeSave() 。 在Yii2.0中,可以任意定义事件的名称,并自己触发它:
$event = new \yii\base\Event;// 使用 trigger() 触发事件$component->trigger($eventName, $event);// 使用 on() 前事件handler与对象绑定$component->on($eventName, $handler);// 使用 off() 解除绑定$component->off($eventName, $handler);
别名(Alias)
Yii2.0中改变了Yii1.1中别名的使用形式,并扩大了别名的范畴。 Yii1.1中,别名以 . 的形式使用:
RootAlias.path.to.target
而在Yii2.0中,别名以 @ 前缀的方式使用:
@yii/jui
另外,Yii2.0中,不仅有路径别名,还有URL别名:
// 路径别名Yii::setAlias('@foo', '/path/to/foo');// URL别名Yii::setAlias('@bar', 'http://www.example.com');
别名与命名空间是紧密相关的,Yii建议为所有根命名空间都定义一个别名,比如上面提到的 yii\base\Object , 事实上是定义了 @yii 的别名,表示Yii在系统中的安装路径。 这样一来,Yii就能根据命名空间找到实际的类文件所在路径,并自动加载。这一点上,Yii2.0与Yii1.1并没有本质区别。
而如果没有为根命名空间定义别名,则需要进行额外的配置。将命名空间与实际路径的映射关系,告知Yii。
关于别名的更详细内容请看 别名(Alias) 。
视图(View)
Yii1.1中,MVC(model-view-controller)中的视图一直是依赖于Controller的,并非是真正意义上独立的View。 Yii2.0引入了 yii\web\View 类,使得View完全独立。这也是一个相当重要变化。
首先,Yii2.0中,View作为Application的一个组件,可以在全局中代码中进行访问。 因此,视图渲染代码不必再局限于Controller中或Widget中。
其次,Yii1.1中视图文件中的 $this 指的是当前控制器,而在 Yii2.0中,指的是视图本身。 要在视图中访问控制器,可以使用 $this->context 。这个 $this->context 是指谁调用了 yii\base\View::renderFile() 来渲染这个视图。 一般是某个控制器,也可以是其他实现了 yii\base\ViewContextInterface 接口的对象。
同时,Yii1.1中的 CClientScript 也被淘汰了,相关的前端资源及其依赖关系的管理,交由Assert Bundle yii\web\AssertBundle 来专职处理。 一个Assert Bundle代表一系列的前端资源,这些前端资源以目录形式进行管理,这样显得更有序。 更为重要的是,Yii1.1中需要你格外注意资源在HTML中的顺序,比如CSS文件的顺序(后面的会覆盖前面的), JavaScript文件的顺序(前后顺序出错会导致有的库未加载)等。 而在Yii2.0中,使用一个Assert Bundle可以定义依赖于另外的一个或多个Assert Bundle的关系, 这样在向HTML页面注册这些CSS或者JavaScript时,Yii2.0会自动把所依赖的文件先注册上。
在视图模版引擎方面,Yii2.0仍然使用PHP作为主要的模版语言。 同时官方提供了两个扩展以支持当前两大主流PHP模版引擎:Smarty和Twig,而对于Pardo引擎官方不再提供支持了。 当然,开发者可以通过设置 yii\web\View::$renderers 来使用其他模版。
另外,Yii1.1中,调用 $this->render('viewFile', ...) 是不需要使用 echo 命令的。 而Yii2.0中,记得 render() 只是返回视图渲染结果,并不对直接显示出来,需要自己调用 echo
echo $this->render('_item', ['item' => $item]);
如果有一天你发现怎么Yii输出了个空白页给你,就要注意是不是忘记使用 echo 了。 还别说,这个错误很常见,特别是在对Ajax请求作出响应时,会更难发现这一错误。请你们编程时留意。
在视图的主题(Theme)化方面,Yii2.0的运作机理采用了完全不同的方式。 在Yii2.0中,使用路径映射的方式,将一个源视图文件路径,映射成一个主题化后的视图文件路径。 因此, ['/web/views' => '/web/themes/basic'] 定义了一个主题映射关系, 源视图文件 /web/views/site/index.php 主题化后将是 /web/themes/basic/site/index.php 。 因此, Yii1.1中的 CThemeManager 也被淘汰了。
模型(Model)
MVC中的M指的就是模型,Yii1.1中使用 CModel 来表示,而Yii2.0使用 yii\base\Model 来表示。
Yii1.1中, CFormModel 用来表示用户的表单输入,以区别于数据库中的表。 这在Yii2.0中也被淘汰,Yii2.0倾向于使用继承自 yii\base\Model 来表示提交的表单数据。
另外,Yii2.0为Model引入了 yii\base\Model::load() 和 yii\base\Model::loadMutiple() 两个新的方法, 用于简化将用户输入的表单数据赋值给Model:
// Yii2.0使用load()等同于下面Yii1.1的用法$model = new Post;if ($model->load($_POST)) {
... ...}// Yii1.1中常用的套路if (isset($_POST['Post'])) {
$model->attributes = $_POST['Post'];}
另外一个重要变化就是Yii2.0中改变了Model应用于不同场景的逻辑。通过引入 yii\base\Model::scenarios() 来集中管理场景,使得一个Model所有适用的场景都比较清晰,一目了然。而Yii1.1是没有一个统一管理场景的方法的。
由此带来的一个很容易出现的问题就是,当你声明一个Model处于某一场景时,可能由于拼写错误, 不小心将场景的名称写错了,那么在Yii1.1中,这个错误的场景并没有任何的提示。假设有以下情况:
class UserForm extends CFormModel{
public $username;
public $email;
public $password;
public $password_repeat;
public $rememberMe=false;
public function rules()
{
return array(
// username 和 password 在所有场景中都要验证
array('username, password', 'required'),
// email 和 password_repeat 只在注册场景中验证
array('email, password_repeat', 'required', 'on'=>'Registration'),
array('email', 'email', 'on'=>'Registration'),
// rememberMe 仅在登陆场景中验证
array('rememberMe', 'boolean', 'on'=>'Login'),
);
}}
这里针对UserForm的注册和登陆两个场景,设定了不同的验证规则。接下来,你要在注册场景中使用这个UserForm, 但你一不小心将 Registration 场景设定成了 SignUp , 说实在,我不是学英文出身的,这两个单词的意思在我眼里是一样一样的。只是Yii不会智能到把这两个场景等同起来。 那么Yii1.1将不会有任何的提示,并自动地使用第一个验证规则,而用户注册时填写的 email 和 password_repeat 字段就被抛弃了。这在实际编程中,是经常出现的一个低级错误。
从这里可以看到,Yii1.1中对于场景,没有一个集中统一的管理,也就是说一个Model可适用的场景, 是不确定的、任意的。通过 rules() 你很难一眼看出来一个Model可以适用于多少个场景,每个场景下都有哪些字段是有效的、需要验证的。
而在Yii2.0中,由于引入了 yii\base\Model::scenarios() 新的方法, 将本Model所有适用的场景,及不同场景下的有效字段都进行了声明, 这个逻辑就显得清晰了。而且,如果使用了一个未声明的场景,Yii2.0会有相应的提示, 这避免了上面这个低级错误的可能:
namespace app\models;use yii\db\ActiveRecord;class User extends ActiveRecord{
public function scenarios()
{
return [
'login' => ['username', 'password', 'rememberMe'],
'registration' => ['username', 'email', 'password', 'password_repeat'],
];
}}
这样看来,是不是很清晰?这个User仅有两种场景,每种场景的有效字段也一目了然。 而至于具体场景下每个字段的验证规则,仍然由 yii\base\Model::rules() 来确定。 这也意味着, unsafe 验证在Yii2.0中也没有了立足之地,凡是 unsafe 的字段,就不在特定的场景中列出来。 或者为了更加明显的表示某一字段在特定场景下是无效的,可以给这个字段加上 ! 前缀。
在默认情况下, yii\base\Model::scenarios() 所有适用的场景和对应的字段由 yii\base\Model::rules() 的内容自动生成。也就是说,如果你的 rules() 很完备、很清晰,那么也是不需要重载这个 scenarios() 的。 这种情况下,Yii1.1和Yii2.0在这一点上的表现形式,是一样的。但是,个人经验看, 我更倾向于将 scenarios() 声明清楚,而在 rules() 中,仅指定字段的验证规则,而不涉及场景的内容。 这样的逻辑更加清晰,便于其他团队成员阅读你的代码,也便于后续的维护和开发。
控制器(Controller)
除了上面讲到的控制器中要使用 echo 来显示渲染视图的输出这点区别外, Yii1.1与Yii2.0的控制器还表现出更为明显的区别,那就是动作过滤器(Action Filter) 的不同。
在Yii2.0中,动作过滤器以行为(behavior)的方式出现, 一般继承自 yii\base\ActionFilter ,并注入到一个控制器中,以发生作用。比如,Yii1.1中很常见的:
1
2
3
4
5
6
7
8
9
10
11
public function behaviors(){
return [
'access' => [
'class' => 'yii\filters\AccessControl',
'rules' => [
['allow' => true, 'actions' => ['admin'], 'roles' => ['@']],
],
],
];}
看着是不是有点像,但又确实不一样?
Active Record
还记得么?在Yii1.1中,数据库查询被分散成 CDbCommand , CDbCriteria 和 CDbCommandBuilder 。 所谓天下大势分久必合,到了Yii2.0,采用 yii\db\Query 来表示数据库查询:
$query = new \yii\db\Query();$query->select('id, name')
->from('user')
->limit(10);$command = $query->createCommand();$sql = $command->sql;$rows = $command->queryAll();
最最最爽的是, yii\db\Query 可以在 Active Record中使用,而在Yii1.1中,要结合两者,并不容易。
Active Record在Yii2.0中最大的变化一个是查询的构建,另一个是关联查询的处理。
Yii1.1中的 CDbCriteria 在Yii2.0中被 yii\db\ActiveQuery 所取代, 这个把前辈拍死在沙滩上的家伙,继承自 yii\db\Query ,所以可以进行类似上面代码的查询。 调用 yii\db\ActiveRecord::find() 就可以启动查询的构建了:
$customers = Customer::find()
->where(['status' => $active])
->orderBy('id')
->all();
这在Yii1.1中,是不容易实现的。特别是比较复杂的查询关系。
在关联查询方面,Yii1.1是在一个统一的地方 relations() 定义关联关系。 而Yii2.0改变了这一做法,定义一个关联关系:
定义一个getter方法
g
举报