2016
02-18

依赖注入和控制反转是什么?

年前,@绵阳飞在群里发起了一个讨论,依赖注入和控制反转到底是什么?
我之前对依赖注入和控制反转也不甚理解,直至在学习Phalcon框架的过程中,发现在Phalcon文档中有一个篇幅通过代码示例的方式专门描述了依赖注入的原理。本文打算通过此文档中的代码示例来讲解什么是依赖注入(DI)和控制反转(IoC)。通过示例代码,来更加深入的了解这些概念。

接下来的例子有些长,但解释了为什么我们要使用依赖注入。所以绝对都是干货,请耐心读完,必会有所收获。

依赖的产生

首先,假设我们正在开发一个组件,叫SomeComponent,它需要执行的内容现在还不重要。 但是我们的组件需要依赖数据库连接。

<?php

class SomeComponent
{
    /**
     * 数据库连接是被写死在组件的内部
     * 因此,我们很难从外部替换或者改变它的行为
     */
    public function someDbTask()
    {
        $connection = new Connection(
            array(
                "host"     => "localhost",
                "username" => "root",
                "password" => "secret",
                "dbname"   => "invo"
            )
        );

        // ...
    }
}

$some = new SomeComponent();
$some->someDbTask();

从上面这个例子中,可以看到数据库连接是在组件内部建立的。在我们日常开发中,类似这样的依赖关系在项目中非常常见。但是这种方法其实是不太实用的;我们不能改变创建数据库连接的参数或者选择不同的数据库系统,因为数据库连接是在组件被创建时建立的。

查看全文 >
2016
02-15

奔跑吧,程序猿!

上个星期,收到了咕咚2016全国新年登高健身大会的奖牌。这是我在2015年加入跑步行动以来参加的第一场咕咚官方赛事,也是我第一次拿到与跑步这项运动相关的奖牌。虽然是阳光普照奖牌,但还是非常高兴,对我也是一种鼓励。跟大家分享一下奖牌图片:
run2.jpg

查看全文 >
2016
01-08

memcache和memcached的区别

前两天,大家在群里讨论memcache缓存时,有群友提到了在memcache中如何存储数组,并如何直接通过数组索引取值的问题?当时,大家的回答基本一致是memcache是key-value形式的内存缓存系统。对于缓存key,只能是string类型,而无法存储array类型的key。虽然大家的理解基本保持一致,但是本着求证的态度,我还是查阅了php官方文档。官方示例代码如下:

<?php
$m = new Memcached();
$m->addServer('localhost', 11211);

$items = array(
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3'
);
$m->setMulti($items);
$result = $m->getMulti(array('key1', 'key3', 'badkey'), $cas);
var_dump($result, $cas);
?>

以上代码的输出如下:

array(2) {
  ["key1"]=>
  string(6) "value1"
  ["key3"]=>
  string(6) "value3"
}
array(2) {
  ["key1"]=>
  float(2360)
  ["key3"]=>
  float(2362)
}

Memcached::setMulti()类似于Memcached::set(),它是一次存储多个key/value元素,以便于对多个元素的操作。之前我理解为key可以是array数组,但实际上并不是。setMulti()方法相当于是多次调用set()方法存储数据。在这里谢谢@乌大湿的指点。群友的问题暂时无解,那代码中的memcached和我们平常认知的memcache有何不同?

查看全文 >
2015
12-13

云服务器编译安装phalcon失败

这两天萌生想法,想做一个自己的东西。在框架选型方面,打算用Phalcon框架。一方面是上手这个框架已经三年多时间了,顺手且轻车熟路;另一方面,也是在公司大大小小的项目中经受住了洗礼。初步选型既已经确定,就即刻开始环境的准备。既然是自己的小项目,那就用自己的阿里云服务器(ECS)。
这里先简单列下ECS的配置:

1核CPU+1G内存 64位centos

问题起因

下面开始Phalcon框架的编译安装。

#下载phalcon 2.0.9安装文件
wget https://github.com/phalcon/cphalcon/archive/phalcon-v2.0.9.tar.gz

#解压phalcon 2.0.9安装文件 
tar -zxvf phalcon-v2.0.9.tar.gz
cd cphalcon-phalcon-v2.0.9/build/

#执行安装脚本
./install

在脚本执行到“make”步骤时,报错:

gcc: Internal error: Killed (program cc1)


查看全文 >
2015
11-20

phpstorm识别Phalcon语法及提示

在开发Phalcon相关项目时,phpstorm编辑器并没有Phalcon相关语法的自动提示,相对影响开发效率。下面来介绍如何让phpstorm支持对Phalcon语法的自动提示。

下载phalcon-devtools包

https://github.com/phalcon/phalcon-devtools/releases 下载phalcon-devtools,并解压到任意目录。

修改gen-stubs.php

ide/gen-stubs.php 文件中的如下三行代码注释掉:

//if (!file_exists(CPHALCON_DIR)) {
//      throw new Exception("CPHALCON directory does not exist");
//}

然后执行如下命令:

php gen-stubs.php

成功后,会看到 ide 目录下生成了Phalcon相应版本的语法文件目录(我这里是生成的 3.2.1 目录)

2、phpstorm导入Phalcon库

1.png

查看全文 >
2015
09-18

数据插入失败引发的主键auto_increment问题

昨天在调试一个业务代码中,无意间发现了一个问题。数据入库后的主键不是连续自增的,主键键值没过几秒就从两千多直接跳到了五千上下。这是为什么?瞬间引起我的注意。

先简单说明下环境。Mysql版本:5.6.23。为了防止某些数据重复,数据库中对某些字段设置了唯一索引,即unique key。经确认此表也只有一个业务程序在操作。那么,问题就定位到主键的auto_increment属性上了。

问题重现

下面来还原问题,以便能准确查找出原因。
表结构如下:

CREATE TABLE `test_innodb` (
   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
   `username` varchar(100) NOT NULL COMMENT '用户名',
   PRIMARY KEY (`id`),
   UNIQUE KEY `UNIQUE_USERNAME` (`username`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8

username字段设置了唯一索引(unique key)。先插入一条数据:

INSERT INTO test_innodb (`username`) VALUES('admin');

执行成功,主键ID为“1”。再次执行此SQL,因username重复,数据入库失败,提示:

Duplicate entry 'admin' for key 'UNIQUE_USERNAME'
查看全文 >
2015
09-03

PHP魔术方法之__set()和__get()

先来看一段代码:

class Article{
    //私有成员属性
    private $title = '标题';

    //受保护的成员属性
    protected $author = '作者';

    //公有成员属性
    public $introduce = '简介';
}

$article = new Article();
var_dump($article -> title);
var_dump($article -> author);
var_dump($article -> introduce);

对象直接访问类中的private和protected成员属性时,会报一个Fatal error的错误,提示“Cannot access private property”或者“Cannot access protected property”。


1、魔术方法__get()

如果对象要直接访问类中的private和protected成员属性呢?
PHP给我们提供了一个魔术方法“__get()”,用于获取private和protected成员属性。

class Article{

    //私有成员属性
    private $title = '标题';

    //受保护的成员属性
    protected $author = '作者';

    //公有成员属性
    public $introduce = '简介';

    //获取private和protected成员属性
    public function __get($name){·
        if(isset($this -> $name)) {
            return $this->$name;
        }
        return false;
    }

}

$article = new Article();
var_dump($article -> title);
var_dump($article -> author);
var_dump($article -> introduce);
查看全文 >
2015
05-29

剖析Redis持久化之AOF方式

上一篇对redis持久化之RDB方式进行了剖析。除了RDB持久化功能之外,Redis还提供了AOF(Append Only File)持久化功能。下面就来介绍一下AOF持久化功能。


1、AOF持久化原理

与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。并在服务器启动时,通过重新执行这些命令来还原数据库。如下图:
aof.png

顺便提一句,被写入AOF文件的所有命令都是以Redis的命令请求协议格式保存的。因为Redis的命令请求协议是纯文本格式,所以我们是可以直接打开一个AOF文件,观察里面的内容的。


2、AOF持久化配置

首先在redis.conf文件开启aof持久化(默认没开启)

appendonly yes

然后对redis.conf文件中的“appendfsync”选项进行规则配置。不同的appendfsync值产生的持久化行为也不相同。

appendfsync=always

appendfsync设置为always时,服务器在每个事件循环中将aof_buf缓冲区中的所有内容写入并同步到AOF文件。从效率来说,是三个选项值当中最慢的一个,但从安全性来说,always是最安全的,因为即使出现故障停机,AOF持久化也只会丢失一个事件循环中所产生的命令数据。

查看全文 >
2015
05-19

centos安装mongodb扩展

PHP程序要正常操作mongodb库,必须要先安装好mongodb扩展。下面就来介绍mongodb扩展的安装方法。

基础环境

  • centos7.2+
  • php7+
  • mongodb3.4+

1、下载mongo扩展包

wget http://pecl.php.net/get/mongodb-1.2.9.tgz

2、重命名并解压

下载成功后,执行如下命令:

# 解压
tar -zxvf mongodb-1.2.9.tgz
cd mongodb-1.2.9

3、编译安装

通过phpize来动态添加mongo扩展,

/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install

4、编辑php.ini

编译成功之后,需要将编译好的mongodb.so添加到php.ini配置文件当中。在php.ini的文件末尾添加如下配置:

extension=mongodb.so

重启nginx和php-fpm后,通过如下命令,

php -m

看到“mongodb”字样存在,即表示扩展安装成功。在PHP程序中就能正常mongodb了。

查看全文 >
2015
05-13

剖析Redis持久化之RDB方式

最近在阅读《Redis设计与实现》这本书,书中关于Redis的实现原理,做了相对详细的介绍与说明。
Marser整理了Redis持久化之RDB方式的原理、redis.conf配置方式、数据还原操作及RDB方式的特点。下面Marser就来做详细的介绍。

1、RDB持久化原理

RDB持久化既可以通过命令行手动执行,也可以通过redis.conf配置选项定期执行,该功能可以将某个时间点上的数据库中的键值对保存到一个rdb文件中,默认为dump.rdb。

2、RDB持久化命令

Redis中有两个命令可以用于生成RDB文件,一个是save,另一个是bgsave。这两个命令都可以通过命令行来手动执行。下面分别来介绍下这两个命令。

  save命令

执行save命令时,Redis服务器主进程会执行保存工作,所以save命令会阻塞Redis服务器进程。在Redis服务器进程阻塞期间,服务器不能处理任何从客户端发送过来的命令请求,直至RDB文件创建完毕。即save命令是做同步操作
此种方式

  bgsave命令

bgsave命令和save命令不同,在执行bgsave命令时,Redis服务器会派生出一个子进程,由这个子进程来负责执行数据保存工作,并创建RDB文件,而Redis服务器进程(父进程)则继续处理从客户端发送过来的命令请求。即bgsave命令是做异步操作

查看全文 >
微信扫一扫