The Wandering Isle

Jackie's blog

0%

注册:

注册地址

点击页面中间的创建免费用户,进入下一步页面:

然后就是填写各种个人信息的页面了:

填写付款信息:

付款信息会进行一个电话验证,这里需要先填写对应的电话号码和验证码,然后点立刻呼叫我,提示音之后从手机键盘上输入提示的验证码就可以完成验证

验证登录完成后进入主界面:

选择所有服务-》EC2,然后启动实例:

我选择的是Ubuntu Server 16.04 LTS (HVM), SSD Volume Type:

选择好实例类型然后点审核启动:

下载保存密钥对:

然后就能看到启动状态了:

选择创建账单警报以免超过免费流量限制:

在控制台可以看见实例已经在运行,接下来就是连接到服务器了:

使用xshell连接:

打开xshell,选择工具->用户秘钥管理者,点导入秘钥,导入刚才创建的秘钥对

然后新建连接:

设置用户身份验证方式:

点击确定后,会弹出会话窗口,第一次连接会弹出警告框,选择”接受并保存”:

点击连接,出现以下界面,表示连接成功:

在PHP的一个类中,带有static关键字的方法和属性被称为静态方法和静态属性,这样的方法和属性可以通过类直接访问,而不需要通过类对应的实例来进行访问,在类中访问静态变量以及静态属性的时候,可以使用self关键字和static关键字,两种访问方式看起来似乎没有区别,但是实际上还是不一样的

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
abstract class Person
{
public static $_className = 'Person';

public static function getIntro()
{
return 'this is a Person';
}

public function say()
{
return self::getIntro();
}

public function staticSay()
{
return static::getIntro();
}

public function getClassName()
{
return self::$_className;
}

public function staticGetClassName()
{
return static::$_className;
}
}

class Driver extends Person
{
public static $_className = 'Driver';

public static function getIntro()
{
return 'this is a Driver';
}
}

$temp = new Driver;

echo $temp->getClassName().'<br>';
echo $temp->say().'<br>';
//static
echo $temp->staticGetClassName().'<br>';
echo $temp->staticSay().'<br>';

运行之后的结果为:

Person
this is a Person
Driver
this is a Driver

由此可看出,在类中使用self关键字访问的静态方法以及静态变量时,self被解析为定义方法和变量的类,在使用static关键字访问的时候,static指的是被调用的类

在抽象类中加入方法print打印一个类的实例:

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
32
33
34
35
36
37
abstract class Person
{
public static $_className = 'Person';

public static function getIntro()
{
return 'this is a Person';
}

public function say()
{
return self::getIntro();
}

public function staticSay()
{
return static::getIntro();
}

public function getClassName()
{
return self::$_className;
}

public function staticGetClassName()
{
return static::$_className;
}
//print方法用于打印一个类的实例
public function print()
{
print_r(new self());
}
}

$temp = new Driver;
$temp->print();

运行后会报“Cannot instantiate abstract class Person”错误,原因是此时$temp->print()方法中new self()指的是定义的Person这个类,而抽象类是无法实例化的,此时将方法改为:

1
2
3
4
public function print()
{
print_r(new static());
}

即可成功运行,输出Driver Object ( ),说明此时打印出来的实例为Driver类的实例

最近开始重新拾掇自己优惠时贪便宜买的一台京东云主机,然而早已经将当年集成环境一键安装时设置的mysql密码给忘了。

于是度娘了解决办法,大致分为以下步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#停止mysqld

service mysqld stop

#以不检查权限的方式启动mysql

mysqld --skip-grant-tables&

#用root帐号以空密码的形式登录mysql

mysql -u root

#进入mysql命令行界面之后,执行以下命令 分别是 修改root用户密码、重新加载权限、退出mysql命令行界面

mysql> update mysql.user set password=PASSWORD('新密码') where user='root';
mysql> flush privileges;
mysql> quit

结果执行之后报这个错误 “Unknown column ‘password’ in ‘field list’”。

后查询得知mysql在5.7版本下已经没有password这个字段了,同一字段换成了authentication_string,因此对之前的步骤进行修改:

1
2
3
4
#修改密码的命令改为:
mysql> update mysql.user set authentication_string=password(新密码) where user='root';#修改密码
mysql> flush priviledge;#重载权限
mysql> quit;#退出mysql命令行

密码修改成功

太空舱运算符:

1
2
3
4
5
6
$a = 1 <=> 1;
//左边等于右边 $a=0
$b = 1 <=> 2;
//左边小于右边 $b=-1
$c = 2 <=> 1;
//左边大于右边 $c=1
1
2
3
4
5
6
7
$a = null;
$b = null;
$c = 1;

$d = $a ?? $b ?? $c ;

//$d = 1, 空合并运算从左到右取第一个非null值

trait是PHP自5.4版本之后加入的一种新的代码复用机制,是一种细粒度代码复用的方法。官方文档对于trait给出的解释是:

自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。
Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。
Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

trait 单词的释义为特性,很好的解释了trait这种方法的特点,可以在不同层次结构内独立的类中复用方法和属性,以一种易于理解的方式来举例,在网络游戏《魔兽世界》当中,法师,潜行者,战士是三个玩家可以操控的职业,三个职业是平等的,可以理解为继承自“角色”这一父类, 因为不管玩家使用什么职业,都能够使用坐骑,所以,父类“Character”中便可以添加一个ride()方法,表示使用坐骑,这样所有继承自“Character”的职业便都有了使用坐骑的能力。而不同的职业又有各自的特点,比如说,法师能够使用暴风雪,潜行者能够潜行,战士能够冲锋,因此,“mage”类中可以增加“blizzard”方法表示法师使用暴风雪技能,“rogue”类中加入“stealth”方法表示潜行者使用潜行技能,“worrior”类中可以增加“charge”方法表示战士使用冲锋技能,这样各职业的特点便能体现出来。而当分配装备时,问题就来了,众所周知《魔兽世界》的装备系统十分庞大,护甲分为布甲、皮甲、锁甲、板甲四种不同的种类,而不同的职业能够装备的护甲类型不完全相同,有些职业只可以装备一种类型的护甲,而有的职业可以装备大部分类型的护甲,这种时候,为了避免重复定义,trait就能够派上用场了。我们在这里定义“布甲”(cloth armour)、“皮甲”(leather armour)、“板甲”(plate armour)三个不同的trait,表示一个职业可以装备某一种护甲,这样我们定义一个职业的时候,便可以通过插入trait来定义这个职业能够装备的护甲类型,而这样一个特性又是独立于职业之外的,多个职业可以共同享有一个特性,比如,战士既可以装备板甲,也可以装备布甲,这样在声明战士这个类的时候,便可以插入多条特性,来表示战士是具有作为一个全需党的条件的:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
trait ClothArmour
{
public function putOnClothArmour()
{
//穿上一件布甲
}
}
trait LeatherArmour
{
public function putOnLeatherArmour()
{
//穿上一件皮甲
}
}
trait PlateArmour
{
public function putOnPlateArmour()
{
//穿上一件板甲
}
}
class Character
{
public function ride(){
//召唤坐骑
}
}
//法师
class Mage extends Character
{
use ClothArmour;
public function blizzard(){
//使用“暴风雪”
}
}
//战士
class Worrior extends Character
{
use ClothArmour,LeatherArmour,PlateArmour;
public function charge(){
//使用“冲锋”
}
}
//潜行者
class rogue extends Character
{
use ClothArmour,LeatherArmour;
public function stealth(){
//使用“潜行”
}
}
$worrior = new Worrior();
//继承自父类的方法,召唤坐骑
$worrior->ride();
//自身的方法,使用冲锋技能
$worrior->charge();
//战士能够装备布甲
$worrior->putOnClothArmour();
//战士能够装备皮甲
$worrior->putOnLeatherArmour();
//战士能够装备板甲
$worrior->putOnPlateArmour();

在这个事例中,就可以看到trait最基础的使用方法,trait其实是一组描述了某个特性的一些属性和方法的集合,能够很方便地进行组合与应用,耦合性低,易于维护,同时特性的引入也在某些程度上减少了层层继承之后必须不断追溯父类寻找某些方法的情况,提高的代码的可读性,对于提升开发工作的效率以及开发团队合作是非常好的。

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
function str_split_utf8($str)  
{
$split = 1;
$array = array();
for ($i = 0; $i < strlen($str);) {
$value = ord($str[$i]);
if ($value > 127) {
if ($value >= 192 && $value <= 223) {
$split = 2;
} elseif ($value >= 224 && $value <= 239) {
$split = 3;
} elseif ($value >= 240 && $value <= 247) {
$split = 4;
}
} else {
$split = 1;
}
$key = null;
for ($j = 0; $j < $split; $j++, $i++) {
$key .= $str[$i];
}
array_push($array, $key);
}
return $array;
}
$str = '飞流直下三千尺,疑是银河落九天';
print_r(str_split_utf8($str));

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Array
(
[0] => 飞
[1] => 流
[2] => 直
[3] => 下
[4] => 三
[5] => 千
[6] => 尺
[7] => ,
[8] => 疑
[9] => 是
[10] => 银
[11] => 河
[12] => 落
[13] => 九
[14] => 天
)

新的电脑安装了PHP、设置好环境变量之后安装了composer,想要通过composer安装Yii2,结果出现了如下报错:

1
2
3
4
5
6
7
[Composer\Downloader\TransportException]
The "https://packagist.org/packages.json" file could not be downloaded: SSL
operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify
failed
Failed to enable crypto
failed to open stream: operation failed

检查发现php.ini里面的extension=php_openssl.dll已开启,如提示所说问题的原因是证书认证失败。

解决方法:

http://curl.haxx.se/docs/caextract.html 从该网址下载证书文件cacert.pem,然后打开php.ini,找到 openssl.cafile=

添加下载证书文件的位置(例如:openssl.cafile=”E:/php-5.6.27/ext/cacert.pem”),问题解决。

简介:

$array 为一堆数组,各数组键值为固定

$keys为分组依据,在$array中按照$keys所指定的键值将数组分组,并且将除$keys指定键值对应的值以外的值合并

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
function groupBy($array,$keys){
$i = 0;
while($i < sizeof($array)){
$x = sizeof($array) - 1;
while ($x > $i) {
//取数组交集并返回交集,保留键名
$temp = array_intersect_assoc($array[$i],$array[$x]);
if(!empty($temp)){
// 取键名交集,并做比较,如果相交等于分组依据的键名,则说明两个子数组可以合并
if(array_intersect_assoc($keys,array_keys($temp)) == $keys){
foreach ($array[$i] as $k => $v) {
if(!in_array($k,$keys)){
$array[$i][$k] += $array[$x][$k];
}
}
//将合并部分移出数组
array_splice($array,$x,1);
}
}
$x--;
}
$i++;
}
return $array;
}

//测试:
$arr = array(
array(
'province' => 'Guangdong',
'city' => 'Guangzhou',
'num1' => 25,
'num2' => 15,
'num3' => 43,
),
array(
'province' => 'Guangdong',
'city' => 'Guangzhou',
'num1' => 25,
'num2' => 15,
'num3' => 43,
),
array(
'province' => 'Guangdong',
'city' => 'Guangzhou',
'num1' => 33,
'num2' => 24,
'num3' => 32,
),
array(
'province' => 'Jiangsu',
'city' => 'Nanjing',
'num1' => 25,
'num2' => 115,
'num3' => 423,
),
array(
'province' => 'Jiangsu',
'city' => 'Nanjing',
'num1' => 0,
'num2' => 15,
'num3' => 1,
),
array(
'province' => 'Jiangsu',
'city' => 'Nanjing',
'num1' => 5,
'num2' => 2,
'num3' => 4,
),
array(
'province' => 'Jiangsu',
'city' => 'Nanjing',
'num1' => 5,
'num2' => 2,
'num3' => 4,
),
array(
'province' => 'Jiangsu',
'city' => 'Nanjing',
'num1' => 5,
'num2' => 2,
'num3' => 4,
),
array(
'province' => 'Guangdong',
'city' => 'Guangzhou',
'num1' => 1,
'num2' => 2,
'num3' => 3,
),
array(
'province' => 'Shanghai',
'city' => 'Shanghai',
'num1' => 25,
'num2' => 15,
'num3' => 43,
),
array(
'province' => 'Jiangsu',
'city' => 'Nanjing',
'num1' => 25,
'num2' => 15,
'num3' => 43,
),
array(
'province' => 'Henan',
'city' => 'Zhengzhou',
'num1' => 25,
'num2' => 15,
'num3' => 43,
),
array(
'province' => 'Hunan',
'city' => 'Changsha',
'num1' => 25,
'num2' => 15,
'num3' => 43,
),
array(
'province' => 'Hunan',
'city' => 'Changsha',
'num1' => 3,
'num2' => 4,
'num3' => 5,
),
);
$keys = array(
'province',
'city'
);
$arr = groupBy($arr,$keys);

输出结果:

原文地址

数据库驱动及URL对应表

注:一般在win7中,数据连接时默认生成的URL中的驱动类型是Access2007,如果连接失败,则本地安装Access2007或以上版本驱动,或者将默认生成的URL中驱动类型改成Access2003类型。

PHP 在 5.3引入了匿名函数closure的概念,这个也就是俗称的闭包,指的是包含有未绑定到特定对象的变量(自由变量)的代码块

创建closure对象:

1
2
3
$foo = function(){
};//因为相当于将一个closure对象赋值给对象,要遵循对象赋值语法,语句结束需要添加分号
$foo();

闭包声明参数以及调用外部变量:

1
2
3
4
5
6
$value = 'hello';
$foo = function($bar) use ($value){
echo $value . $bar;
};
$foo('world');//输出helloworld
/*PHP版本5.4以上$this才可用于匿名函数*/

使用引用和不使用引用,根据官方文档:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$result = 0;

$one = function()
{ var_dump($result); };

$two = function() use ($result)
{ var_dump($result); };

$three = function() use (&$result)
{ var_dump($result); };

$result++;

$one(); // outputs NULL: $result is not in scope
$two(); // outputs int(0): $result was copied
$three(); // outputs int(1)
?>

不使用引用时,在闭包内部的$result实际是声明时候对外部变量$result的复制,因此闭包内部对$result的处理不会影响到外部变量result,而使用引用则闭包内$result直接指向外部变量$result的内存地址,因此会对外部$result造成影响:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php 
$x = 0;
$foo = function() use ($x){
$x++;
echo $x;
};

$bar = function() use (&$x){
$x++;
echo $x;
};
$foo();
$foo();
$bar();
$bar();
//输出 11 12
?>

因为闭包的存在,我们便可以在不需要在外部声明回调函数的情况下使用一些类似于array_walk的方法,比如官方手册中提供的购物车的方法:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
// 一个基本的购物车,包括一些已经添加的商品和每种商品的数量。
// 其中有一个方法用来计算购物车中所有商品的总价格,该方法使
// 用了一个 closure 作为回调函数。
class Cart
{
const PRICE_BUTTER = 1.00;
const PRICE_MILK = 3.00;
const PRICE_EGGS = 6.95;

protected $products = array();

public function add($product, $quantity)
{
$this->products[$product] = $quantity;
}

public function getQuantity($product)
{
return isset($this->products[$product]) ? $this->products[$product] :
FALSE;
}

public function getTotal($tax)
{
$total = 0.00;

$callback =
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};

array_walk($this->products, $callback);
return round($total, 2);;
}
}

$my_cart = new Cart;

// 往购物车里添加条目
$my_cart->add('butter', 1);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 6);

// 打出出总价格,其中有 5% 的销售税.
print $my_cart->getTotal(0.05) . "\n";
// 最后结果是 54.29
?>