Yii2.0框架学习笔记
1、Yii框架工作流程(MVC文件后缀都是php):
models文件夹下建模型,写AR类、对应数据库相关表、定义属性标签、写验证规则、保存表之前调用的方式,用于保存非表单获取的默认数据(如添加数据的时间等,此步如不需要可省略)->controllers文件夹下建控制器、写保存表单的动作->views文件夹下建模板,动态显示视图。
2、YII中各种类
模型中添加:
use yii\base\Model;
use yii\db\ActiveRecord; //活动记录,简称AR,用于访问数据库,一个AR类关联一张数据表
use yii\web\IdentityInterface; //认证接口,登录(身份接口)
控制器中添加:
use yii\web\Controller;
use frontend\models\Test; //引入前台模型中的AR类
use yii\helpers\Url; //url助手类
use Yii; //使用这个后,在控制器动作中的\Yii::$app可以直接写成Yii::$app
use backend\models\Product; //调用后台产品模型类
use yii\data\Pagination; //分页类
use backend\models\UploadForm; //上传模型类
use yii\web\UploadedFile; //上传功能类
use yii\filters\AccessControl; //授权类
视图中添加:
use yii\helpers\Url; //url助手类,用于生成URL
use yii\widgets\ActiveForm; //借助小部件,动态生成表单(创建表单类)
use yii\widgets\LinkPager; //显示分页类
<?php
$this->title="首页"; //定义页面title名称,用于布局中
//$this->title = $info->title; //设置页面标题,同上方
//<link rel="stylesheet" type="text/css" href="css/ssss.css"/>
//$this->registerCssFile('css/ssss.css'); //添加css到布局中,布局中要有$this->head();meta标签和link标签, 需要调用此方法动态生成
//<script src="js/aa.js"></script>
//$this->registerJsFile('js/aa.js'); //加载到布局中$this->endBody()这个位置,</body>前
/*
添加关键词和简介标签
<meta name="keywords" content="">
<meta name="description" content="">
*/
//$this->registerMetaTag(['name'=>'keywords','content'=>'网站关键字']);
//$this->registerMetaTag(['name'=>'description','content'=>'简介']);
?>
3、使用布局-包含文件
public $layout = 'main'; //属性-使用布局-包含文件,不想使用布局设置false
4、视图中调用视图-相当于包含文件
<?= $this->render('/index/_leftlxwm'); ?> //视图中调用视图
5、模型中的写法
<?php
namespace frontend\models;
use yii\db\ActiveRecord;
//模型命名不用带有model和.class
class Msg extends ActiveRecord {
//设定对应表,如果此步省略, 代表表名和类名一致(表前缀,在配置中设置)
public static function tableName() {
return '{
{%msg}}'; //return 'msg';表名,如果配置里设置了表前缀,那么{
{%msg}}是给msg表加前缀的
}
//定义属性标签,固定函数
public function attributeLabels() {
return[
'title' => '留言主题',
'sex' => '性别',
'tel' => '联系电话',
'lxr' => '联系人',
'content' => '留言内容'
];
}
//验证规则,固定函数
public function rules() {
return[
[['title','sex','tel','lxr','content'],'required','message' => '{attribute}不能为空'],
['title','string','min' => 4,'max' => 30,'tooShort' => '{attribute}最小长度必须在4个字以上','tooLong' => '{attribute}最大长度必须在30个字以内'],
['tel','match','pattern' => '/^1[34578]\d{9}$/','message' => '手机格式不正确'],
['lxr','match','pattern' => '/^[\x{4e00}-\x{9fa5}]+$/u','message' => '{attribute}只能使用中文'],
['content','string','min' => 10,'max' => 140,'tooShort' => '{attribute}最小长度必须在10个字以上','tooLong' => '{attribute}最大长度必须在140个字以内']
];
}
//保存表之前调用的方式,用于保存非表单获取的默认数据,此步不需要时可省略
public function beforeSave($insert) {
if(parent::beforeSave($insert)) {
if($insert) { //插入,即新增
//属性对应表中字段
$this->status = 0;
$this->ip = \Yii::$app->request->getUserIP(); //获取访问者IP
$this->add_time = time();
return true;
} else { //修改
$this->edit_time = time();
return true;
}
} else { //非添加和修改
return false;
}
}
}
/*
* 上传模型类
*/
<?php
namespace backend\models;
use yii\base\Model;
class UploadForm extends Model {
//定义属性,表单中上传控件名
public $img;
public function attributeLabels() {
return [
'img' => '上传图片'
];
}
public function rules() {
return [
['img', 'file', 'extensions' => 'png, jpg'], //上传文件扩展名
['img', 'file', 'mimeTypes' => 'image/jpeg, image/png'], //上传文件类型
['img', 'file', 'minSize' => '30720', 'tooSmall' => '{attribute}不能小于30Kb'], //单位字节
['img', 'file', 'maxSize' => '512000', 'tooBig' => '{attribute}不能大于500Kb'],
];
}
}
/*
* 登陆模型类
*/
<?php
namespace backend\models;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface; //认证接口
class Login extends ActiveRecord implements IdentityInterface {
//定义属性对应表单(表中不存在的字段,临时使用的)
public $rel = true; //记住我,默认勾选
public $_user; //保存查询的用户信息
public static function tableName() {
return 'user';
}
public function attributeLabels() {
return [
'username' => '用户名',
'pwd' => '密码',
'rel' => '记住我'
];
}
public function rules() {
return [
[['username','rel', 'pwd'], 'required', 'message' => '{attribute}不能为空'],
['pwd', 'checkLogin'] //调用方法实现验证用户+密码
];
}
//checkLogin方法(验证用户名和密码是否正确($attribute对应值为pwd))
public function checkLogin($attribute) { //self::即当前类
$this->_user = self::findOne(['username' => $this->username, 'pwd' => md5($this->pwd), 'status' => 0]); //查询,保存查询结果
if ($this->_user) { //登陆成功
//记录上次登录时间
\Yii::$app->session->set('login_time', $this->_user->login_time); //使用session
//更新数据,登录时间,登录次数,登录IP
self::updateAll(['login_time' => time(), 'login_num' => ($this->_user->login_num + 1), 'ip' => \Yii::$app->request->getUserIP()], ['username' => $this->username]);
} else {
$this->addError($attribute, '用户名或密码错误!');
}
}
//验证登录信息,保存登录状态
public function login() {
if ($this->validate()) { //使用rules定义的规则进行验证
//保存登录信息(有效期1个月)
return \Yii::$app->user->login($this->_user, $this->rel ? 3600 * 24 * 30 : 0); //参数:用户对象,有效期单位秒
} else { //验证失败
return false;
}
}
//以下就是固定格式,必须在验证模型中,实现接口中定义的方法
/**
* @return int|string 当前用户ID
*/
public function getId() {
return $this->id;
}
/**
* 根据给到的ID查询身份。
*
* @param string|integer $id 被查询的ID
* @return IdentityInterface|null 通过ID匹配到的身份对象
*/
public static function findIdentity($id) {
return static::findOne($id);
}
/**
* 根据 token 查询身份。不使用token认证,方法体内代码可以删除
*
* @param string $token 被查询的 token
* @return IdentityInterface|null 通过 token 得到的身份对象
*/
public static function findIdentityByAccessToken($token, $type = null) {
return static::findOne(['access_token' => $token]);
}
/**
* 表中要有auth_key字段(值随机生成),用于加密cookie使用
* @return string 当前用户的(cookie)认证密钥,
*/
public function getAuthKey() {
return $this->auth_key;
}
/**
* @param string $authKey
* @return boolean 判断当前认证秘钥是否过期
*/
public function validateAuthKey($authKey) {
return $this->getAuthKey() === $authKey;
}
}
6、控制器中的原生与Yii框架写法
<?php
namespace frontend\controllers;
use yii\web\Controller;
use frontend\models\Test;//引入AR类
echo "<meta charset='utf-8'/>";
class TestController extends Controller{
//行为方法,用于授权,写法固定
public function behaviors() {
return [
'access' => [ //访问控制
'class' => AccessControl::className(),
'rules' => [ //规则
[
'allow' => false, //false是拒绝
'roles' => ['?'], // 匹配访客用户(未经认证)
],
[
'allow' => true, //true是允许
'roles' => ['@'], //匹配已认证用户
],
],
],
];
}
//显示新闻列表
public function actionNews($keyword = null, $typeid = 0) {
$news = News::find(); //相当于连接这个模型的对应表,类似于TP框架中的M('News');
//添加搜索条件
if (!empty($keyword)) { //添加模糊搜索
$news->andWhere(['like','title',$keyword]); //添加一个条件用And拼接,orWhere/或
}
if (!empty($typeid)) { //添加分类
$news->andWhere(['typeid' => $typeid]); //添加一个条件用And拼接
}
//分页
$count = $news->count(); //表总记录数
$page = new Pagination(['totalCount' => $count, 'pageSize' => 2]); //分页类,计算limit
$list = $news->orderBy('newsid desc')
->offset($page->offset) //偏移量,从哪行开始取limit(0,2)
->limit($page->limit) //取几行
->all();
//加载视图,传递数据给视图使用
return $this->render('news',['list' => $list, 'page' => $page, 'keyword' => $keyword, 'typeid' => $typeid]);
}
//执行原生SQL
public function actionTestdb($id = 1){
//添加数据,直接在浏览器地址栏输入控制器及动作即可添加到数据库,以下相同
//echo \Yii::$app->db->createCommand("insert into msg(title,sex,tel,lxr,content,ip,status,add_time) values('标题','先生','17245678944','张三','留言内容123','127.0.0.1','0','".time()."')")->execute();
//修改数据
//echo \Yii::$app->db->createCommand("update msg set lxr='熊二' where msgid=5")->execute();
//删除数据
//echo \Yii::$app->db->createCommand("delete from msg where msgid=11")->execute();
//查询数据
//$list = \Yii::$app->db->createCommand("select * from msg")->queryAll(); //查询所有数据,返回二维数组
//$list = \Yii::$app->db->createCommand("select * from msg where msgid=5")->queryOne(); //查询一条数据,返回一维数组
$list = \Yii::$app->db->createCommand("select * from msg where msgid>:id")->bindValue(':id',$id)->queryAll(); //绑定参数,为了防止SQL注入攻击,可以使用此方式
var_dump($list);
}
//测试AR模型
public function actionTestAR(){
// $model = new Test(); //头部namespace下需要加use frontend\models\Test;
// //写入数据
// //属性对应表中字段
// $model->title = '主题';
// $model->sex = '女士';
// $model->tel = '1324567899';
// $model->lxr = '熊三';
// $model->content = '1111内容';
// $model->ip = '127.0.0.1';
// $model->status = '0';
// $model->add_time = time();
// $model->save(); //保存数据,同$model->insert()
// //修改数据
// $model1 = Test::findOne(1); //修改一条数据,主键=1。
// $model1->title = '主题';
// $model1->save(); //保存数据,同$model->update()
// Test::updateAll(['title' => '主题'],'msgid > 1'); //修改多条数据
// //删除数据
// Test::findOne(5)->delete(); //删除一条数据
// Test::deleteAll("msgid IN(10,16)"); //删除所有符合条件的数据
// //查询数据
// $msg = Test::find()->where(['status' => 0])->orderBy('msgid desc')->all();//查询所有符合条件的数据
// var_dump($msg);
// $msg = Test::find()->where(['status' => 0])->orderBy('msgid desc')->one();//查询一条数据
// var_dump($msg);
$msg = Test::find() //查询
->select(['msgid','title']) //选择显示字段
->where('status=:status',[':status' => 0]) //条件绑定方式
->limit(2) //取数
->orderBy('msgid desc') //排序
->asArray() //以数组方式返回结果
->all(); //获取所有符合条件的数组
var_dump($msg);
}
//产品列表及分页
public function actionProduct() {
$product = Product::find();
$count = $product->count();
$page = new Pagination(['totalCount' => $count, 'pageSize' => 6]);
$list = $product->orderBy('id desc')
->offset($page->offset) //偏移量
->limit($page->limit)
->all();
return $this->render('product', ['list' => $list, 'page' => $page]);
}
//产品详细
public function actionInfo($id = 0) {
$info = Product::findOne($id);
if (empty($info)) {
return $this->goHome();
}
//更新数量
$info->updateCounters(['show_num' => 1]);
return $this->render('product_show', ['info' => $info]);
}
}
7、视图中的写法
循环输出及跳转并传值:
<ul>
<?php foreach ($list as $val) { ?>
<li><a href="<?= Url::to(['info', 'id' => $val->id]) ?>"><s><img src="<?= $val->pic ?>" /></s><span><?= mb_substr($val->title, 0, 15, 'utf-8'); ?></span></a></li>
<?php } ?>
</ul>
分页:
<div class="message">共<i class="blue"><?= $page->totalCount; ?></i>条记录,当前显示第 <i class="blue"><?= $page->getPage()+1; ?>/<?= $page->getPageCount(); ?> </i>页</div>
<?= LinkPager::widget(['pagination' => $page, 'maxButtonCount' => 6, 'nextPageLabel' => '下一页', 'prevPageLabel' => '上一页', 'firstPageLabel' => '首页', 'lastPageLabel' => '尾页']); ?>
获取所有分类(视图中也可直接查询):
$cat = backend\models\Category::find()->all();
Ajax为post类型时必须带令牌:
<script>
$(function () {
$('#selectAll').click(function() {
$('#list').find('input[type=checkbox]').attr('checked', $(this).prop('checked'));
});
//提交删除
$('#selectdel').click(function () {
var valArr = new Array;
$('#list :checkbox[checked]').each(function (i) {
valArr[i] = $(this).val();
});
var vals = valArr.join(','); // 方法用于把数组中的所有元素放入一个字符串。//1,2,3
if (vals == ''){
alert('id未获取到');
return;
}
//AJAX提交到PHP中处理
$.ajax({
url: '<?= Url::to(['news/select-del']); ?>',
type: 'post',
data: {'ids': vals, '<?= \Yii::$app->request->csrfParam; ?>':'<?= \Yii::$app->request->csrfToken; ?>'}, //post需要加令牌
dataType: 'text',
success: function (d) {
if (d == 1) { //删除成功
window.location.reload(); //刷新当前页
} else if (d == 2) { //删除失败
alert('删除失败');
} else if (d == 3) { //未登录
window.location.href = 'login.html';
}
}
});
});
});
</script>
还没有评论,来说两句吧...