学而不思则罔,思而不学则怠

0%

原理

国际化 i18nYii2 的核心组件,应用 bootstrapi18n 就会被实例化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// yii2/base/Application.php
public function coreComponents()
{
return [
'log' => ['class' => 'yii\log\Dispatcher'],
'view' => ['class' => 'yii\web\View'],
'formatter' => ['class' => 'yii\i18n\Formatter'],
'i18n' => ['class' => 'yii\i18n\I18N'],
'mailer' => ['class' => 'yii\swiftmailer\Mailer'],
'urlManager' => ['class' => 'yii\web\UrlManager'],
'assetManager' => ['class' => 'yii\web\AssetManager'],
'security' => ['class' => 'yii\base\Security'],
];
}

默认情况 i18n 会把实现交给 yii\i18n\PhpMessageSource 类,这也是项目中最常用的方式。在不修改应用配置的情况下,只需要将多语言的 php 文件放到 @app/messages 目录下即可。如 zh-CN 中文配置 @app/messages/zh-CN/app.php,文件名必须为 app.php

除此外还有 yii\i18n\GettextMessageSourceyii\i18n\DbMessageSource 可用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// yii2/i18n/I18N.php
public function init()
{
parent::init();
if (!isset($this->translations['yii']) && !isset($this->translations['yii*'])) {
$this->translations['yii'] = [
'class' => 'yii\i18n\PhpMessageSource',
'sourceLanguage' => 'en-US',
'basePath' => '@yii/messages',
];
}

if (!isset($this->translations['app']) && !isset($this->translations['app*'])) {
$this->translations['app'] = [
'class' => 'yii\i18n\PhpMessageSource',
'sourceLanguage' => Yii::$app->sourceLanguage,
'basePath' => '@app/messages',
];
}
}

如何配置,如何使用?关键要理解 i18n 是如何根据配置文件加载多语言文件的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// yii2/i18n/I18N.php
public function getMessageSource($category)
{
// 判断 $category 在配置中是否存在
// 1. 先进行完全匹配
// 2. 再匹配结尾带 * 的配置
// 3. 最后直接引用 * 配置
// 如果某步成功,就把任务交给 PhpMessageSource,
// 并将 $category 传递给 PhpMessageSource
}

// yii2/i18n/PhpMessageSource.php
protected function getMessageFilePath($category, $language)
{
// PhpMessageSource 关键任务是找到多语言文件的路径
// 根据 $category 获取多语言文件的路径
// 1. 先从 fileMap 配置中获取路径
// 2. 再用 $category 拼接路径
// loadMessages() 方法根据路径加载多语言数据返回 I18N
}

使用

  1. 简单配置

    配置文件如下:

    1
    2
    3
    4
    5
    6
    7
    8
    'i18n' => [ 
    'translations' => [
    'demo' => [
    'class' => 'yii\i18n\PhpMessageSource',
    'basePath' => '@app/messages',
    ],
    ],
    ],

    文件存放位置:

    1
    @app/messages/zh-CN/demo.php

    引用:

    1
    Yii::t('demo', 'key');
  2. 分层级,通过文件目录实现

    配置文件如下:

    1
    2
    3
    4
    5
    6
    7
    8
    'i18n' => [ 
    'translations' => [
    'demo*' => [
    'class' => 'yii\i18n\PhpMessageSource',
    'basePath' => '@app/messages',
    ],
    ],
    ],

    文件存放位置:

    1
    @app/messages/zh-CN/demo/common.php

    引用:

    1
    Yii::t('demo/common', 'key');
  3. 分层级,通过配置实现

    配置文件如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    'i18n' => [ 
    'translations' => [
    'demo*' => [
    'class' => 'yii\i18n\PhpMessageSource',
    'basePath' => '@app/messages',
    'fileMap' => [
    // 文件名应该与键名对应,即 common.php
    // 此处只是为了说明问题
    'demo/common' => 'main.php'
    ]
    ],
    ],
    ],

    文件存放位置:

    1
    @app/messages/zh-CN/main.php

    引用:

    1
    Yii::t('demo/common', 'key');
  4. 模块中独立配置

    在模块入口文件 Module.php 中,增加如下代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public function init()
    {
    parent::init();

    if ( !isset(Yii::$app->get('i18n')->translations['demo*']) ) {
    Yii::$app->get('i18n')->translations['demo*'] = [
    'class' => 'yii\i18n\PhpMessageSource',
    'basePath' => __DIR__ . '/messages',
    'fileMap' => [
    'demo/common' => 'common.php',
    ],
    ];
    }
    }

    多语言文件放在模块的 ./messages/ 目录下。

    引用:

    1
    Yii::t('demo/common', 'key');

环境

  1. VirtualBox 5.1.30
  2. 主机 Windows 10
  3. 虚拟机 Ubutnu Sever 16.04

目标

实现主机目录与虚拟机共享,虚拟机搭建测试环境,目录指向共享目录,主机中编码开发。测试环境可以在团队中共享。

安装 VBoxGuestAdditions

  1. 准备

    安装 kernel headersbuild tools,执行如下命令。

    1
    2
    # 请使用 root 用户操作
    apt-get install build-essential module-assistant
  2. 安装

    将 VBoxGuestAdditions.iso 文件解压上传到虚拟机后安装,VBoxGuestAdditions.iso 文件可以在 VirtualBox 安装目录中找到。

    1
    2
    3
    4
    5
    # 请使用 root 用户操作
    cd VBoxGuestAdditions
    chmod a+x VBoxLinuxAdditions.run
    ./VBoxLinuxAdditions.run
    # 安装完成后重启虚拟机

目录共享

  1. 配置共享目录

    vbox-guest-additions-01

  2. 挂载共享目录

    虚拟机中新建 /www/wwwroot 目录作为挂载点。

    1
    mkdir -p /www/wwwroot

    将虚拟机 /rec/rc.local 文件下载,添加如下内容,然后上传覆盖原文件。

    1
    2
    mount -t vboxsf wwwroot /www/wwwroot
    exit 0

    wwwroot 为上一步配置的 共享文件夹名称

  3. 检查效果

    完成以上两步后重启虚拟机,然后看看 /www/wwwroot 目录与主机 wwwroot 目录内容是否相同。

异常处理

  1. 软链接错误

    1
    2
    3
    cd /www/wwwroot
    ln -s /home/website website
    ln: failed to create symbolic link `website': Read-only file system
    1
    2
    # php 项目提示如下错误
    symlink(): Read-only file system

    解决办法:

    在主机中以管理员权限执行如下命令:

    1
    VBoxManage setextradata "VM-NAME" VBoxInternal2/SharedFoldersEnableSymlinksCreate/SHARE-FOLDER 1

    请将 VirtualBox 安装目录加入环境变更 Path 中
    VM-NAME 虚拟机名称,SHARE-FOLDER 为共享文件夹名称

    同样以管理员权限执行如下命令,以无界面方式启动/停止虚拟机:

    1
    2
    VBoxManage startvm "VM-NAME" --type headless
    VBoxManage controlvm "VM-NAME" poweroff

简介

安装

  1. Linux / Unix / OSX 系统

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 下载安装程序
    php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    # 校验安装程序,此步可以忽略
    php -r "if (hash_file('SHA384', 'composer-setup.php') === '55d6ead61b29c7bdee5cccfb50076874187bd9f21f65d8991d46ec5cc90518f447387fb9f76ebae1fbbacf329e583e30') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
    # 运行安装程序
    php composer-setup.php
    # 删除安装程序
    php -r "unlink('composer-setup.php');"
    # 全局安装
    mv composer.phar /usr/local/bin/composer

    如果出错请尝试使用 sudo 执行。

  2. Windows 系统

    下载并且运行 Composer-Setup.exe,它将安装最新版本的 Composer ,并设置好系统的环境变量,因此你可以在任何目录下直接使用 composer 命令。

配置

  1. 修改 Packagist 镜像源

    1
    2
    3
    4
    # 配置只在当前项目生效
    composer config repo.packagist composer https://mirrors.aliyun.com/composer/
    # 取消当前项目配置
    composer config --unset repos.packagist
    1
    2
    3
    4
    # 配置全局生效
    composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
    # 取消全局配置
    composer config -g --unset repos.packagist

简介

Yii 是一个高性能,基于组件的 PHP 框架,用于快速开发现代 Web 应用程序。 名字 Yii (读作 易)在中文里有“极致简单与不断演变”两重含义, 也可看作 Yes It Is! 的缩写。

安装

推荐使用 composer 安装,如果还没有安装 composer移步

先安装 Composer Asset Plugin 插件:

1
composer global require fxp/composer-asset-plugin

选择所需的 Yii2 应用模板进行安装:

1
2
3
4
# Basic 
composer create-project yiisoft/yii2-app-basic yii-basic
# Advanced
composer create-project yiisoft/yii2-app-advanced yii-advanced

进入项目目录并初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ ./init
Yii Application Initialization Tool v1.0

Which environment do you want the application to be initialized in?

[0] Development
[1] Production

Your choice [0-1, or "q" to quit] 0

Initialize the application under 'Development' environment? [yes|no] yes

Start initialization ...

上面初始化项目为开发状态。

配置数据库信息,迁移数据:

1
2
3
4
5
6
7
8
9
10
11
12
# 打开配置文件
# common\config\main-local.php
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=yii2advanced',
'username' => 'root',
'password' => 'root',
'charset' => 'utf8',
'tablePrefix' => 'yii_'
],
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 迁移数据
$ ./yii migrate
Yii Migration Tool (based on Yii v2.0.12)

Creating migration history table "yii_migration"...Done.
Total 1 new migration to be applied:
m130524_201442_init

Apply the above migration? (yes|no) [no]:yes
*** applying m130524_201442_init
> create table {{%user}} ... done (time: 0.020s)
*** applied m130524_201442_init (time: 0.035s)


1 migration was applied.

Migrated up successfully.

配置服务器

使用 Apache 服务器:

1
2
3
4
5
6
7
8
9
10
11
12
# 将 path/to/basic/web 修改为项目的实际目录
DocumentRoot "path/to/basic/web"

<Directory "path/to/basic/web">
# 开启 mod_rewrite 用于美化 URL 功能的支持
RewriteEngine on
# 如果请求的是真实存在的文件或目录,直接访问
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# 如果请求的不是真实文件或目录,分发请求至 index.php
RewriteRule . index.php
</Directory>

或使用 Nginx 服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 将 path/to/basic/web 修改为项目的实际目录
server {
charset utf-8;
client_max_body_size 128M;

listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6

server_name mysite.local;
root /path/to/basic/web;
index index.php;

access_log /path/to/basic/log/access.log;
error_log /path/to/basic/log/error.log;

location / {
try_files $uri $uri/ /index.php$is_args$args;
}

location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
try_files $uri =404;
}

location ~* /\. {
deny all;
}
}

验证测试

浏览器中 打开,如下图。

yii2-start-01

安装

hexo-filter-sequence 插件:

1
npm install --save hexo-filter-sequence

配置

站点配置文件 _config.yml 中增加如下配置:

1
2
3
4
5
6
7
8
9
sequence:
raphael: https://cdn.bootcss.com/raphael/2.2.8/raphael.min.js
webfont: https://cdn.bootcss.com/webfont/1.6.28/webfontloader.js
snap: https://cdn.bootcss.com/snap.svg/0.5.1/snap.svg-min.js
underscore: https://cdn.bootcss.com/underscore.js/1.9.1/underscore-min.js
sequence: https://cdn.bootcss.com/js-sequence-diagrams/1.0.6/sequence-diagram-min.js
# css: # optional, the url for css, such as hand drawn theme
options:
theme: simple

源码

源码修改后才能正常使用,进入插件目录作如下修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// index.js
var assign = require('deep-assign');
var renderer = require('./lib/renderer');

hexo.config.sequence = assign({
webfont: 'https://cdnjs.cloudflare.com/ajax/libs/webfont/1.6.27/webfontloader.js',
// sequence-diagram 1.x 版本依赖 raphael, 2.x版本依赖 snap
raphael: 'https://cdnjs.cloudflare.com/ajax/libs/raphael/2.2.7/raphael.min.js',
snap: 'https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg-min.js',
underscore: 'https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js',
sequence: 'https://cdnjs.cloudflare.com/ajax/libs/js-sequence-diagrams/1.0.6/sequence-diagram-min.js',
css: '',
options: {
theme: 'simple'
}
}, hexo.config.sequence);

hexo.extend.filter.register('before_post_render', renderer.render, 9);
1
2
3
4
5
6
7
8
9
10
11
12
// lib/renderer.js, 25 行
if (sequences.length) {
var config = this.config.sequence;
// resources
data.content += '<script src="' + config.webfont + '"></script>';
// sequence-diagram 1.x 版本依赖 raphael, 2.x版本依赖 snap
data.content += '<script src="' + config.raphael + '"></script>';
data.content += '<script src="' + config.snap + '"></script>';
data.content += '<script src="' + config.underscore + '"></script>';
data.content += '<script src="' + config.sequence + '"></script>';
......
}

示例

新建文章,增加如下内容:

1
2
3
Alice->Bob: Hello Bob, how are you?
Note right of Bob: Bob thinks
Bob-->Alice: I am good thanks!

安装

hexo-filter-flowchart 插件:

1
npm install --save hexo-filter-flowchart

配置

站点配置文件 _config.yml 中增加如下配置:

1
2
3
4
5
6
7
8
9
flowchart:
raphael: https://cdn.bootcss.com/raphael/2.2.8/raphael.min.js
flowchart: https://cdn.bootcss.com/flowchart/1.11.3/flowchart.min.js
options:
scale: 1,
line-width: 2
line-length: 50
text-margin: 10
font-size: 12

示例

新建文章,增加如下内容:

1
2
3
4
5
6
7
8
9
10
st=>start: 开始:>http://www.google.com[blank]
e=>end: 结束:>http://www.google.com[blank]
op1=>operation: 操作
sub1=>subroutine: 子流程
cond=>condition: 成功?:>http://www.google.com[blank]
io=>inputoutput: 输入输出...

st->op1->cond
cond(yes)->io->e
cond(no)->sub1(right)->op1

环境

  • Windows10
  • Zend Guard 7.0 (32 bit)
  • Nginx 版 UPUPW PHP5.6 系列环境包

准备

下载 Zend Guard、Nginx 版 UPUPW PHP5.6 系列环境包、Zend Guard Loader 软件;安装 Zend Guard,将 UPUPW PHP5.6 解压到合适的目录,
将 Zend Guard Loader 解压到 UPUPW PHP5.6 下的 PHP/ext 目录并替换原扩展。

配置

打开 UPUPW PHP5.6/PHP5/php.ini 文件,修改如下配置:

1
2
3
4
5
6
[ZendLoader]
zend_extension ="C:\DevTools\UPUPWNP5.6\PHP5\ext\php_ZendLoader.dll"
zend_loader.enable = 1
zend_loader.disable_licensing = 0
zend_loader.obfuscation_level_support = 3
zend_loader.license_path = "C:\DevTools\UPUPWNP5.6\htdocs\guard\licenses"

参数 zend_extension 为扩展存放目录,参数 zend_loader.license_path 为授权文件存放目录,请根据实际情况配置。

打开 UPUPW PHP5.6 控制面板【开启全部服务】:

zend-guard-01

浏览器打开 http://localhost/u.php 地址,检查 Zend Guard Loader 扩展是否正常开启:

zend-guard-02

源码

先准备源文件 demo/index.php,代码如下:

1
2
3
<?php
phpinfo();
?>

新建项目

菜单中新建项目,输入项目名称,选择输出目录:

zend-guard-03

添加源代码目录:

zend-guard-04

源代码配置参数:

zend-guard-05

基本配置完成:

zend-guard-06

配置加密授权信息:

zend-guard-07

生成授权文件:

zend-guard-08

加密后的文件:

zend-guard-09

测试

将加密输出的文件拷贝到 Web 目录,浏览器中打开。

ngrok 是什么

百度百科
官网

ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。ngrok 可捕获和分析所有通道上的流量,便于后期分析和重放。

官方版本 ngrok 有太多的限制,免费用户最多启动4个节点且不能自定义域名,所以我们跳过它直接介绍 sunny 的使用。

sunny 才是福利

  1. 注册账号

    先到 sunny 官网 注册账号

  2. 开通隧道

    在后台管理界面选择:隧道管理->开通隧道->选择免费产品,点击立即购买。

    ngrok-sunny-01

    填写表单:隧道协议、隧道名称、前置域名、本地端口,然后点击确定添加。

    ngrok-sunny-02

    返回隧道列表或点击隧道管理菜单,可以看到刚刚申请的隧道信息。

    ngrok-sunny-03

  3. 运行客户端

    下载 sunny 客户端,根据需要下载不同版本。

    命令行启动客户端:

    1
    2
    3
    4
    # windows
    sunny clientid d3fdc171be3a94a0,e3fc6b1431a51e89
    # linux
    ./sunny clientid d3fdc171be3a94a0,e3fc6b1431a51e89

    启动成功后就可以通过 ngrok.cc 二级域名访问自己的站点了。

自定义域名

  1. 准备域名

    首先要有自己的域名,最好是顶级的,如果没有可以到 freenom 免费领取一枚。

  2. 配置隧道自定义域名

    进入隧道编辑页面,修改域名类型、自定义域名,最后确认修改。

    ngrok-sunny-04

  3. 根据提示,修改域名的 CNAME 参数

    我的域名是从 freenom 申请的,配置方法如下图,其它域名请根据提供商文档操作。

    ngrok-sunny-05

    Target 项填入的内容要与 sunny 提供的一致,请参考上图

开机运行 sunny

这是在 Ubuntu 16.04 上做的尝试。

  1. 新建 sunny.sh 文件

    1
    2
    3
    4
    5
    6
    7
    8
    #!/bin/bash
    count=`ps -ef | grep "sunny" | wc -l`

    if [ $count -gt 0 ]; then
    killall sunny;
    fi

    /root/sunny/sunny clientid de9e30c769c73e02,0fa3f0385e227f14

    /root/sunny/sunny 为 sunny 客户端所在路径,可以将多个隧道全部写在 clientid 后面。

  2. 添加开机运行

    /ect/rc.local 文件最后增加如下命令:

    1
    2
    setsid /root/sunny/sunny.sh
    exit 0
  3. 定时重启

    新建 sunny.cron 文件,输入如下内容:

    1
    0 */1 * * * setsid /root/sunny/sunny.sh

    然后执行如下命令:

    1
    crontab sunny.cron

    系统将每小时重启一次 sunny

为什么字典表

某些变量在多个地方使用,而且一般是固定的,但是随着系统升级和后期变化,可能需要改变,如果这些变量写死在代码里面将会变得难以维护。

有的做法是使用枚举或者 Constants 常量类来实现,这种情况下在量少的前提是没问题的,但是一旦随着系统的开发拓展,后期将无法维护,甚至命名困难。

所以通常把字典放在数据库,这样后期的维护变更就比较简单,也可以在不用修改代码的情况下修改配置。

但是,放在数据库又有着频繁访问数据库的问题,这不是我们希望的,这时候通常做法就是加缓存,降低访问数据库的频率。

字典表的设计

通常分成两张表来实现,一个是字典类型,一个是字典

字典类型表: SYS_DICT_TYPE

字段名 类型 作用 备注
code varchar 编码 主键
name varchar 类型 -

字典表 : SYS_DICT

字段名 类型 作用 备注
code varchar 编码 主键
type_code varchar 类型 code 外键
name varchar 字典名 展示用
value varchar 字典值 使用值
fixed int 是否是固定的 default 0 不固定,固定的话用 1

以上是字典表的关键列和结构的设计,根据不同系统不同业务自定其他列。

作者:SevenLin1993
链接:http://www.jianshu.com/p/0034802afc1f
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

安装

Ubuntu 系统

1
2
3
$ sudo apt-add-repository ppa:git-core/ppa
$ sudo apt-get update
$ sudo apt-get install git

如果出现 apt-add-repository: command not found 错误,要先执行以下:

1
2
$ sudo apt-get install python-software-properties
$ sudo apt-get install software-properties-common

Windows 系统

下载 Git for Windows,建议下载安装版根据提示安装。
Windows 系统中,以下操作均在 Git Bash 命令窗口中执行。

配置

设置全局用户

1
2
$ git config --global user.name "Your Name"
$ git config --global user.email "youremail@gmail.com"

设置密钥

生成 ssh 密钥:

1
2
3
4
5
6
7
8
$ ssh-keygen -t rsa -C "youremail@gmail.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa): #保存位置,回车
Enter passphrase (empty For no passphrase): #加密,不加密直接回车
Enter same passphrase again: #加密校验
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
......

如果备份了 id_rsaid_rsa.pub 文件,可以直接将其复制到 ~/.ssh 目录:

1
$ cp ./id_rsa* ~/.ssh

复制后要检查密钥文件的读写权限,安全的设置如下:

1
2
3
$ ls -al ~/.ssh/id_rsa*
-rw------- 1 user grp 1675 Aug 11 02:23 /home/user/.ssh/id_rsa
-rw-r--r-- 1 user grp 401 Aug 11 02:23 /home/user/.ssh/id_rsa.pub

把密钥添加到 ssh-agent 的高速缓存中:

1
2
$ ssh-add
Identity added: /home/user/.ssh/id_rsa (/home/user/.ssh/id_rsa)

使用

将公钥内容导入远程 git 服务站点

github.comgitee.com 上申请个帐号。
id_rsa.pub 公钥内容添加到已经申请的帐号,目录如下:

1
2
3
4
# github.com
Settings -> SSH and GPG keys -> New GPG key
# gitee.com
修改资料 -> SSH公钥 -> 添加公钥

新建项目,并克隆到本地

1
2
3
$ git clone git@github.com:username/project.git
## 或
$ git clone git@gitee.com:username/project.git

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ cd project
# 拉取远程或其它仓库内容合并到本地仓库
# Fetch from and integrate with another repository or a local branch
$ git pull
# 将文件内容添加到索引中
# Add file contents to the index
$ git add --all
$ git add .
$ git add <file>...
# 提交修改到本地仓库
# Record changes to the repository
$ git commit -a -m "说明"
# 将本地暂存内容更新到远程仓库
# Update remote refs along with associated objects
$ git push