Yii2 Log 特性

文件Log的配置:

'log' =>[  
      # 追踪级别  
      # 消息跟踪级别  
      # 在开发的时候,通常希望看到每个日志消息来自哪里。这个是能够被实现的,通过配置 log 组件的 yii\log\Dispatcher::traceLevel 属性, 就像下面这样:  
      'traceLevel' => 3,  
        
      # 通过 yii\log\Logger 对象,日志消息被保存在一个数组里。为了这个数组的内存消耗, 当数组积累了一定数量的日志消息,日志对象每次都将刷新被记录的消息到 log targets 中。 你可以通过配置 log 组件的 yii\log\Dispatcher::flushInterval 属性来自定义数量  
      'flushInterval' => 1,  
        
      'targets' => [  
        'file' =>[  
          //'levels' => ['trace'],  
          'categories' => ['fecshop_debug'],  
          'class' => 'yii\log\FileTarget',  
          # 当 yii\log\Logger 对象刷新日志消息到 log targets 的时候,它们并 不能立即获取导出的消息。相反,消息导出仅仅在一个日志目标累积了一定数量的过滤消息的时候才会发生。你可以通过配置 个别的 log targets 的 yii\log\Target::exportInterval 属性来 自定义这个数量,就像下面这样:  
          'exportInterval' => 1,  
          # 输出文件  
          'logFile' => '@appfront/runtime/fecshop_logs/fecshop_debug.log',  
          # 你可以通过配置 yii\log\Target::prefix 的属性来自定义格式,这个属性是一个PHP可调用体返回的自定义消息前缀  
          'prefix' => function ($message) {  
            return $message;  
          },  
          # 除了消息前缀以外,日志目标也可以追加一些上下文信息到每组日志消息中。 默认情况下,这些全局的PHP变量的值被包含在:$_GET, $_POST, $_FILES, $_COOKIE,$_SESSION 和 $_SERVER 中。 你可以通过配置 yii\log\Target::logVars 属性适应这个行为,这个属性是你想要通过日志目标包含的全局变量名称。 举个例子,下面的日志目标配置指明了只有 $_SERVER 变量的值将被追加到日志消息中。  
          # 你可以将 logVars 配置成一个空数组来完全禁止上下文信息包含。或者假如你想要实现你自己提供上下文信息的方式, 你可以重写 yii\log\Target::getContextMessage() 方法。  
           'logVars' => [],  
        ],  
      ],  
    ],

然后新建文件:@appfront/runtime/fecshop_logs/fecshop_debug.log 并设置可写就行。

调用:

\Yii::info($post_log,'fecshop_debug');

$post_log 就是要输出的log内容。

如果log的配置或者文件有问题会不会报错呢?

1.去掉上面的配置,然后执行调用:

\Yii::info($post_log,'fecshop_debug');

经过测试,程序不会被卡住,会继续执行的

2.配置保留,去掉配置中对应的真实文件:@appfront/runtime/fecshop_logs/fecshop_debug.log 删除掉,经过测试,发现程序不会被卡住,还是会继续执行的。

总结:log出现问题,只要不是语法文件,不会卡住,还是会继续跑下去的。

Yii2 中使用ElasticSearch – 所有

 

安装ElasticSearch ,以及在yii2中的使用

 

Yii2 elasticSearch – 配置部分

 

Yii2 elasticSearch – Model部分

 

Yii2 elasticSearch 进行查询

 

Yii2 ElasticSearch aggregate (group) 的例子

 

yii2 elasticSearch 传递数据到elasticSearch中

 

 

ElasticSearch 使用 – 传递数据规避重复数据

Yii2 elasticSearch 多值查询 和 查询数组字段

Yii2 elasticSearch 多值查询 和 查询数组字段

 

elasticSearch 批量传递数据,存在数据丢失的原因

 

 

 

yii2 elasticSearch 传递数据到elasticSearch中

 

代码如下:$data 是一个数组。

    
if(is_array($data) && !empty($data )){
  $elasticsearch = Yii::$app->elasticsearch;
  $bulkclient = $elasticsearch->createBulkCommand();
  # elasticSearch的index,相当于mysql的数据库
  $index_name = 'fecshop';
  # elasticSearch的type,相当于mysql的table
  $type_name = 'whole_free_sku_data';
  echo $index_name."###".$type_name." \n";
  foreach($data  as $one){
    $i++;
    $a = [];
    $a['sku_id'] = $one['_id'];
    $value = $one['value'];
    
    # 将多维数组部分进行序列化。
    if(is_array($value) && !empty($value )){
      foreach($value  as $k => $v){
        if(in_array($k,['devide','country_code','browser_name','operate'])){
          
          if(is_array($v) && !empty($v)){
            $vv = [];
            foreach($v as $vk => $o){
              $vv[] = serialize([$vk=>$o]);
            }
            $v = $vv;
          }
        }
        $a[$k] = $v;
      }
    }
    # 去掉_id字段。
    unset($a['_id']);
    $bulkclient->addAction(array(
      'index' => array(
        '_index'=> $index_name,
        '_type' => $type_name,
        '_id' 	=> $one['_id'],
      )
    ), $a);
    
  }
  $bulkclient->execute();
}

 

Yii2 elasticSearch 进行查询

elasticsearch的查询:查询器query 和 过滤器filter

关于查询器query和过滤器filter的区别,可以参看文章:http://www.tuicool.com/articles/7rqAFne

public function getTableTbody()
{
  $pageNum = 3;
  $numPerPage = 50;
  $offset = ($pageNum - 1) * $numPerPage;
  $limit  = $numPerPage ;
  $sort = ['emails' => ['order' => 'desc']];  # emails 按照desc的方式进行排序
  $query = $this->_getSearchQuery();
  $result = $query->orderby($sort)->offset($offset)->limit($limit)->asArray()->all();
  $data = \yii\helpers\BaseArrayHelper::getColumn($result, '_source');
  if(!empty($data))
  {
    foreach($data as $dk => $dr)
    {
    // do something
    }
  }
}

上面使用的_getSearchQuery() 方法如下:

public function _getSearchQuery(){
  # $field_1 $field_2 都是字段
  $filter_arr = [
    'bool' => [
      'must' => [
        ['term' => [$field_1 => 'xxxxxxx']] 
        # $emails_arr 是数组。
        ['terms' => [$field_2 => $emails_arr]]  # 在查询的字段只有一个值的时候,应该使用term而不是terms,在查询字段包含多个的时候才使用terms
      ]
    ],
  ];

  # $field_1 $field_2 都是字段
  $query_arr = [
    'bool' => [
      'must' => [
        ['match' => [$field_1 => 'xxxxx']],
        
      ],
      'should' => [
        # 关于wildcard查询可以参看文章:http://blog.csdn.net/dm_vincent/article/details/42024799
        ['wildcard' => [$field_2 => "W?F*HW"]]
      ]
    ],
  ];

  # Customer 就是elasticSearch 的 model
  $query = Customer::find()->filter($filter_arr)->query($query_arr);
  return $query;
}

对于上面出现的must should,自己查资料,了解elasticSearch

对于term 相当于等于

对于terms相当于mysql中的in

在上述查询中,filter是不分词,不进行同义词查询的,速度肯定要快

query会进行同义词查询的,速度肯定要慢一些的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Yii2 elasticSearch – Model部分

在上一篇文章,我们配置好了es,那么,我们开始配置model

 

<?php

namespace appadmin\code\Ta\models\elasticSearch;

use yii\elasticsearch\ActiveRecord;

class Customer extends ActiveRecord
{
  public static $currentIndex;
  
  # 定义db链接
  public static function getDb()
  {
    return \Yii::$app->get('elasticsearch');
  }
  
  
  # db
  public static function index()
  {
    return 'ta';
  }
  # table
  public static function type()
  {
    return 'customer';
  }
  
  # 属性
  public function attributes()
    {
        $mapConfig = self::mapConfig();
    return array_keys($mapConfig['properties']);
    }
  # mapping配置
  public static function mapConfig(){
    return [
      'properties' => [
        'customer_id'	=> ['type' => 'long',	"index" => "not_analyzed"],
        'uuids'			=> ['type' => 'string',	"index" => "not_analyzed"],
        'updated_at'	=> ['type' => 'long',	"index" => "not_analyzed"],
        'emails'		=> ['type' => 'string',"index" => "not_analyzed"],
      ]
    ];
  }
  
  public static function mapping()
    {
        return [
            static::type() => self::mapConfig(),
        ];
    }

    /**
     * Set (update) mappings for this model
     */
    public static function updateMapping(){
        $db = self::getDb();
        $command = $db->createCommand();
    if(!$command->indexExists(self::index())){
      $command->createIndex(self::index());
    }
        $command->setMapping(self::index(), self::type(), self::mapping());
    }
  
  public static function getMapping(){
    $db = self::getDb();
        $command = $db->createCommand();
    return $command->getMapping();
  }
  
  
  
}

 

index()方法,可以看成mysql的db

type()可以看成mysql的table,但是实质是有差别的。

mapConfig()是配置mapping,关于elasticSearch的mapping,您可以参看下面的一些资料:

https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html

http://blog.csdn.net/lvhong84/article/details/23936697

等等,您可以去搜搜。

由于我不想让elasticSearch 进行分词等操作,我只是想当成一个和数据库类似的搜索,因此,我的mapping的定义为:”index” => “not_analyzed”

当然,index部分,您可以不定义,直接用默认的方式,是会被分词的。mapping类似于一个表定义。

当model建立好,您如果定义了mapping,那么您需要执行一下方法updateMapping(),让es建立mapping,该方法执行一次就可以了。

如果您需要在mapping中添加其他的字段,那么添加后在运行一次updateMapping()

另外需要注意的是:elasticSearch的mapping是不能删除的,建了就是建了,如果要删除,您只能删除index(相当于mysql的db),然后重建mapping,因此,您最好写一个脚本,执行es的所有model的mapping。

到这里,model就讲述完了、

 

Yii2 elasticSearch – 配置部分

配置部分如下:

'elasticsearch' => [
        'class' => 'yii\elasticsearch\Connection',
        'nodes' => [
            ['http_address' => '192.168.0.199:9200'],
            ['http_address' => '192.168.0.210:9200'],
        ],
    ],

您配置了es的集群,那么需要在http_address中把每一个节点的ip都要配置上,

我只有两个节点,那么,我只写了两个IP。

这样就完成了在Yii2中es的配置。

composer 默认地址改为中国镜像地址,以及中国镜像地址还原成默认地址

一、查看当前镜像地址

在命令行输入如下命令,即可查看镜像地址:

$ composer config -g repo.packagist
{"type":"composer","url":"https://packagist.org","allow_ssl_downgrade":true}

也可以使用 composer config -l -g 查看所有全局配置

下面有把地址修改为中国镜像,如果中国镜像出现了问题,那么您可以还原成官方的默认地址,下面是详细。

二、启用中国全量镜像服务:

启用中国全量镜像服务有两种方式,具体配置方法如下:

1. 系统全局配置:

即将配置信息添加到 Composer 的全局配置文件 config.json 中。修改composer的全局配置文件(推荐方式),打开命令行并执行如下命令:

默认地址改为中国镜像地址:

composer config -g repo.packagist composer https://packagist.phpcomposer.com

中国镜像地址还原成默认地址:(注意:这个是将中国镜像还原)

composer config -g repo.packagist composer https://packagist.org

 

2. 单个项目配置:

即将将配置信息添加到某个项目的 composer.json 文件中。修改当前项目的composer.json配置文件有两种方式,最后都是向文件中添加如下配置信息:

"repositories": {
    "packagist": {
        "type": "composer",
        "url": "https://packagist.phpcomposer.com"
    }
}

2.1 打开命令行并进入项目的根目录(也就是 composer.json 文件所在目录),执行如下命令:

默认地址改为中国镜像地址:

composer config repo.packagist composer https://packagist.phpcomposer.com

该命令将会在当前项目中的 composer.json 文件的末尾自动添加镜像的配置信息

中国镜像地址还原成默认地址:(注意:这个是将中国镜像还原)

composer config repo.packagist composer https://packagist.org

2.2 手动向composer.json文件中添加以上信息

默认地址改为中国镜像地址:

"repositories": {
    "packagist": {
        "type": "composer",
        "url": "https://packagist.phpcomposer.com"
    }
}

中国镜像地址还原成默认地址(注意:这个是将中国镜像还原)

将url的值改为:https://packagist.org

 

 

 

 

 

 

 

 

 

 

 

 

 

Yii2 controller 传值给layout

在yii2中,我们通过下面的方法,将controller的数组传递给view

public function actionIndex()
    {
        $data = ['xx' => 'yy'];
        return $this->render($this->action->id,$data);
    }

在view文件中就可以使用$xx变量了,这个变量的值是’yy’.

现在我们想给layout里面传递,怎么办呢?下面是原理:

在yii/base/Controller.php中可以看到如下代码:

public function render($view, $params = [])
    {
        $content = $this->getView()->render($view, $params, $this);
        return $this->renderContent($content);
    }

查找renderContent()方法

public function renderContent($content)
   {
       $layoutFile = $this->findLayoutFile($this->getView());
       if ($layoutFile !== false) {
           return $this->getView()->renderFile($layoutFile, ['content' => $content], $this);
       }
       return $content;
   }

可以看到,我们只要重写renderContent()方法,在这个方法的内容部分:

[‘content’ => $content]

在这个数组中,添加上我们的想要的其他的数组,譬如:

[‘content’ => $content, ‘tt’ => ‘terry’]

我们就可以在layout里面使用$tt变量了。也就是将controller中的变量传递给layout。

 

 

css js 后面加版本号的原因和方式

在网站加载的时候,为了快速,浏览器一般会缓存js和css,但是,我们网站如果更新了css和js,怎么告诉浏览器呢、?我么可以通过js和css url的参数方式来解决。

譬如:

/assets/dbdba3fa/js/js.js?v=2

在fecshop中,可以通过参数配置的方式,全部更改js和css的版本号。

如果我们更改了js,那么我们修改为

/assets/dbdba3fa/js/js.js?v=3

,由于是不同的链接,浏览器本地没有这个链接的内容,自然就会去服务器获取这个js的内容。

这也就是为什么我们看到很多网站的css和js后面带这个奇怪的v参数的原因。

网站的图片,css,js 为什么要和网站的域名不一样

在很多网站,我们会发现这么一个问题,为什么很多网站的image js  css 和网站的域名不一样呢?

譬如网站是www.fecshop.com , 但是图片地址为image1.tomtop.com

css和js的地址为xxx.fecshop.com,为什么要这样搞呢?

下面细说一下原因,原因有两点:

1.浏览器在并发加载网站链接内容的时候,每一个域名的并发加载url都有一定的数量限制,如果用不同的域名,那么一次性加载的url就会变多,这样可以快速渲染加载页面。

2.网站一般都是有状态的,也就是有cookie和session等,无论什么链接,都要发送cookie的,譬如网站是www.fecshop.com,那么www.fecshop.com/logo.jpg也是会发送cookie的,包括js和css文件,都会发送cookie,这就带来无意义的发送,增加额外开销,因此,对于图片js,css等,我们使用不同的域名,就不会发送cookie了。

上面是我想到的两点,如果有其他的观点,欢迎拍砖。

当然, 也有的是为了CDN的考虑,用不同的域名解析都CDN服务器上面。