YII2框架详解

yii2框架的安装我们在之前文章中已经提到下面我们开始了解YII2框架

强大的YII2框架网上指南:http://www.yii-china.com/doc/detail/1.html?postid=278或者

http://www.yiichina.com/doc/guide/2.0

Yii2的应用结构:
这里写图片描述

目录篇:

         
 advance 版本的特点是:根目录下预先分配了三个模块,分别是前台、后台、控制台模块。
1.backend
它主要用于管理后台,网站管理员来管理整个系统。

assets 目录用于存放前端资源包PHP类。 这里不需要了解什么是前端资源包,只要大致知道是用于管理CSS、js等前端资源就可以了。
config 用于存放本应用的配置文件,包含主配置文件 main.php 和全局参数配置文件 params.php 。
models views controllers 3个目录分别用于存放数据模型类、视图文件、控制器类。这个是我们编码的核心,也是我们工作最多的目录。
widgets 目录用于存放一些常用的小挂件的类文件。
tests 目录用于存放测试类。
web 目录从名字可以看出,这是一个对于Web服务器可以访问的目录。 除了这一目录,其他所有的目录不应对Web用户暴露出来。这是安全的需要。
runtime 这个目录是要求权限为 chmod 777 ,即允许Web服务器具有完全的权限, 因为可能会涉及到写入临时文件等。 但是一个目录并未对Web用户可见。也就是说,权限给了,但是并不是Web用户可以访问到的。

    
2.frontend

我们的目标最终用户提供的主要接口的前端应用。 其实,前台和后台是一样的,只是我们逻辑上的一个划分.。
  好了,现在问题来了。对于  frontend   backend   console  等独立的应用而言, 他们的内容放在各自的目录下面,他们的运作必然用到Yii框架等  vendor  中的程序。 他们是如何关联起来的?这个秘密,或者说整个Yii应用的目录结构的秘密, 就包含在一个传说中的称为入口文件的地方。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
phpdefined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/../../common/config/bootstrap.php');
require(__DIR__ . '/../config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../../common/config/main.php'),
require(__DIR__ . '/../../common/config/main-local.php'),
require(__DIR__ . '/../config/main.php'),
require(__DIR__ . '/../config/main-local.php'));
$application = new yii\web\Application($config);$application->run();


3.console
控制台应用程序包含系统所需要的控制台命令的。
 



下面是全局公共文件夹
4.common

其中:

  • config 就是通用的配置,这些配置将作用于前后台和命令行。
  • mail 就是应用的前后台和命令行的与邮件相关的布局文件等。
  • models 就是前后台和命令行都可能用到的数据模型。 这也是 common 中最主要的部分。

 公共的目录(Common)中包含的文件用于其它应用程序之间共享。例如,每一个应用程序可能需要访问该数据库的使用 ActiveRecord。因此,我们可以将AR模型类放置在公共(common)的目录下。同样,如果在多个应用程序中使用了一些辅助(helper )或部件类(widget ),我们也应该把这些放置在公共目录(common)下,以避免重复的代码。
  正如我们将很快解释,应用程序也可以共享一部分的共用配置。因此,我们还可以存储config目录下共同的常见配置。
当开发一个大型项目开发周期长,我们需要不断调整数据库结构。出于这个原因,我们还可以使用数据库迁移(DB migrations )功能来保持跟踪数据库的变化。我们将所有 DB migrations(数据库迁移)目录同样都放在公共(common)目录下面。

5.environment
每个Yii环境就是一组配置文件, 包含了入口脚本 index.php和各类配置文件。 其实他们都放在/environments 目录下面.

  从上面的目录结构图中,可以看到,环境目录下有3个东东:
  • 目录 dev
  • 目录 prod
  • 文件 index.php

其中, dev 和 prod 结构相同,分别又包含了4个目录和1个文件:

  • frontend 目录,用于前台的应用,包含了存放配置文件的 config 目录和存放web入口脚本的web 目录
  • backend 目录,用于后台应用,内容与 frontend 相同
  • console 目录,用于命令行应用,仅包含了 config 目录,因为命令行应用不需要web入口脚本, 因此没有 web 目录。
  • common 目录,用于各web应用和命令行应用通用的环境配置,仅包含了 config 目录, 因为不同应用不可能共用相同的入口脚本。 注意这个 common 的层级低于环境的层级,也就是说,他的通用,仅是某一环境下通用,并非所有环境下通用。
  • yii 文件,是命令行应用的入口脚本文件。

对于分散于各处的 web 和 config 目录而言,它们也是有共性的。

  • 凡是 web 目录,存放的都是web应用的入口脚本,一个 index.php 和一个测试版本的index-test.php
  • 凡是 config 目录,存放的,都是本地配置信息 main-local.php 和 params-local.php

6.vendor
 
  vendor  。 这个目录从字面的意思看,就是各种第三方的程序。 这是Composer安装的其他程序的存放目录,包含Yii框架本身,也放在这个目录下面。 如果你向 composer.json  目录增加了新的需要安装的程序,那么下次调用Composer的时候, 就会把新安装的目录也安装在这个  vendor  下面。

下面也是一些不太常用的文件夹
7.vagrant
 
8.tests
 

入口文件篇:

1、入口文件路径:

http://127.0.0.1/yii2/advanced/frontend/web/index.php

每个应用都有一个入口脚本 web/index.PHP,这是整个应用中唯一可以访问的 PHP 脚本。一个应用处理请求的过程如下:

1.用户向入口脚本 web/index.php 发起请求。
2.入口脚本加载应用配置并创建一个应用实例去处理请求。
3.应用通过请求组件解析请求的路由。
4.应用创建一个控制器实例去处理请求。
5.控制器创建一个操作实例并针对操作执行过滤器。
6.如果任何一个过滤器返回失败,则操作退出。
7.如果所有过滤器都通过,操作将被执行。
8.操作会加载一个数据模型,或许是来自数据库。
9.操作会渲染一个视图,把数据模型提供给它。
10.渲染结果返回给响应组件。
11.响应组件发送渲染结果给用户浏览器

可以看到中间有模型-视图-控制器 ,即常说的MVC。入口脚本并不会处理请求,而是把请求交给了应用主体,在处理请求时,会用到控制器,如果用到数据库中的东西,就会去访问模型,如果处理请求完成,要返回给用户信息,则会在视图中回馈要返回给用户的内容。

2、为什么我们访问方法会出现url加密呢?


我们找到文件:vendor/yiisoft/yii2/web/UrlManager.php

    return "$baseUrl/{$route}{$anchor}";
} else {
    $url = "$baseUrl?{$this->routeParam}=" . urlencode($route);
    if (!empty($params) && ($query = http_build_query($params)) !== '') {
        $url .= '&' . $query;
    }
将urlencode去掉就可以了
3、入口文件内容
 
入口文件流程如下:


MVC篇:


一、控制器详解:

1、修改默认控制器和方法

  修改全局控制器:打开vendor/yiisoft/yii2/web/Application.php

eg:

public $defaultRoute = 'student/show';
 修改前台或者后台控制器:
eg :打开  frontend/config/main.php 中
 
  
'params' => $params,
'defaultRoute' => 'login/show',
2、建立控制器示例:StudentController.php

//命名空间

 
  
namespace frontend\controllers;


use Yii; 

use yii\web\Controller;   vendor/yiisoft/yii2/web/Controller.php   (该控制器继承的是\yii\base\Controller)
\web\Controller.php中干了些什么  
1、默认开启了 授权防止csrf攻击
2、响应Ajax请求的视图渲染
3、将参数绑定到动作(就是看是不是属于框架自己定义的方法,如果没有定义就走run方法解析)
4、检测方法(beforeAction)beforeAction() 方法会触发一个 beforeAction 事件,在事件中你可以追加事件处理操作;
5、重定向路径 以及一些http Response(响应) 的设置
use yii\db\Query; //使用query查询
use yii\data\Pagination;//分页  
use yii\data\ActiveDataProvider;//活动记录  
use frontend\models\ZsDynasty;//自定义数据模型 


class StudentController extends Controller
{  
 $request = YII::$app->request;//获取请求组件
   $request->get('id');//获取get方法数据
   $request->post('id');//获取post方法数据
   $request->isGet;//判断是不是get请求
   $request->isPost;//判断是不是post请求
   $request->userIp;//获取用户IP地址
    $res = YII::$app->response;//获取响应组件
    $res->statusCode = '404';//设置状态码
    $this->redirect('http://baodu.com');//页面跳转
    $res->sendFile('./b.jpg');//文件下载

 $session = YII::$app->session;
    $session->isActive;//判断session是否开启
    $session->open();//开启session
    //设置session值
    $session->set('user','zhangsan');//第一个参数为键,第二个为值
    $session['user']='zhangsan';
    //获取session值
    $session->get('user');
    $session['user'];
    //删除session值
    $session-remove('user');
    unset($session['user']);

 $cookies = Yii::$app->response->cookies;//获取cookie对象
    $cookie_data = array('name'=>'user','value'=>'zhangsan')//新建cookie数据
    $cookies->add(new Cookie($cookie_data));
    $cookies->remove('id');//删除cookie
    $cookies->getValue('user');//获取cookie

     //显示视图
     return $this->render('add'); 默认.php
     return $this->render('upda',["data"=>$data]); 
 

   }
}

二、模型层详解

   简单模型建立:

  

 
  

namespace frontend\models;
class ListtModel extends \yii\db\ActiveRecord
{
    public static function tableName()
    {
    return 'listt';
    }
    public function one(){
       return $this->find()->asArray()->one();
    }
}

控制器引用
namespace frontend\controllers;
use Yii;
use yii\web\controller;
use frontend\models\ListtModel;

class ListtController extends Controller{
    public  function  actionAdd(){
        $model=new ListtModel;
        $list=$model->one();
       $data=$model->find()->asArray()->where("id=1")->all();
        print_r($data);
    }
}
?>


三、视图层详解首先在frontend下建立与控制器名一致的文件(小写)eg:student 在文件下建立文件

eg:index.php
每一个 controller对应一个view的文件夹,但是视图文件yii不要求是HTML,而是php,所以每个视图文件php里面都是视图片段:


   而views下面会有一个默认的layouts文件夹,里面存放的就是布局文件,什么意思呢?:
在控制器中,会有一个layout字段,如果制定他为一个layout视图文件,比如common.php,那么视图就会以他为主视图,其他的view视图片段都会作为显示片段嵌入到layout文件common.php中.
而如果不明确重载layout字段,那么默认layout的值是main,意味着layouts的main.php是视图模板。
控制器:

common.php:


layouts 

这样就达到了视图复用的作用。
    控制器中写入$layout
//$layout="main"  系统默认文件
//$layout=null  会找父类中默认定义的main
public $layout="common";
public  function  actionIndex(){
  return  $this->render('index');
}
 将以下内容插入 common中
  $content;?>  它就是index文件中的内容
当然了,视图与模板之间还有数据传递以及继承覆盖的功能。





YII2框架数据的运用

1、数据库连接

简介

一个项目根据需要会要求连接多个数据库,那么在yii2中如何链接多数据库呢?其实很简单,在配置文件中稍加配置即可完成。

配置

打开数据库配置文件common\config\main-local.php,在原先的db配置项下面添加db2,配置第二个数据库的属性即可

'db' => [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=hyii2',   //数据库hyii2
    'username' => 'root',
    'password' => 'pwhyii2',
    'charset' => 'utf8',
],
'db2' => [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=hyii',     //数据库hyii
    'username' => 'root',
    'password' => 'pwhyii',
    'charset' => 'utf8',
],

如上配置就可以完成yii2连接多个数据库的功能,但还是需要注意几个点

如果使用的数据库前缀 在建立模型时 这样: eg:这个库叫 haiyong_test        return {{%test}}

应用

1.我们在hyii数据库中新建一个测试表test

blob.png

2.通过gii生成模型,这里需要注意的就是数据库链接ID处要改成db2

blob.png

3.查看生成的模型,比正常的model多了红色标记的地方

blob.png

所以各位童鞋,如果使用多数据配置,在建db2的模型的时候,也要加上上图红色的代码。

好了,以上步骤就完成了,yii2的多数据库配置,配置完成之后可以和原因一样使用model或者数据库操作

2、数据操作:


方式一:使用createCommand()函数

加 

获取自增id

$id=Yii::$app->db->getLastInsertID();

Yii::$app->db->createCommand()->insert('user', [  
    'name' => 'test',  
    'age' => 30,  
])->execute();

批量插入数据

Yii::$app->db->createCommand()->batchInsert('user', ['name', 'age'], [  
    ['test01', 30],  
    ['test02', 20],  
    ['test03', 25],  
])->execute();
删除

Yii::$app->db->createCommand()->delete('user', 'age = 30')->execute();

修改

Yii::$app->db->createCommand()->update('user', ['age' => 40], 'name = test')->execute();
查询

//createCommand(执行原生的SQL语句)  
$sql= "SELECT u.account,i.* FROM sys_user as u left join user_info as i on u.id=i.user_id";  
$rows=Yii::$app->db->createCommand($sql)->query();  

查询返回多行:    
$command = Yii::$app->db->createCommand('SELECT * FROM post');  
$posts = $command->queryAll();
 
返回单行
$command = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=1');  
$post = $command->queryOne();
  
查询多行单值:  
$command = Yii::$app->db->createCommand('SELECT title FROM post');  
$titles = $command->queryColumn();
  
查询标量值/计算值:  
$command = Yii::$app->db->createCommand('SELECT COUNT(*) FROM post');  
$postCount = $command->queryScalar();

方式二:模型处理数据(优秀程序媛必备)!!


新增(因为save方法有点low)所以自己在模型层中定义:add和addAll方法

注意:!!!当setAttributes($attributes,fase);时不用设置rules规则,否则则需要设置字段规则;

 //入库一维数组
    public function add($data)
    {
        $this->setAttributes($data);
        $this->isNewRecord = true;
        $this->save();
        return $this->id;
    }
     //入库二维数组
    public function addAll($data){
        $ids=array();
        foreach($data as $attributes)
        {
            $this->isNewRecord = true;
            $this->setAttributes($attributes);
            $this->save()&& array_push($ids,$this->id) && $this->id=0;
        }
        return $ids;
    }


    public function rules()
    {
        return [
            [['title','content'],'required'
       ]];
    }

    控制器:

    $ids=$model->addAll($data);
     var_dump($ids);

删除

使用model::delete()进行删除

$user = User::find()->where(['name'=>'test'])->one(); 
$user->delete();

直接删除:删除年龄为30的所有用户

$result = User::deleteAll(['age'=>'30']);

根据主键删除:删除主键值为1的用户

$result = User::deleteByPk(1);


 /**
     * @param $files  字段
     * @param $values  值
     * @return int  影响行数
     */
    public function del($field,$values){
//        $res = $this->find()->where(['in', "$files", $values])->deleteAll();
        $res=$this->deleteAll(['in', "$field", "$values"]);
        return $res;
    }





修改

使用model::save()进行修改

$user = User::find()->where(['name'=>'test'])->one(); //获取name等于test的模型
$user->age = 40; //修改age属性值
$user->save();   //保存

直接修改:修改用户test的年龄为40

$result = User::model()->updateAll(['age'=>40],['name'=>'test']);


/**
 * @param $data   修改数据
 * @param $where  修改条件
 * @return int  影响行数
 */
public function upda($data,$where){
    $result = $this->updateAll($data,$where);
   // return $this->id;
    return $result;
}


基础查询

Customer::find()->one();    此方法返回一条数据;

Customer::find()->all();    此方法返回所有数据;

Customer::find()->count();    此方法返回记录的数量;

Customer::find()->average();    此方法返回指定列的平均值;

Customer::find()->min();    此方法返回指定列的最小值 ;

Customer::find()->max();    此方法返回指定列的最大值 ;

Customer::find()->scalar();    此方法返回值的第一行第一列的查询结果;

Customer::find()->column();    此方法返回查询结果中的第一列的值;

Customer::find()->exists();    此方法返回一个值指示是否包含查询结果的数据行;

Customer::find()->batch(10);  每次取10条数据 

Customer::find()->each(10);  每次取10条数据,迭代查询 

//根据sql语句查询:查询name=test的客户
Customer::model()->findAllBySql("select * from customer where name = test"); 

//根据主键查询:查询主键值为1的数据
Customer::model()->findByPk(1); 

//根据条件查询(该方法是根据条件查询一个集合,可以是多个条件,把条件放到数组里面) 
Customer::model()->findAllByAttributes(['username'=>'admin']); 

//子查询
$subQuery = (new Query())->select('COUNT(*)')->from('customer');
// SELECT `id`, (SELECT COUNT(*) FROM `customer`) AS `count` FROM `customer`
$query = (new Query())->select(['id', 'count' => $subQuery])->from('customer');

//关联查询:查询客户表(customer)关联订单表(orders),条件是status=1,客户id为1,从查询结果的第5条开始,查询10条数据
$data = (new Query())
    ->select('*')
    ->from('customer')
    ->join('LEFT JOIN','orders','customer.id = orders.customer_id')
    ->where(['status'=>'1','customer.id'=>'1'])
    ->offset(5)
    ->limit(10)
    ->all()


关联查询

/**
 *客户表Model:CustomerModel 
 *订单表Model:OrdersModel
 *国家表Model:CountrysModel
 *首先要建立表与表之间的关系 
 *在CustomerModel中添加与订单的关系
 */     
Class CustomerModel extends \yii\db\ActiveRecord
{
    ...
    //客户和订单是一对多的关系所以用hasMany
    //此处OrdersModel在CustomerModel顶部别忘了加对应的命名空间
    //id对应的是OrdersModel的id字段,order_id对应CustomerModel的order_id字段
    public function getOrders()
    {
        return $this->hasMany(OrdersModel::className(), ['id'=>'order_id']);
    }
    
    //客户和国家是一对一的关系所以用hasOne
    public function getCountry()
    {
        return $this->hasOne(CountrysModel::className(), ['id'=>'Country_id']);
    }
    ....
}
      
// 查询客户与他们的订单和国家
CustomerModel::find()->with('orders', 'country')->all();

// 查询客户与他们的订单和订单的发货地址(注:orders 与 address都是关联关系)
CustomerModel::find()->with('orders.address')->all();

// 查询客户与他们的国家和状态为1的订单
CustomerModel::find()->with([
    'orders' => function ($query) {
        $query->andWhere('status = 1');
        },
        'country',
])->all();















           









 
   
  
 
  




你可能感兴趣的:(YII2框架)