置顶 讨论
为了便于用户理解,推出部分教程支持视频 选择有视频的课程,即可在教程文章中看到视频 登录后才可以观看哦
6月前 喜欢(4) 浏览(1311) 评论(0)
博客
基础 Gridview 插件被应用于数据呈现,它提供了很多功能,如浏览、排序、分页和数据过滤。 下面是一个简单的 Gridview 应用实例: <?= GridView::widget([ 'dataProvider' => $dataProvider, 'columns' => [ 'id', 'name', 'created_at:datetime', // ... ], ]) ?> 用法示例 1.在例头添加排序,在cloumns中加入以下代码 ['class' => 'yii\grid\SerialColumn'] 2.列表勾选框,在cloumns中加入以下代码 ['class' => 'yii\grid\CheckboxColumn'], 3.列数据快速格式化:时间戳转化为时间格式显示 'created_at:datetime', 4.显示关联表数据:前提是在model中有关联关系,例如:getAuthor() 'author.name', //获取关联表author的name的值 5.列表中显示图片:显示一张50*100的图片,label_img为图片地址 'label_img'=>[ 'label' => '标签图', 'format' => [ 'image', [ 'height' =>50, 'width' => 100 ] ], 'value' => function($model){ return $model->label_img; } ], 6.显示状态,且带过滤 [ 'attribute' => 'is_valid', 'label' => '发布状态', 'value' => function($model) { return $model->is_valid == 0 ? '未发布' : '发布'; }, 'filter' => [ 0 => '未发布', 1 => '发布' ] ], 7.显示带html标签的例值:正常情况下是过滤html标签的 [ 'attribute' => 'content', 'format' => 'raw', 'value' => function ($model) { return $model->content; }, ], 8.自定义按钮:{view} {update} {delete} 为默认,可以不填显示默认,也可以覆盖重新定义 [ 'class' => 'yii\grid\ActionColumn', 'template' => '{test} {view} {update} {delete}', 'header' => '操作', 'buttons' => [ 'test' => function ($url, $model, $key) { return Html::a('测试按钮', $url, ['data-method' => 'post','data-pjax'=>'0'] ); }, 'delete'=> function ($url, $model, $key){ return Html::a('删除', ['delete', 'id'=>$model->id],[ 'data-method'=>'post', //POST传值 'data-confirm' => '确定删除该项?', //添加确认框 ] ) ; } ], ], 9.修改列表顶部分页信息 //{begin}:当前列的第一个元素序号 //{end}:当前页的最后一个元素序号 //{count}:当前页的元素总数 //{totalCount}:所有元素总数 //{page}:当前页 //{pageCount}:总页数 <?= GridView::widget([ 'dataProvider' => $dataProvider, 'summary' => '第{begin}-{end}页,共计{totalCount}篇文章', ... 以上为gridview的一些基本操作,当然还有很多其他情景,但要活学活用,举一反三
精华贴
9月前 喜欢(4) 浏览(1213) 评论(2)
置顶 博客
介绍 变更概述 Yii3 composer 包 运行您的第一个 Yii3 驱动的应用程序 介绍 本文档适用于已熟悉Yii2的读者。 这意味着将所有与Yii 3相关的信息集中在一个地方,以便更容易走上正轨。 Yii 3是Yii框架的第二次重写。 最初从2.1分支开始,后来因为所有向后兼容性破坏而决定切换到3.X系列。 从3.0开始,Yii将遵循Sementic Versionning。 这个重写解决了Yii 2遭受的许多问题,比如框架与jQuery,bower,bootstrap相结合。 [TODO:添加更多关于Yii2的grieff] 变更概述 以下是Yii 3中的主要更改。您可以查看完整的CHANGELOG以获取详尽的列表。 源代码分裂 框架源代码已被拆分为多个包,并且在其核心级别,Yii不再对您的开发堆栈或您将使用的功能进行假设。 这使您可以选择组成应用程序所需的软件包。 这种重组也是维护的好消息,因为这些包将单独发布,从而允许更频繁的更新。 自动加载 已删除自定义PHP类自动加载器,以支持 Composer 的 PSR-4 实现。 这意味着为了让Yii看到你的类,你必须在 composer.json 中显式注册你的命名空间。 我们稍后会看到一个例子。 PSR兼容性 通过实现以下PSR,Yii 3在 PHP-FIG 建议之后采取了一些积极的步骤: 现在,日志记录符合PSR-3 缓存现在符合PSR-16 依赖注入现在符合PSR-11 应用配置 如果您曾经使用Yii 2安装了扩展程序,您可能/当然已经找到了自己的扩展 README 文件,在您自己的config/ main.php文件中查找要复制/粘贴的配置块。 这通常会导致: 一个巨大的配置文件(您可能决定将其拆分为较小的文件) 当使用新的/更改的配置选项重新发布新版本的扩展时,将更新非平凡配置。 Yii3 采用了另一种方法。 每个软件包捆绑自己的配置,可能会开箱即用。 如果需要,您可以从配置文件中覆盖它们。 这一切都是通过利用 hiqdev/composer-config-plugin composer插件完成的,该插件在您运行 composer dump-autoload(也称为composer du)时负责扫描和合并所有配置。 您可以阅读 Yii2 projects alternative organization,以深入解释 hiqdev/composer-config-plugin 背后的动机。 软件包作者将有责任通过严格的版本化版本来避免引入BC中断。 依赖注入 ... Yii3 composer 包 以下是Yii 3中引入的新软件包,可在此官方列表中找到。 我们简要介绍一下: 框架 yiisoft/yii-core 这是Yii的新内核。 它定义了基本框架及其核心功能,如行为,i18n,邮件,验证... 您很少想直接安装 yiisoft/yii-core。 相反,您将安装以下一项或多项: yiisoft/yii-console yiisoft/yii-web yiisoft/yii-rest 这三个包被视为扩展,负责实现它们所指的每个“通道”的基本功能: yii-console 实现了构建控制台应用程序所需的一切(命令的基本控制器,命令助手,...) yii-web 实现了构建Web应用程序所需的一切(资产管理,会话,请求处理..) yii-rest 实现了构建REST接口所需的一切(ActiveController,..) 库 在Yii 3中,库不依赖于Yii,并且可以在框架之外使用。 他们的包名是 yiisoft/ 没有yii-prefix的东西。 yiisoft/log:日志库 yiisoft/di:依赖注入库 yiisoft/cache:缓存库 yiisoft/active-record:Active Record库 yiisoft/rbac:角色基本访问控制库 yiisoft/view:视图渲染库 yiisoft/mutex:互斥锁实现 yiisoft/db:数据库库 yiisoft/db 的驱动程序 DB的各种驱动程序也已分为包: yiisoft/db-mysql MySQL支持Yii yiisoft/db-mssql 对Yii的MSSQL支持 yiisoft/db-pgsql PostgreSQL支持Yii yiisoft/db-sqlite 对Yii的SQLite支持 yiisoft/db-oracle Oracle 数据库支持 yiisoft/db-sphinx Sphinx支持 yiisoft/db-redis Redis支持 yiisoft/db-mongodb MongoDB支持 yiisoft/db-elasticsearch Elatic 支持 扩展 扩展取决于(至少)yii-core。 除了上面已经遇到的3个扩展(yii-console,yii-web,yii-api),这些包都可用 开发环境扩展 yiisoft/yii-debug 调试面板 yiisoft/yii-gii 代码生成器扩展 yiisoft/yii-dev 用于框架贡献者的工具 页面渲染扩展 yiisoft/yii-twig Twig Extension 数据渲染 yiisoft/yii-dataview:ListView,GridView,DetailView JS&CSS框架集成 yiisoft/yii-bootstrap3:Bootstrap3 资源和小部件 yiisoft/yii-bootstrap4:Bootstrap4 资源和小部件 yiisoft/yii-jquery jQuery,ActiveForm 小部件 yiisoft/yii-captcha CAPTCHA扩展 yiisoft/yii-masked-input:屏蔽输入小部件(取决于jquery) 杂项 yiisoft/yii-swiftmailer Swift Mailer Extension yiisoft/yii-http-client HTTP客户端扩展 yiisoft/yii-auth-client 外部身份验证扩展 Yii项目模板和基础应用程序 yiisoft/yii-project-template 这是一个非常基本的Yii项目模板,您可以使用它来开始开发。 您可能希望选择这三个启动器中的一个或多个以在下一个项目中安装: yiisoft/yii-base-cli yiisoft/yii-base-web yiisoft/yii-base-api 让我们尝试在下一节中运行Web基础模板。 运行您的第一个 Yii3 驱动的应用程序 让我们尝试使用 Yii3 和提供的项目模板运行Web应用程序。 安装项目模板 composer create-project --prefer-dist --stability=dev yiisoft/yii-project-template myapp cd myapp 这是创建的结构: . ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── config │ ├── common.php │ └── params.php ├── docker-compose.yml ├── hidev.yml ├── public │ ├── assets │ ├── favicon.ico │ ├── index.php │ └── robots.txt ├── runtime └── vendor 您将无法使用./vendor/bin/yii serve 立即启动Web服务器,因为它会抱怨不知道“app”类。 实际上,此项目模板仅在您的应用程序中引入最低限度:缓存,依赖项注入和日志记录。 模板不会对您正在构建的应用程序类型(web,cli,api)做出假设。 你可以从头开始使用这个裸模板,选择你想要使用的扩展和包并开始开发,或者你可以选择提供的三个启动器中的一个。 安装Web启动器 由于我们正在进行Web应用程序,因此我们需要一个资产管理器。 我们可以选择其中一个: Asset-packagist和composer-merge-plugin(仅需要PHP) Foxy (要求 npm 或 yarn) 让我们选择Foxy(个人品味,因为composer 来自 Tunisia 的速度很慢): composer require "foxy/foxy:^1.0.0" 我们现在可以安装 yii-base-web 启动器并运行我们的应用程序: composer require yiisoft/yii-base-web vendor/bin/yii serve 通过访问 http://localhost:8080/ 您现在应该看到如下内容: 检查我们的项目结构,除了创建这三个条目之外,没有什么真正改变: node_modules/ package-lock.json package.json 那么我们在浏览器中看到的内容来自哪里? 探索 yiisoft/yii-base-web结构: 如果您浏览vendor/yiisoft/yii-base-web中的文件夹,您将看到该模板实际上是一个项目本身,具有以下结构: . ├── LICENSE.md ├── README.md ├── composer.json ├── config │ ├── common.php │ ├── console.php │ ├── env.php │ ├── messages.php │ ├── params.php │ └── web.php ├── phpunit.xml.dist ├── public │ └── css │ └── site.css ├── requirements.php ├── runtime └── src ├── assets │ └── AppAsset.php ├── commands │ └── HelloController.php ├── controllers │ └── SiteController.php ├── forms │ ├── ContactForm.php │ └── LoginForm.php ├── mail │ └── layouts ├── messages │ ├── et │ ├── pt-BR │ ├── ru │ └── uk ├── models │ └── User.php ├── views │ ├── layouts │ └── site └── widgets └── Alert.php 如果您已经使用Yii2和基本模板开发了应用程序,那么文件夹和文件应该对您有意义。
精华贴
6月前 喜欢(3) 浏览(6572) 评论(9)
博客
required : 必须值验证属性||CRequiredValidator 的别名, 确保了特性不为空. [['字段名1','字段名2'],required] //字段1 2 必填 [['字段名'],required,'requiredValue'=>'必填值','message'=>'提示信息']; email : 邮箱验证||CEmailValidator 的别名,确保了特性的值是一个有效的电邮地址. ['email', 'email']; match : 正则验证||CRegularExpressionValidator 的别名, 确保了特性匹配一个正则表达式. [['字段名'],'match','pattern'=>'正则表达式','message'=>'提示信息']; [['字段名'],'match','not'=>ture,'pattern'=>'正则表达式','message'=>'提示信息']; /*正则取反*/ url : 网址||CUrlValidator 的别名, 确保了特性是一个有效的路径. ['website', 'url', 'defaultScheme' => 'http']; captcha(验证码)||CCaptchaValidator 的别名,确保了特性的值等于 CAPTCHA 显示出来的验证码. ['verificationCode', 'captcha']; safe : 安全 ['description', 'safe']; compare :(比较) CCompareValidator 的别名, 确保了特性的值等于另一个特性或常量. ['repassword', 'compare', 'compareAttribute' => 'password','message'=>'两次输入的密码不一致!'], //compareValue:比较常量值 operator:比较操作符 ['age', 'compare', 'compareValue' => 30, 'operator' => '>=']; default : 默认值||CDefaultValueValidator 的别名, 为特性指派了一个默认值. ['age', 'default', 'value' => null]; exist : 存在||CExistValidator 的别名, 确保属性值存在于指定的数据表字段中. ['字段名', 'exist']; file : 文件||CFileValidator 的别名, 确保了特性包含了一个上传文件的名称. ['primaryImage', 'file', 'extensions' => ['png', 'jpg', 'gif'], 'maxSize' => 1024*1024*1024] filter : 滤镜||CFilterValidator 的别名, 使用一个filter转换属性. //'skipOnArray' => true 非必填 [['username', 'email'], 'filter', 'filter' => 'trim', 'skipOnArray' => true]; in : 范围||CRangeValidator 的别名, 确保了特性出现在一个预订的值列表里. ['level', 'in', 'range' => [1, 2, 3]]; unique : 唯一性||CUniqueValidator 的别名, 确保了特性在数据表字段中是唯一的. ['字段名', 'unique'] 补充:联合唯一索引rule规则 [ ['app_id', 'group_id'], 'unique', 'targetAttribute' => ['app_id', 'group_id'], 'message' => 'app_id和group_id已经被占用!' ], integer : 整数 ['age', 'integer']; number : 数字 ['salary', 'number']; double : 双精度浮点型 ['salary', 'double']; date : (日期) [['from', 'to'], 'date']; string : 字符串 ['username', 'string', 'length' => [4, 24]]; boolean : 是否为一个布尔值||CBooleanValidator 的别名 ['字段名', 'boolean', 'trueValue' => true, 'falseValue' => false, 'strict' => true]; image :是否为有效的图片文件 [ 'primaryImage', 'image', 'extensions' => 'png, jpg', 'minWidth' => 100, 'maxWidth' => 1000, 'minHeight' => 100, 'maxHeight' => 1000 ] each:遍历,ids 和 product_ids 是数字的集合 [['ids', 'product_ids'], 'each', 'rule' => ['integer']], 自定义rules: ['password', 'validatePassword'], /** * Validates the password. * This method serves as the inline validation for password. * * @param string $attribute the attribute currently being validated * @param array $params the additional name-value pairs given in the rule */ public function validatePassword($attribute, $params) { if (!$this->hasErrors()) { $user = $this->getUser(); if (!$user || !$user->validatePassword($this->password)) { $this->addError($attribute, '账号或者密码错误!'); } } }
9月前 喜欢(3) 浏览(1109) 评论(2)
讨论
在提问的时候,适当使用一些小技巧,会让老师快速get到你的问题在哪里,这样会使问题更快被解答喔~ 提问技巧 标题:简洁、易懂,完整表达主题;避免无意义、模糊、口语化标题。 提问内容: 客观描述问题:中性客观描述问题,保证问题的可读性,避免过于简单或模糊; 提供编程环境:问题描述注明编程环境信息,包括操作系统、语言、使用的软件版本等; 输出报错信息:过程中出现异常的话,需提供重现异常的步骤; 输出错误信息:编码过程中的技术问题出现错误应该输出日志或控制台的全部信息,以便更好排查错误; 注明课程时间:针对课程的问题,请在问题描述中注明出现时间,便于及时解答; 排版规范合理:注意文本,代码,标点、语法使用规范,排版合理。 提倡有偿问答:对于有能力的学者,可以提供有偿提问,勾引大神们快速响应(提问者自愿为主,答题者不可强求) 注意: 不要在提问内容框里长篇粘入代码,只需粘出关键代码并加以描述即可 标题不等于提问内容,标题应简明扼要,提问内容应详细描述,二者尽量不要重复。 提问尽量以 PHP/Yii2.0 的内容为主。 千万不要贴一段业务报错代码,问为什么这里报错了,代码调试可以帮您解决大部分的问题。 学员和老师要互相尊重,尊重是有效解决问题的前提,对于人身攻击的问题管理员是有权隐藏的哦~ 说完了如何提问,那么大!神!般!的你在问答区看到了其他小伙伴提出的问题,想要回答时需要注意些什么呢?^_^ 回答建议: 回答保证内容的准确性,不模糊,能实际解决提问者疑问; 回答保证内容通俗易懂,语句通顺、有条理,排版利于阅读; 回答保证内容全面,避免过于简单,可对回答做详细阐释、扩展和引导; 回答保证内容与问题相关,避免所问非所答和过多的重复内容; 添加图片或代码应附上说明,代码用对应代码块包裹并合理排版; 核心思想:要持着“授人以鱼不如授人以渔”的心来回答提问者的问题~
9月前 喜欢(3) 浏览(1414) 评论(4)
博客
Yii2.0 RESTful API 之版本控制 之前我写过两篇关于 Yii2.0 RESTful API 如何搭建,以及 认证 等处理,但是没有涉及到版本管理,今天就来谈谈版本管理如何实现。 索性就从头开始一步一步搭建吧,但是关于一些概念以及使用本篇就不一一解释了,可以参考 第一篇 Yii2.0 RESTful API 基础配置教程 进行配置 安装Yii2.0 通过 Composer 安装 这是安装Yii2.0的首选方法。如果你还没有安装 Composer,你可以按照这里的说明进行安装。 安装完 Composer,运行下面的命令来安装 Composer Asset 插件: composer global require "fxp/composer-asset-plugin:^1.2.0" 安装高级的应用程序模板,运行下面的命令: composer create-project yiisoft/yii2-app-advanced yii-api 2.0.14 拷贝backend目录,命名为api 打开api\config\main.php 修改id,controllerNamespace: return [ 'id' => 'app-api', 'basePath' => dirname(__DIR__), 'controllerNamespace' => 'api\controllers', ] 初始化高级模板 在初始化之前不妨先看下这篇文章 cd advanced php init 打开common\config\main.php开启url路由美化规则 'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => [ ], ], 打开common\config\bootstrap.php添加以下别名 Yii::setAlias('@api', dirname(dirname(__DIR__)) . '/api'); ok,以上工作准备完毕,接下来进入正题, 关于版本更多介绍可以参考 权威指南 ,这里不过多解释(PS:主要我也不会......) 我的理解: Yii2 的版本你可以理解为不同的模块,每一个版本就是一个新的模块,比如常见的v1,v2等。 模块的搭建 关于如何生成模块,我们可以使用GII来进行生成. 配置 GII 打开 api/config/main-local.php 文件 修改如下: if (!YII_ENV_TEST) { // configuration adjustments for 'dev' environment $config['bootstrap'][] = 'debug'; $config['modules']['debug'] = [ 'class' => 'yii\debug\Module', ]; $config['bootstrap'][] = 'gii'; $config['modules']['gii'] = [ 'class' => 'yii\gii\Module', 'allowedIPs' => ['127.0.0.1', '*'] ]; } 我这里因为使用的是 Homestead ,默认是不允许访问 GII 的,所以得加上'allowedIPs' => ['127.0.0.1', '*'] ,否则会出现 Forbidden (#403), 你可以根据自己的需要来进行配置,或者不配置 生成Modules 浏览器中输入 http://your host/gii ,可以看到 Module Generator ,点击 Start Modules Class 中输入:api\modules\v1\Module Module ID 中输入v1,(一般会自动输入) 点击 Preview 最后点击 Generate 进行生成 配置模块 打开 api/config/main.php 文件,修改 modules 'modules' => [ 'v1'=>[ 'class'=>'api\modules\v1\Module', ], ], 接着修改 urlManager 'urlManager' => [ 'enablePrettyUrl' => true, 'enableStrictParsing' => true, 'showScriptName' => false, 'rules' => [ ['class' => 'yii\rest\UrlRule', 'controller' => 'v1/default', 'extraPatterns'=>[ 'GET index'=>'index', ], ], ], ], 基于以上,Yii2.0 RESTFul API 就实现了版本管理,我们可以通过如下地址进行访问: http://localhost/v1/defaults 多说一点,我上方的地址是已经映射到api/web目录,请根据自己的实际情况进行配置 打开刚生成的 modules 文件目录,可以看到里面存在一个 v1 的目录,可以看到该目录还有一个controllers,以及一个 views 目录 ,我们刚才访问的 defaults 其实就是这两个文件,和传统的web项目一样控制器渲染视图 好了,你可能知道了,我们以后的控制器代码就放到 modules/v1/controllers 里了 刚才仅仅是默认GII为我们生成的代码,因为我们是API,所以 views 目录,我们一般情况下用不到。 新建一个 rest 的控制器 在 modules\v1\controllers 下新建 UserController <?php namespace api\modules\v1\controllers; use yii\rest\Controller; /** * User controller for the `v1` module */ class UserController extends Controller { /** * @return string */ public function actionIndex() { return 'this is v1/user'; } } 修改 api/config/main.php 中的urlManager 'urlManager' => [ 'enablePrettyUrl' => true, 'enableStrictParsing' => true, 'showScriptName' => false, 'rules' => [ ['class' => 'yii\rest\UrlRule', 'controller' => 'v1/default', 'extraPatterns'=>[ 'GET index'=>'index', ], ], ['class' => 'yii\rest\UrlRule', 'controller' => 'v1/user', 'extraPatterns'=>[ 'GET index'=>'index', ], ], ], ], 试着访问下 http://localhost/v1/users/index ok,以上就是 Yii2.0 版本管理的实现方式 格式化响应 修改 api/config/main.php 在components 数组中添加 response 'response' => [ 'class' => 'yii\web\Response', 'on beforeSend' => function ($event) { $response = $event->sender; $response->data = [ 'success' => $response->isSuccessful, 'code' => $response->getStatusCode(), 'message' => $response->statusText, 'data' => $response->data, ]; $response->statusCode = 200; }, ], 至此关于 Yii2.0 RESTFul API 我一共完成了 3 篇文章,分别为: Yii2.0 RESTful API 基础配置教程 Yii2.0 RESTful API 认证教程 Yii2.0 RESTful API 之版本控制 写得实在不怎么样,您如果看了有收获,不妨留言给个评论,或者您觉得写得有问题,或者不明白,也可以留言,我们可以一块探讨研究。
6月前 喜欢(2) 浏览(604) 评论(1)
博客
场景 网站 https 已经成为一种趋势,那么作为个人站长如何用廉价的方式使自己的网站实现 https?阿里云推出了免费 SSL 证书,是众多个人站长的福音,那么我们就以阿里云作为示例,来演示一下如何实现全站 https 。 购买免费的 SSL 证书 推荐在域名购买的账户进行购买SSL证书(可以免去很多认证的步骤)。 注意啊,上面可不是让你买收费证书。因为免费证书默认看不到,请按图中红字和箭头进行选择: 1. 先选Symantec 2. 选1个域名 就会变成下图了 然后购买完成即可。详细申请步骤 nginx 配置 在证书控制台下载 Nginx 版本证书。下载到本地的压缩文件包解压后包含: 在Nginx的安装目录下创建cert目录,并且将下载的全部文件拷贝到cert目录中。如果申请证书时是自己创建的CSR文件,请将对应的私钥文件放到cert目录下并且命名为a.key; 打开 Nginx 安装目录下 conf 目录中的 nginx.conf 文件,找到: # HTTPS server # #server { # listen 443; # server_name localhost; # ssl on; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_timeout 5m; # ssl_protocols SSLv2 SSLv3 TLSv1; # ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; # ssl_prefer_server_ciphers on; # location / { # # #} #} 将其修改为 (以下属性中ssl开头的属性与证书配置有直接关系,其它属性请结合自己的实际情况复制或调整) : server { listen 443; server_name www.yii-china.com; ssl on; root /var/www; # 项目根目录 index index.php index.html index.htm; location / { try_files $uri $uri/ @rewrite; } location @rewrite { rewrite ^(.*)$ /index.php$1 last; } ssl_certificate cert/a.pem; ssl_certificate_key cert/a.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; location ~ \.php { fastcgi_pass 127.0.0.1:9000; include fastcgi_params; fastcgi_split_path_info ^(.+?\.php)(.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_REANSLATED $document_root$fastcgi_path_info; } } 然后设置一下http 自动转 https server { listen 80; server_name www.yii-china.com; rewrite ^(.*) https://$server_name$1 permanent; ... 以上操作即可实现全站 https 。
7月前 喜欢(2) 浏览(1079) 评论(4)
博客
目的 通过了解binlog日志的相关配置,简单掌握通过binlog对数据库进行数据恢复操作; mysql 日志文件 任何成熟软件都会有一套成熟的日志系统,当软件出现问题时,这些日志就是查询问题来源的宝库。同样,mysql也不例外,也会有一系列日志记录mysql的运行状态。 mysql主要有以下几种日志: 错误日志:记录mysql运行过程中的错误信息 一般查询日志:记录mysql正在运行的语句,包括查询、修改、更新等的每条sql 慢查询日志:记录查询比较耗时的SQL语句 binlog日志:记录数据修改记录,包括创建表、数据更新等 这些日志均需要在my.cnf文件进行配置,如果不知道mysql的配置文件路径,可以使用mysql命令进行查找, mysql --verbose --help|grep -A 1 'Default options’ #该命令会罗列出my.cnf顺序查找的路径。 binlog日志 binlog就是binary log,二进制日志文件,记录所有数据库更新语句,包括表更新和记录更新,即数据操纵语言(DML),binlog主要用于数据恢复和配置主从复制等; 数据恢复:当数据库误删或者发生不可描述的事情时,可以通过binlog恢复到某个时间点的数据。 主从复制:当有数据库更新之后,主库通过binlog记录并通知从库进行更新,从而保证主从数据库数据一致; mysql按照功能分为服务层模块和存储引擎层模块,服务层负责客户端连接、SQL语句处理优化等操作,存储引擎层负责数据的存储和查询;binlog属于服务层模块的日志,即引擎无关性,所有数据引擎的数据更改都会记录binlog日志。当数据库发生崩溃时,如果使用InnoDB引擎,binlog日志还可以检验InnoDB的redo日志的commit情况。 binlog日志开启 日志开启方式: 1、添加配置 log_bin=ON log_bin_basename=/path/bin-log log_bin_index=/path/bin-log.index 2、仅仅设置log-bin参数 log-bin=/path/bin-log 当开启binlog日志之后,mysql会创建一个 log_bin_index指定的 .index 文件和多个二进制日志文件,index中按顺序记录了mysql使用的所有binlog文件。binlog日志则会以指定的名称(或默认值) 加自增的数字作为后缀,ex:bin-log.000001,当发生下述三种情况时,binlog日志便会进行重建: 文件大小达到max_binlog_size参数的值 执行 flush logs命令 重启mysql服务 binlog 日志格式 通过参数binlog_format参数的值,可以设置binlog的格式,可选值有 statement、row、mixed * statement格式:记录数据库执行的原始SQL语句 * row格式:记录具体的行的修改,这个为目前默认值 * mixed格式:因为上边两种格式各有优缺点,所以就出现了mixed格式 binlog日志查看工具:mysqlbinlog 因为binlog是二进制文件,不能像其他文件一样,直接打开查看。但mysql提供了binlog查看工具mysqlbinlog,可以解析二进制文件。当然不同格式的日志解析结果是不一样的; 1. statement格式日志,执行mysqlbinlog /path/bin-log.000001,可以直接看到原始执行的SQL语句 2. row格式日志,则可读性没有那么好,但仍可通过参数使文档更加可读 mysqlbinlog -v /path/bin-log.000001 mysqlbinlog两对非常重要的参数 1. --start-datetime --stop-datetime 解析某一个时间段内的binlog; 2. --start-position --stop-position 解析在两个position之间的binlog; 使用binlog恢复数据: 使用binlog恢复数据,本质上就是通过binlog找到所有DML操作,去掉错误的SQL语句,然后重走一遍长征路,就可以将数据恢复; 线下实操: 创建数据表并插入初始值 CREATE TABLE `users` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `age` int(8) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO `users` (`id`, `name`, `age`) VALUES (null, '姓名一', 5); 找到上一次全量备份的数据库和binlog的position(ps:当然也可以通过时间进行恢复)。此处以目前状态作为备份的初始值, mysqldump -uroot -p T > /path/xxx.sql; # 备份数据库 show master status; # 查看当前的position位置,此时值为154 插入多条记录 INSERT INTO `users` (`id`, `name`, `age`) VALUES (null, '姓名二', 13), (null, '姓名三', 14), (null, '姓名四', 15), (null, '姓名五', 16), (null, '姓名六', 17); 进行误操作,并且在误操作之后又插入几条数据 update users set age = 5; INSERT INTO `users` (`id`, `name`, `age`) VALUES (null, '姓名七', 16), (null, '姓名八', 18); 发现误操作之后,进行数据恢复,首先停止mysql对外的服务,利用备份数据恢复到上次数据; 通过mysqlbinlog命令对二进制文件进行分析,分析发现 误操作发生在position为706位置,且上次正常操作的结束位置在513 在1152到结尾位置有正常执行的SQL执行 通过mysqlbinlog命令从binlog日志中导出可执行的SQL文件,并将数据导入到mysql mysqlbinlog --start-position=154 --stop-position=513 bin-log.000001 > /path/bak.sql; mysql -uroot -p < /path/bak.sql; 跳过错误的更新语句,再通过步骤7的逻辑把后续正常语句重新跑一遍,完成数据恢复工作 小结 无论什么时间,数据库发生崩溃都会令人愁眉紧锁,心烦意乱。binlog可以说是在各种情况下,数据库崩溃、数据丢失之后的一粒后悔药,本文通过线下环境,简单的对数据库进行了一次数据恢复实验,如有不对,还请指教 参考文章 http://www.ywnds.com/?p=12839 https://zhuanlan.zhihu.com/p/33504555
7月前 喜欢(2) 浏览(741) 评论(0)
博客
改动 就像当初 Yii2.0 时代降临 Yii1.0 终将灰暗,Yii3.0 版本推出势必掀起 Yii 框架的波澜,那么Yii3.0 相比 Yii2.0 究竟做了哪些改动呢? 一睹为快:Yii3.0 版本改动 Yii3.0 框架简介 Yii3.0 框架是一个骨架应用程序,最适合快速创建项目。 该框架包含基本功能,包括用户登录/注销和联系页面。它包括所有常用配置,使您可以专注于为应用程序添加新功能。 目录结构 config/ 包含应用配置 public/ 包含入口脚本,已发布的资源和其他公开可用的文件,例如favicon.ico和robots.txt runtime/ 包含运行时生成的文件 vendor/ 包含依赖的第三方包 .env .env.dist composer.json docker-compose.yml 要求 Web服务器支持PHP 7.1 是 Yii3.0 框架的最低要求。 安装 如果您没有 Composer,可以按照 getcomposer.org 上的说明进行安装。 然后,您可以使用以下命令安装此项目模板: composer create-project --prefer-dist --stability = dev yiisoft / yii-project-template myapp cd myapp 这为您提供了一个空项目,您可以添加应用程序模板,请参阅以下有关如何添加这些项目的部分。 根据您的系统,您可能需要为./runtime和./public/assets提供写入权限 CLI 应用 如果要安装运行自己的控制台命令所需的控制台应用程序,可以通过加载yiisoft / yii-base-cli 软件包来实现。 composer require yiisoft/yii-base-cli 您现在可以运行yii help来查看可用的命令。 API 应用 如果要创建API,可以通过加载 [yiisoft / yii-base-api](https://github.com/yiisoft/yii-base-api)包来实现 composer require yiisoft/yii-base-api vendor/bin/yii serve -p 8081 您可以通过http:// localhost:8081 /访问API。 Web 应用 由于Web应用程序使用客户端资源(例如CSS和Javascript),因此首先选择资源分配系统 方案a:Asset-packagist和composer-merge-plugin(只需要PHP) composer require "wikimedia/composer-merge-plugin" composer config repositories.ap '{"type": "composer", "url": "https://asset-packagist.org"}' composer config extra.merge-plugin.include "vendor/*/*/composer.assets.json" 方案b:Foxy (需要 npm 或者 yarn) composer require "foxy/foxy:^1.0.0" 现在,您可以安装Web应用程序库及其依赖项 composer require yiisoft/yii-base-web vendor/bin/yii serve 现在您应该可以通过http://localhost:8080/访问该应用程序。 您可以在 GitHub 上找到更多可用的应用程序库。 Docker 克隆存储库并创建环境配置文件 cp .env.dist .env 要运行安装,请从PHP映像创建bash docker-compose run --rm php bash 并运行上面的composer命令。 启动应用程序堆栈 docker-compose up -d 通过浏览器访问 http://docker.host:30080 配置 数据库 编辑数据库配置文件config/db.php,并添加真实的配置,例如: return [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=yii2basic', 'username' => 'root', 'password' => '1234', 'charset' => 'utf8', ]; 提示: - Yii不会为您创建数据库,必须先手动完成,然后才能访问它。 - 检查并编辑config /目录中的其他文件,根据需要自定义应用程序。 - 有关基本应用程序测试的信息,请参阅tests目录中的README。 测试 测试位于tests目录中。 直接从Docker镜像运行 docker run -it -v $PWD/yii-project:/app -w /app yiisoftware/yii2-php:7.2-apache bash
精华贴
7月前 喜欢(2) 浏览(4996) 评论(5)
博客
概念 把一个大型的单个应用程序和服务拆分为数个甚至数十个的支持微服务,它可扩展单个组件而不是整个的应用程序堆栈,从而满足服务等级协议。 传统的开发模式就是把所有功能都放在一个包里,基本不存在依赖,这样的优势在于开发简单,集中式管理,功能都在本地,不存在分布式的管理和调度消耗。但缺点也很明显:效率低,开发都在同一个项目改代码,相互等待,冲突不断。稳定性差,一个微小的问题,都可能导致整个应用挂掉。另外在资源利用上表现出明显的劣势,比如电商双11大促场景,下单压力非常大,评价的压力相对较少,那么我们希望临时增配应对双11的大流程,只能全部增配,而不能定点只对订单服务增配。所以微服务的架构开始慢慢流行并应用于大型的网站平台。 那么引入今天的主题,Yii 如何做微服务?Yii 可以轻松使用,而不需要基本和高级模板中包含的功能。换句话说,Yii 已经是一个微框架。不需要由模板提供的目录结构与 Yii 一起工作。 安装 Yii 为您的项目创建一个目录并将工作目录更改为该路径。示例中使用的命令是基于 Unix 的,但在 Windows 中也存在类似的命令。 mkdir micro-app cd micro-app Note:需要一些 Composer 的知识才能继续。如果您还不知道如何使用 composer,请花些时间阅读 Composer 指南。 使用您最喜爱的编辑器在 micro-app 目录下创建 composer.json 文件并添加以下内容: { "require": { "yiisoft/yii2": "~2.0.0" }, "repositories": [ { "type": "composer", "url": "https://asset-packagist.org" } ] } 保存文件并运行 composer install 命令。这将安装框架及其所有依赖项。 创建项目结构 安装框架之后,需要为此应用程序创建一个入口点。入口点是您尝试打开应用程序时将执行的第一个文件。出于安全原因,建议将入口点文件放在一个单独的目录中,并将其设置为Web根目录。 创建一个 web 目录并将 index.php 放入其中,内容如下: <?php // comment out the following two lines when deployed to production defined('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'); $config = require __DIR__ . '/../config.php'; (new yii\web\Application($config))->run(); 还要创建一个名为 config.php 的文件,它将包含所有的应用程序配置: <?php return [ 'id' => 'micro-app', //设置`micro-app`的根目录 'basePath' => __DIR__, // 控制器所在目录。 'controllerNamespace' => 'micro\controllers', // 设置命名空间为 micro 'aliases' => [ '@micro' => __DIR__, ], //默认访问地址 'defaultRoute' => 'home/index', 'components' => [ //请求配置 'request' => [ 'cookieValidationKey' => 'test&123456', 'parsers' => [ 'application/json' => 'yii\web\JsonParser', ] ], //Url 美化 'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'enableStrictParsing' => false, 'rules' => [ '<controller:\w+>/<action:\w+>/<id:\w+>' => '<controller>/<action>', ], ], //数据库配置 'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=micro', 'username' => 'root', 'password' => '数据库密码', 'charset' => 'utf8', ], ], ]; Info:尽管配置可以保存在 index.php 文件中,建议单独使用它。 这样它也可以用于控制台应用程序,如下所示。 您的项目现在已经准备进行编码了。尽管由您决定项目目录结构,只要您遵守命名空间即可。 创建第一个控制器 在创建控制器之前,创建一个 controllers/base 目录并创建一个基础控制器 BaseController。 <?php namespace micro\controllers\base; use yii\web\Controller; class BaseController extends Controller { //关闭 csrf 验证 public $enableCsrfValidation = false; } 然后在 controller 文件夹下面 新建一个 SiteController.php,这是默认的 控制器将处理没有路径信息的请求。 <?php namespace micro\controllers; use yii\web\Controller; class HomeController extends BaseController { public function actionIndex() { return '欢迎来到 Yii2.0 微服务!'; } } 如果您想为此控制器使用不同的名称,则可以配置 yii\base\Application::$defaultRoute 进行更改。 例如,对于 HomeController 将会是 'defaultRoute' => 'home/index'。 在这一点上,项目结构应该如下所示: micro-app/ ├── composer.json ├── config.php ├── web/ └── index.php └── controllers/ └── base └── BaseController.php └── HomeController.php └── vendor 如果您尚未设置 Web 服务器,则可能需要查看Web服务器配置文件示例。 另一种选择是使用 yii serve 命令,它将使用 PHP 内置 web 服务器。 您可以通过以下方式从 micro-app / 目录运行它: vendor/bin/yii serve --docroot=./web 在浏览器中打开应用程序URL现在应该打印出“欢迎来到 Yii2.0 微服务!”,它已经在 HomeController::actionIndex() 中返回。 Info:在我们的示例中,我们已将默认应用程序名称空间 app 更改为 micro, 以表明您不受此名称的限制(如果您是这样认为), 然后调整 controllers namespace 并设置正确的别名。
8月前 喜欢(2) 浏览(2057) 评论(2)
Wiki
查询一个作者(Author)写的所有书籍(Book),其中Author 和 Book 是对应的 Model 作者模型:Author Class Author extend \yii\db\ActiveRecord { ··· public function getBook() { return $this->hasMany(Book::className(), ['author_id'=>'id']); } ··· } 书籍模型:Book Class Author extend \yii\db\ActiveRecord { ··· } 查询一个id=1的作者的信息及其所写的所有书籍: $authorInfo = Author::find()->where(['id'=>1])->with('book')->one(); hasOne 是1对1,hasMany 是 1对多,写法基本一致;
8月前 喜欢(2) 浏览(1394) 评论(0)
博客
打开配置文件将下面代码添加到 components => [...]中(例:高级版默认配置在/common/config/main-local.php) 'mailer' => [ 'class' => 'yii\swiftmailer\Mailer', 'viewPath' => '@common/mail', 'useFileTransport' => false, //这里一定要改成false,不然邮件不会发送 'transport' => [ 'class' => 'Swift_SmtpTransport', 'host' => 'smtp.163.com', 'username' => 'xianan_huang@163.com', 'password' => '*********', //如果是163邮箱,此处要填授权码 'port' => '25', 'encryption' => 'tls', ], ], 在控制器中调用: $mail = \Yii::$app->mailer->compose() ->setFrom(['xianan_huang@163.com' => 'Yii 中文网']) ->setTo('391430388@qq.com') ->setSubject('邮件发送配置') //->setTextBody('Yii中文网教程真好 www.yii-china.com') //发布纯文字文本 ->setHtmlBody("<br>Yii中文网教程真好!www.yii-china.com") //发布可以带html标签的文本 ->send(); if($mail) echo 'success'; else echo 'fail'; 注意:很多报错原因都是因为163邮箱的smtp没有开,进入邮箱设置一下 默认不开启smtp要绑定手机之后才能开启
精华贴
9月前 喜欢(2) 浏览(1133) 评论(3)
讨论
先问是不是,再问为什么。 难道美国的程序员就不加班吗?他们就一天八小时工作,还想来就来,想走就走?非工作时间完全找不到人?还有什么食物饮料都免费提供? 让我来告诉你真实的情况吧,还...真是这样的。 加班文化应该是中美两地最明显的不同了,形成这种差异的原因不是一两句可以讲清楚的。我在两个国家都工作过,也在不同岗位工作过,所以就尽量从不同角度来简要说一下。 国内程序员加班严重,首先问题不在程序员这个群体。 产品层面拍脑袋决策多 产品层面,拍脑袋决策多,美其名曰:互联网思维、小步快跑、试错思维,其实是没想清楚,反正我就需求一提,技术团队来做,上线后成功了我是产品天才,失败了也没啥坏处,找个借口说什么“互联网市场变化太快”也能搪塞过去,或者找个新项目,继续画大饼。 国内的产品经理实在是太多了,很多还是刚毕业的小鲜肉,没有一点经验积累,凭借天马行空的想象力,提一个需求,就能让一帮技术专家为之操劳好几个月去实现,这简直是不可思议的。即使产品经理很厉害,但人数一多,每个人都要业绩,都拼命想点子、提需求,技术团队怎么能招架得住那么多需求呢。于是就会这些现象:     - 节假日来了,我们上一个活动,或者节日小彩蛋功能。     - 竞品上了一个 xx 功能,看起来不错,我们也抓紧上一个。     - 10个产品经理同时跟你说:这个需求我跟老板对过了,xx 之前必须上线。 产品经理没有想清楚某个功能的价值,或者带来的收益不痛不痒,而技术团队则需要为此付出巨大的心血,也就是加班。当然这也不一定是产品经理的错,国内公司,老板的指令太多了,不说了,你懂的。 在美国这边,产品经理大多是行业经验非常丰富的人,要么是从工程师转过来,要么是从多年的商业领域经历然后读个 MBA转过来。上线一个功能,经过严谨的理论推演、多轮前期调研、科学的 AB test,从提出 idea 到最终用户看到更新,经常耗时半年或一年。很多不成功的 idea 还没面市,就因为数据不好而“胎死腹中”。这样一方面提高了产品需求的质量,另一方面也给技术团队足够多的时间来设计和实现一个可持续发展的架构。 技术团队话语权低 管理层在做决策时,往往更重视产品更新迭代,而忽视技术的建设。 比如说技术团队有100个小时,老板可能会把90小时都投入到实现产品功能,给技术优化、修补技术债务。于是就会出现技术实现非常粗糙的情况,举个栗子,给你一周时间,实现一个 IM 功能,你还会考虑什么模块化、可维护性、性能优化之类的吗?当然是怎么快怎么来,百度一下有没有别人实现过的代码,ctrl+v / ctrl+c,一点运行,诶,跑通了,上线。 所以国内很多程序员看别人的代码,感觉都是一团 shit,完全没法维护,干脆自己重写一个。 技术老大能跑到老板面前说“我们先把产品需求停一停,让我们的技术团队好好地优化一下基础设施吧。”吗?只要他不是傻子,都不会这样说。 话语权低还体现在,对产品几乎没有决策权,甚至不能质疑产品决策,提反对意见,总会被产品经理各种理由挡回来,产品经理有一句话终结争论的尚方宝剑:这是老板要做的。 久而久之,技术债务越堆越高,bug 越来越多,程序员不加班,谁加班? 而美国公司的现象是,技术话语权非常高,一个没想清楚的产品需求,能被技术团队直接打回去。同时,技术团队可以自主地花很多时间在技术优化上面。产品不能按时上线?经理说:没关系,延后,按照最优的技术方案来推进。有时候你想赶紧上线,提交一段粗制滥造的代码,会被同事鄙视死,被老板骂死。 每个季度最后一个月,专门抽出精力,来弥补技术债务,产品需求放一边先。 在这样的环境下,短期看起来效率低,但长期是最高效的。国内是“欲速侧不达”,美国是“慢工出细活”。 技术基础设施差 知乎上有一个比较热门的讨论:腾讯的技术建设是否落后? 这不但是腾讯的问题,实际上绝大部分公司的技术基础设施都非常差。 有多少个公司能养一个专门的 Infra 团队?有多少个技术团队能专门成立一个小团队,进行 Infra 优化?即使有,有多少个公司能保证 Infra 团队的成果能在全公司推行? 我相信能做到这样的公司是凤毛麟角的。 中小公司不必说,在这样高度竞争环境下,哪有财力养一个不能直接带来 KPI 提升的团队,即使有钱,也没时间搞优化。 而大公司呢,即使腾讯这样的体量,有一个 TEG 事业群做基础设施建设。但是现实情况是,依然没有全公司通用的内部工具,各个团队依然在重复造轮子。阿里算是做的很好的,前几年开始推行的大中台战略取得了显著的成果,解放了各个产品部门的生产力。 计算机程序这种东西,一个人写和一群人写,几千个用户使用和几千万用户使用,是完全不同的概念。没有强大的基础设施建设,技术团队越壮大,效率越低,用户数越多,bug 越多。出来混总是要还的,今天没有人关注基础设施,未来就会又无数个程序员为此加班。 而说回美国这边,专门的 Infra 团队几乎是每个公司的标配了。这也是工程师文化的结果,创始人、高管团队一定有很强的技术背景,走过了很多弯路,所以非常重视基础设施建设这种“重要而不紧急”的事情。 畸形的职场文化 最后再来说说文化的差异。 美国人非常注重个人和家庭,牺牲自己的时间来给公司加班,这是不可能的。一到下班时间准点走,非上班时间完全不查邮件。很多公司入职培训就专门强调了怎么平衡工作和生活,其实就是说:下班时间就是你的时间,你有权利不处理公司事务。 反观国内,不知道从什么时候起,加班就是约定俗成的。还出现了看似很有道理的人生经验,比如“年轻人就应该多拼一下”,“加班能学到更多东西,对未来也有好处”。 加班,竟然成了光荣的、可以拿来攀比的现象,比如说加班到凌晨一两点,拍个照,发个朋友圈,收到老板的点赞很开心。而管理者呢,还就吃这一套,谁加班多、会来事儿,考核的时候就更有好处。 在这种加班氛围下,甚至还出现了“伪加班”。早上十点到公司,上个厕所、看会儿新闻、刷刷朋友圈,就到十一点半了,什么工作也没做,然后准备吃午饭;饭后逛一逛、睡个觉,又到2点上班时间了,写会儿代码、刷刷知乎,一下午又过去了,很多公司有免费晚餐,吃完饭回来7点左右,再写写代码,磨到10点。哦耶,又是充实的一天呢,发个朋友圈给老板知道。 其实一天有效工作时间还不够8小时,但就是“加班”了。 综上,大概就是国内加班严重的原因。 我觉得这也是某个时代特有的现象,谁都没有错,谁也没有办法改变这种情况。在国内这样一个高度竞争的环境下,公司为了生存必须跑快点,个人为了发展必须多做事,毕竟你不做就会有千千万万的人来抢。等到中国真的发展到美国这样的发达程度,生存的减小了,才有资格谈更好的生活品质。
6月前 喜欢(1) 浏览(650) 评论(0)
博客
Yii2.0 RESTful API 之速率限制 什么是速率限制? 权威指南翻译过来为限流,为防止滥用,你应该考虑对您的 API 限流。 例如,您可以限制每个用户 10 分钟内最多调用 API 100 次。 如果在规定的时间内接收了一个用户大量的请求,将返回响应状态代码 429 (这意味着过多的请求)。 要启用速率限制,首先需要实现认证类,而关于认证的章节我在 Yii2.0 RESTful API 认证教程 进行了详细的阐述,本篇就不过多介绍,再次基础上进行操作 启用速率限制 翻阅权威指南,我们可以看到要启用速率限制首先 认证类 需要继承 yii\filters\RateLimitInterface 生成两个关键字段 php yii migrate/create add_allowance_and_allowance_updated_at_to_user 修改 刚才的迁移文件 /** * {@inheritdoc} */ public function safeUp() { $this->addColumn('user', 'allowance', $this->integer()); $this->addColumn('user', 'allowance_updated_at', $this->integer()); } /** * {@inheritdoc} */ public function safeDown() { $this->dropColumn('user', 'allowance'); $this->dropColumn('user', 'allowance_updated_at'); } 执行迁移 php yii migrate 编写认证类,并继承 RateLimitInterface namespace api\models; use Yii; use yii\base\NotSupportedException; use yii\behaviors\TimestampBehavior; use yii\db\ActiveRecord; use yii\filters\RateLimitInterface; use yii\web\IdentityInterface; class User extends ActiveRecord implements IdentityInterface,RateLimitInterface { . . . } 实现 RateLimitInterface 所需要的方法 public function getRateLimit($request, $action) { return [1, 1]; // $rateLimit requests per second } public function loadAllowance($request, $action) { return [$this->allowance, $this->allowance_updated_at]; } public function saveAllowance($request, $action, $allowance, $timestamp) { $this->allowance = $allowance; $this->allowance_updated_at = $timestamp; $this->save(); } 控制器中实现调用 use yii\filters\auth\CompositeAuth; use yii\filters\auth\HttpBearerAuth; use yii\filters\auth\QueryParamAuth; use yii\filters\RateLimiter; public function behaviors() { $behaviors = parent::behaviors(); $behaviors['rateLimiter'] = [ 'class' => RateLimiter::className(), 'enableRateLimitHeaders' => true, ]; $behaviors['authenticator'] = [ 'class' => CompositeAuth::className(), 'authMethods' => [ //Http::className(), HttpBearerAuth::className(), QueryParamAuth::className(), ], ]; //$behaviors['rateLimiter']['enableRateLimitHeaders'] = true; return $behaviors; } ok,请求下你的 action,多次请求如果出现 429,那么表示速率限制启用成功 以上就是关于 Yii2.0 速率限制的使用,速率限制需要和认证配合着使用,关于认证的,查阅Yii2.0 RESTful API 认证教程 ,这篇文章,推荐您,先看完认证,先做完认证的功能,然后在启用速率限制 关于 Yii2.0 RESTFul API到此我觉得就结束了,核心功能就是这些,剩下的就是具体的实战了,多练、多敲, 一共四篇文章,分别为: Yii2.0 RESTful API 基础配置教程 Yii2.0 RESTful API 认证教程 Yii2.0 RESTful API 之版本控制 Yii2.0 RESTful API 之速率限制
6月前 喜欢(1) 浏览(892) 评论(2)
博客
作为一个屌丝级别的开发者对接别人的api也是一个常见的事情。 比如有以下一个api需要对接 接口地址:http://api.qingyunke.com/api.php?key=free&appid=0&msg=关键词      key 固定参数free      appid 设置为0,表示智能识别,可忽略此参数      msg 关键词,请参考下方参数示例,该参数可智能识别,该值请经过 urlencode 处理后再提交 返回结果:{"result":0,"content":"内容"}      result 状态,0表示正常,其它数字表示错误      content 信息内容 对接接口第一步封装一个能用于请求http的工具类, components/helper/CurlHelper.php namespace components\helper; class CurlHelper extends \yii\base\Object { public static function get($url,$data){ $curl = curl_init(); $o = ""; foreach ( $data as $k => $v ) { $o.= "$k=" . urlencode( $v ). "&" ; } $data = substr($o,0,-1); $url = $url.'?'.$data; curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在 //curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转 curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环 curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回 $tmpInfo = curl_exec($curl); // 执行操作 curl_close($curl); // 关闭CURL会话 return $tmpInfo; } } components为根目录下的一个文件夹,里面用于存放自己定义的类,YII2时MVC结构,没有建议用户的自定义类放哪里,而vendor目录很多第三方的活雷锋库,最为一个自私的开发者。所有得自定义一个文件夹用于放自己定义的class,题外话”components“的叫法来自一个没我帅的人,我不会告诉大家他叫【谁偷了汝的凶兆】,也有人把自定义的class放libs的,由于我是Java过来的半吊子,觉得这样叫不太妥当。所有采用了”components“的叫法,总之大家开心就好。 对这个库进行配置 config/web.php $config = [ ... 'aliases' => [ '@components' => '@app/components' ],..]; 封装一下api components/qingyunke/FeiFei.php namespace components\qingyunke; use components\helper\CurlHelper; use yii\base\Object; use yii\helpers\Json; /** * Created by PhpStorm. * User: 16487 * Date: 2018/5/8 * Time: 9:47 */ class FeiFei extends Object { const API_URL='http://api.qingyunke.com/api.php'; const API_KEY='free'; const APP_ID='0'; public static function sendMessage($msg){ $data = [ 'key' => self::API_KEY, 'appid' =>self::APP_ID, 'msg' => $msg ]; try { $infoStr = CurlHelper::get(self::API_URL, $data); if ($infoStr != null) { $mjson = Json::decode($infoStr, false); if ($mjson->result == 0) { $mContent=$mjson->content; $mContent=str_replace("{br}","\n",$mContent); $mContent=str_replace("请发送","请回复",$mContent); return $mContent; } } } catch (\Exception $e) { } return null; } } 测试api commands/HelloController.php namespace app\commands; ... class HelloController extends Controller { ... public function actionQwe() { var_dump(FeiFei::sendMessage("我是大帅哥")); } ... } cd 到yii目录执行 D:\www\foxhome>yii hello/qwe 得到响应
6月前 喜欢(1) 浏览(602) 评论(0)
讨论
更新 2018年6月10日发布了Yii框架3.0.0 更新的第一个alfa版本 Yii 3.0中的新功能 包 “ezyang/htmlpurifier” 已经成为可选项,默认情况下不会安装 移除 Yii 自动加载器以支持 Composer 的 PSR-4 实现 删除了特定于 HHVM 的代码 在 ApcCache 中删除了 APC 支持, APCu 像以前一样工作 当覆盖默认值时,会更改yii\grid\DataColumn :: $filterInputOptions的行为 将屏蔽的输入字段小部件移动到单独的扩展https://github.com/yiisoft/yii2-maskedinput 邮件消息组成提取到单独的类,yii\mail\Composer,可以通过yii\mail\BaseMailer :: $composer获得设置 将yii\base\InvalidParamException重命名为yii\base\InvalidArgumentException 更新了未安装 intl 扩展时使用的后备日期格式,以匹配最新 ICU 版本的默认值 删除了 XCache 和 Zend 数据缓存支持作为缓存后端 更新了yii\widgets\ActiveField :: hint()方法签名以匹配label() 删除了yii\base\Object :: className(),支持本机PHP语法:: class,它不会触发自动加载 PHP的最低要求版本现在为7.1 所有框架小部件中run()方法的一致行为。现在返回结果以获得更好的可扩展性 yii\web\RequestParserInterface :: parse()的签名已更改为接受yii\web\Requestinstance作为唯一参数 删除了 CUBRID 数据库支持 删除了 PJAX 支持 包 'captcha','jquery','rest','mssql' 和 'oracle' 已被提取到扩展中 删除了在 2.0.x 中标记为已弃用的方法 Yii 3.0中的增强功能 使用random_int()而不是mt_rand()来生成加密安全的伪随机整数 对象yii\helpers\ReplaceArrayValue,yii\helpers\UnsetArrayValue现在支持在使用var_export()函数导出后恢复 添加了yii\web\AssetConverter::$isOutdatedCallback,允许自定义检查过时的资产转换结果 在yii\serialize\* 命名空间下添加了序列化抽象层 增加了对 PSR-3 'Logger' 支持 优化了yii\filters\AccessController处理访问规则 将$checkAjax参数添加到方法yii\web\Controller::redirect(),该方法控制 AJAX 和 PJAX 请求中的重定向 邮件视图呈现封装到yii\mail\Template类中,允许隔离呈现并通过视图内的$this-> context->message 访问 yii\mail\MessageInterface 实例 CAPTCHA渲染逻辑被提取到yii\captcha\DriverInterface中,该实例可通过 yii\captcha\CaptchaAction::$driver 字段获得 yii\web\Request :: getBodyParams() 在无效或缺失 'Content-Type' 头时,生成 415 “Unsupported Media Type” 错误 yii\web\Request :: getBodyParams() 的结果现在包括上传的文件 已上载的文件检索方法已从 yii\http\UploadedFile 移至 yii\web\Request 添加了对 PSR-7 HTTP Message 的支持 根据 PSR-16 “Simple Cache” 规范重构的缓存实现 相对与 Yii2 改动 Yii3这个版本改动相对于Yii2是非常的巨大,包括以下特性: Yii3需要PHP的最低版本是 7.1 并且 HHVM 不再被支持. Yii3 将采用新的版本规则,即 semver since 3.0规则. 不再使用Subtree-split 模式. 放弃使用 Yii自己的 autoloader 改为用 Composer 的autoloader. 框架的结构也进行了大量的调整,分出来好几个包,包括下面这些: yiisoft/yii-core - 这个是Yii Framework . Yii 2.0 的开发还是在 yiisoft/yii2 仓库. Yii2 只支持Bug 和安全补丁,新特性和加强的特性不在被接收。 yiisoft/di - PSR-11适应依赖注入的 container. yiisoft/log - PSR-3 适应 Psr-3的 logging library. yiisoft/cache - PSR-16 适应 psr-16的 caching library. yiisoft/db - 数据库的 abstraction and QueryBuilder. yiisoft/db-mysql - MySQL 的db扩展. yiisoft/db-pgsql - PostgreSQL 的db扩展. yiisoft/db-sqlite - SQLite 的db扩展. yiisoft/db-mssql - MSSQL 的db扩展. yiisoft/db-oracle - Oracle 的db扩展. yiisoft/active-record - ActiveRecord 库. yiisoft/rbac - RBAC 库. yiisoft/view - 视图渲染库. yiisoft/yii-web - Web 扩展. yiisoft/yii-rest - REST API 扩展. yiisoft/yii-console - console 扩展. yiisoft/yii-jquery - JQuery 扩展. yiisoft/yii-bootstrap3 - Bootstrap 3 扩展. yiisoft/yii-bootstrap4 - Bootstrap 4 扩展. yiisoft/yii-dataview - data displaying 扩展. yiisoft/yii-masked-input - Masked input field widget. yiisoft/yii-captcha - CAPTCHA 扩展. 更多的 PSR 兼容: PSR-3, PSR-11, PSR-16 框架核心只需要虚拟PSR实现包,您可以自由选择日志记录器和缓存实现。 更多PSR实现的兼容性预计将在稍后实现。 从Application and Module 删除ServiceLocator ,采用 container来替代. 数据库的扩展被分到几个composer包里面. 删除PJAX 的支持. yiisoft/yii2-composer 这个包不再被使用. 不再提供高级的项目模板. 项目模板也有所变化 yiisoft/yii-project-template - 工程模板; yiisoft/yii-base-web - web的基础应用模板. 我们将为您提供Yii框架中所有最新更改的最新信息。
7月前 喜欢(1) 浏览(3212) 评论(2)
博客
通过一个例子简单说一下Yii2 模型中的场景(scenario)应用,现在在 文章表里面有 title image content 三个的字段,当我创建一个文章 的时候,我想三个字段全部是必填项,但是你修改的时候,title content 两个字段是必填的, iamge 可以不填写。正常的情况下, [['title', 'content', 'image'], 'required',], 但是我们更改的时候 只需要 [['title', 'content'], 'required'], 就可以了,但是少了 image 字段,我们的表单就无法提交,这种问题怎么办啊?? 场景可以帮你解决这种问题,下面是一个简单的场景实例。 1.首先我们在 model 里面定义一下场景 类名必须是 scenarios() public function scenarios() { return [ 'create' => ['title', 'image', 'content'], 'update' => ['title', 'content'], ]; } 2.好的,如上所示,场景的基本设置我们就已经完成一部分了,下面我们设置 rules() ,调用场景我们用 on 关键字 [['title', 'content'], 'required', 'on' => ['create', 'update']], [['image'], 'required', 'on' => 'create'], [ ['image'], 'image', 'enableClientValidation' => true, 'maxSize' => 1024, 'message' => '您上传的文件过大', 'on' => ['create', 'update'] ], on 指定的就是场景,一个场景用字符串,多个场景用数组 3.好的,model 里面我们就设置完毕了 现在开始调用吧 Controller里面 $model = $this->findModel($id); $model->setScenario('update'); //或者 $model->scenario = 'update'; 都可以 上面的意思就是 调用 update 场景。
8月前 喜欢(1) 浏览(1012) 评论(1)
博客
如果做API的话,如何使别人再调用你的接口时能够有一个统一标准的json或者jsonp格式,然而 json响应的格式和内容,每个人的约定都是有差异的,所以我们必须再数据出去之前做一定的处理。 1.首先我们需要初始化去调用beforeSend,因为我们需要对beforesend做一些处理,以下是init初始化处理代码: /** * (non-PHPdoc) * @see \yii\base\Object::init() */ public function init() { parent::init(); //绑定beforeSend事件,更改数据输出格式 Yii::$app->getResponse()->on(Response::EVENT_BEFORE_SEND, [$this, 'beforeSend']); } 2.然后我们就需要对beforesend进行处理,处理点有下面几个重点: 1>更改数据输出格式 2>默认情况下输出Json数据 3>如果客户端请求时有传递$_GET['callback']参数,输出Jsonp格式 4>请求正确时数据为 {"success":true,"data":{...}} 5>请求错误时数据为 {"success":false,"data":{"name":"Not Found","message":"页面未找到。","code":0,"status":404}} 6>具体代码如下: /** * 更改数据输出格式 * 默认情况下输出Json数据 * 如果客户端请求时有传递$_GET['callback']参数,输入Jsonp格式 * 请求正确时数据为 {"success":true,"data":{...}} * 请求错误时数据为 {"success":false,"data":{"name":"Not Found","message":"页面未找到。","code":0,"status":404}} * @param \yii\base\Event $event */ public function beforeSend($event) { /* @var $response \yii\web\Response */ $response = $event->sender; $isSuccessful = $response->isSuccessful; if ($response->statusCode>=400) { //异常处理 if (true && $exception = Yii::$app->getErrorHandler()->exception) { $response->data = $this->convertExceptionToArray($exception); } //Model出错了 if ($response->statusCode==422) { $messages=[]; foreach ($response->data as $v) { $messages[] = $v['message']; } //请求错误时数据为 {"success":false,"data":{"name":"Not Found","message":"页面未找到。","code":0,"status":404}} $response->data = [ 'name'=> 'valide error', 'message'=> implode(" ", $messages), 'info'=>$response->data ]; } $response->statusCode = 200; } elseif ($response->statusCode>=300) { $response->statusCode = 200; $response->data = $this->convertExceptionToArray(new ForbiddenHttpException(Yii::t('yii', 'Login Required'))); } //请求正确时数据为 {"success":true,"data":{...}} $response->data = [ 'success' => $isSuccessful, 'data' => $response->data, ]; $response->format = Response::FORMAT_JSON; \Yii::$app->getResponse()->getHeaders()->set('Access-Control-Allow-Origin', '*'); \Yii::$app->getResponse()->getHeaders()->set('Access-Control-Allow-Credentials', 'true'); //jsonp 格式输出 if (isset($_GET['callback'])) { $response->format = Response::FORMAT_JSONP; $response->data = [ 'callback' => $_GET['callback'], 'data'=>$response->data, ]; } } 3.针对请求可能会发生一些异常,同样我们也需要对异常进行一些标准化处理,将异常转换为array输出,具体代码如下: /** * 将异常转换为array输出 * @see \yii\web\ErrorHandle * @param \Exception $exception * @return multitype:string NULL Ambigous <string, \yii\base\string> \yii\web\integer \yii\db\array multitype:string NULL Ambigous <string, \yii\base\string> \yii\web\integer \yii\db\array */ protected function convertExceptionToArray($exception) { if (!YII_DEBUG && !$exception instanceof UserException && !$exception instanceof HttpException) { $exception = new HttpException(500, Yii::t('yii', 'An internal server error occurred.')); } $array = [ 'name' => ($exception instanceof Exception || $exception instanceof ErrorException) ? $exception->getName() : 'Exception', 'message' => $exception->getMessage(), 'code' => $exception->getCode(), ]; if ($exception instanceof HttpException) { $array['status'] = $exception->statusCode; } if (YII_DEBUG) { $array['type'] = get_class($exception); if (!$exception instanceof UserException) { $array['file'] = $exception->getFile(); $array['line'] = $exception->getLine(); $array['stack-trace'] = explode("\n", $exception->getTraceAsString()); if ($exception instanceof \yii\db\Exception) { $array['error-info'] = $exception->errorInfo; } } } if (($prev = $exception->getPrevious()) !== null) { $array['previous'] = $this->convertExceptionToArray($prev); } return $array; } 好了,这样我们就有了标准同一个的api接口返回数据格式了,在调用接口的人员也不用为了格式不统一感到烦恼
8月前 喜欢(1) 浏览(1089) 评论(0)
讨论
说明 课程简介 素材及源码 纠错 课程简介 本课程主要内容是如何通过使用 yii2 框架,快速打造个人博客系统。 博客系统主要分两个部分: 后台管理系统(backend) 相关内容:yii2-admin扩展, RBAC基于角色的权限管理,基于Markdown的富文本编辑器,上传图片到七牛,Gii生成代码,自定义Gii模版 前台内容展示(frontend) 相关内容:挂件的应用(widget),博客首页界面排版,文章内容呈现,博客时间史 素材及源码 为了方便大家学习 yii2 相关的知识并应用于实践中,本次教程会提供学习素材。什么是素材呢?就是基于 hyii2 后台管理系统添加了学习教程时所需要的样式文件,js文件,界面排版等。让大家免去在学习后端框架的过程中,去写前端的页面和js。更加精确的掌握 yii2 框架的实战应用。通过教程的学习可以开发出相应的一套完整的博客系统。详情查看 应用搭建 一章 为了保证课程的高品质,我们需要对素材进行收费,购买链接。购买后请联系 391430388 获取素材和源码 前台界面预览:http://hyblog.itdocs.org 管理后台地址:http://hyblog-admin.itdocs.org 账户:test 密码:123456 作者会提供完整的开发素材和成品源码,希望不要借此传播,尊重原创,万分感谢。 纠错 教程中遇到的问题,可以先自己尝试解决,培养自身的问题排查能力是一个程序员基本的要求。 本地环境问题(本站统一环境教程:PHP开发环境部署)。 代码书写错误,引起的报错。 搜索本教程错误集锦(开发中) 若仍不能解决,请联系 QQ:391430388 当然人无完人,也许教程中也存在一些不可避免的疏漏,如果发现可以联系作者,先行致谢!
精华贴
8月前 喜欢(1) 浏览(1842) 评论(1)
博客
场景 现在有客户表、订单表、图书表、作者表 客户表:Customer【id customer_name】 订单表:Order【id order_name customer_id book_id】 图书表:Book【id book_name author_id】 作者表:Author【id author_name】 怎么来确定是一对多还是一对一呢?这个很简单,比如下面的Customer,一个Customer有多个Order,所以就是一对多;又比如Book,一个Book只有一个作者(这里的情况就是一本书只有一个作者),所以就是一对一。 模型定义 下面是这4个个模型的定义,只写出其中的关联 Customer class Customer extends \yii\db\ActiveRecord { //这是获取客户的订单,由上面我们知道这个是一对多的关联,一个客户有多个订单 public function getOrders() { //第一个参数为要关联的子表模型类名, //第二个参数指定 通过子表的customer_id,关联主表的id字段 return $this->hasMany(Order::className(), ['customer_id' =>'id']); } } Order class Order extends \yii\db\ActiveRecord { //获取订单所属用户 public function getCustomer() { //同样第一个参数指定关联的子表模型类名 return $this->hasOne(Customer::className(), ['id' =>'customer_id']); } //获取订单中所有图书 public function getBooks() { //同样第一个参数指定关联的子表模型类名 return $this->hasMany(Book::className(), ['id' =>'book_id']); } } Book class Book extends \yii\db\ActiveRecord { //获取图书的作者 public function getAuthor() { //同样第一个参数指定关联的子表模型类名 return $this->hasOne(Author::className(), ['id' => 'author_id']); } } Author class Autor extends \yii\db\ActiveRecord { } hasMany、hasOne使用 Yii2中的表之间的关联有2种,它们用来指定两个模型之间的关联。 一对多:hasMany 一对一:hasOne 返回结果:这两个方法的返回结果都为yii\db\ActiveQuery对象 - 第一个参数:所关联的模型的类名称。 - 第二个参数:是一个数组,其中键为所关联的模型中的属性,值为当前模型中的属性。 关联的使用 现在我们获取一个客户的所有的订单信息 // 获取一个客户信息 $customer = Customer::findOne(1); //通过在Customer中定义的关联方法(getOrders())来获取这个客户的所有的订单。 $orders = $customer->orders; 上面的两行代码会生成如下sql语句 SELECT * FROM customer WHERE id=1; SELECT * FROM order WHERE customer_id=1; 关联结果缓存 如果客户的订单改变了,我们再重新调用 $orders = $customer->orders; 再次得到订单的时候你会发现没有变化。原因是只会在第一次执行$customer->orders的时候才会去数据库里面查询,然后会把结果缓存起来,以后查询的时候都不会再执行sql。 那么如果我想再次执行sql如何做呢?可以执行 unset($customer->orders); $customer->orders; 然后就可以从数据库里面取数据了。 定义多个关联 同样,我们还可以在Customer里面定义多个关联。 如返回总数大于100的订单。 class Customer extends \yii\db\ActiveRecord { public function getBigOrders($threshold = 100) { return $this->hasMany(Order::className(), ['customer_id' => 'id']) ->where('subtotal > :threshold', [':threshold' => $threshold]) ->orderBy('id'); } } 关联的两种访问方式 如上面的,如果使用 $customer->bigOrders 将会得到大于100的所有的订单。如果要返回大于200的订单可以这样写 $orders = $customer->getBigOrders(200)->all(); 从上面可以看出访问一个关联的时候有两种方法 如果以函数的方式调用,会返回一个 ActiveQuery 对象($customer->getOrders()->all()) 如果以属性的方式调用,会直接返回模型的结果($customer->orders) with的使用看如下代码,是取一个客户的订单 // 执行sql语句: SELECT * FROM customer WHERE id=1 $customer = Customer::findOne(1); //执行sql:SELECT * FROM order WHERE customer_id=1 $orders1 = $customer->orders; //这个不会执行sql,直接使用上面的缓存结果 $orders2 = $customer->orders; 如果现在我们要取出100个用户,然后访问每个用户的订单,从上面的了解我们可能会写出如下代码 // 执行sql语句: SELECT * FROM customer LIMIT 100 $customers = Customer::find()->limit(100)->all(); foreach ($customers as $customer) { //执行sql: SELECT * FROM order WHERE customer_id=... $orders = $customer->orders; // 处理订单。。。 } 然而,如果真要这样写的话,会在foreach的每个循环里面都执行一次sql去数据库里面查询数据。因为每个$customer对象都是不一样的。 为了解决上面的问题 可以使用 yii\db\ActiveQuery::with()。 其中with的参数为关系的名称,也就在model里面定义的getOrders,getCustomer中的orders和customer // 先执行sql: SELECT * FROM customer LIMIT 100; // SELECT * FROM orders WHERE customer_id IN (1,2,...) $customers = Customer::find()->limit(100)->with('orders')->all(); foreach ($customers as $customer) { // 在这个循环的时候就不会再执行sql了 $orders = $customer->orders; // ...handle $orders... } 如果使用了select来指定返回的列,一定要确保返回的列里面包含所关联的模型的关联字段,否则将不会返回关联的表的Model $orders = Order::find()->select(['id', 'amount'])->with('customer')->all(); // $orders[0]->customer 的结果将会是null // 因为上面的select中没有返回所关联的模型(customer)中的指定的关联字段。 // 如果加上customer_id,$orders[0]->customer就可以返回正确的结果 $orders = Order::find()->select(['id', 'amount', 'customer_id'])->with('customer')->all(); 给with加过滤条件 查询一个客户大于100的订单 //首先执行sql: SELECT * FROM customer WHERE id=1 $customer = Customer::findOne(1); // 再执行查询订单的sql语句:SELECT * FROM order WHERE customer_id=1 AND subtotal>100 $orders = $customer->getOrders()->where('subtotal>100')->all(); 查询100个客户的,每个客户的总合大于100的订单 // 下面的代码会执行sql语句: // SELECT * FROM customer LIMIT 100 // SELECT * FROM order WHERE customer_id IN (1,2,...) AND subtotal>100 $customers = Customer::find()->limit(100)->with([ 'orders' => function($query) { $query->andWhere('subtotal>100'); }, ])->all(); 在这里with的参数为数组,键为关联的名称,值为回调函数。 也就是说 对 orders 这个关联返回的 ActiveQuery,再执行一次$query->andWhere(‘subtotal>100′); 使用joinWith进行表关联 我们都知道可以用join on来写多个表之间的关联。先看看yii2中joinWith的声明 joinWith( $with, $eagerLoading = true, $joinType = ‘LEFT JOIN’ ) $with 数据类型为字符串或数组, 如果为字符串,则为模型中定义的关联的名称(可以为子关联)。 如果为数组,键为model中以getXXX格式定义的关联,值为对这个关联的进一步的回调操作。 $eagerLoading 是否加载在 $with 中关联的模型的数据。 $joinType 联接类型,可用值为:LEFT JOIN、INNER JOIN,默认值为LEFT JOIN // 订单表和客户表以Left join的方式关联。 // 查找所有订单,并以客户 ID 和订单 ID 排序 $orders = Order::find()->joinWith('customer')->orderBy('customer.id, order.id')->all(); // 订单表和客户表以Inner join的方式关联 // 查找所有的订单和书 $orders = Order::find()->innerJoinWith('books')->all(); // 使用inner join 连接order中的 books关联和customer关联。 // 并对custmer关联再次进行回调过滤:找出24小时内注册客户包含书籍的订单 $orders = Order::find()->innerJoinWith([ 'books', 'customer' => function ($query) { $query->where('customer.created_at > ' . (time() - 24 * 3600)); } ])->all(); // 使用left join连接 books关联,books关联再用left join 连接 author关联 $orders = Order::find()->joinWith('books.author')->all(); 在实现上,Yii 先执行满足JOIN查询条件的SQL语句,把结果填充到主模型中, 然后再为每个关联执行一条查询语句, 并填充相应的关联模型。 // Order和books关联 inner join ,但不获取books关联对应的数据 $orders = Order::find()->innerJoinWith('books', false)->all(); On条件 在定义关联的时候还可以指定on条件 class User extends ActiveRecord { public function getBooks() { return $this->hasMany(Item::className(), ['owner_id' => 'id'])->onCondition(['category_id' => 1]); } } 在 joinWith 中使用 //先查询主模型(User)的数据 SELECT user.* FROM user LEFT JOIN item ON item.owner_id=user.id AND category_id=1 // 然后再根据关联条件查询相关模型数据 SELECT * FROM item WHERE owner_id IN (...) AND category_id=1 // 这两个在查询的过程中都使用了 on条件。 $users = User::find()->joinWith('books')->all(); 如果没有使用join操作,即使用的是with 或者 直接以属性来访问关联。这个时候on条件会作为where 条件。 SELECT * FROM user WHERE id=10 $user = User::findOne(10);
8月前 喜欢(1) 浏览(1332) 评论(0)
社区公告
[公告] Yii中文网为优化用户体验进行大版本升级,老版网站会维持一段时间,可以点击顶部"旧版"链接访问旧版网站。
沟通交流

:492175201(技术1群)

:183620600(技术2群)

:291010569(技术3群)

订阅号 | 更多精彩内容推送
本周推荐