回写机制造成session '无法被删除'

今天在项目开发中遇到一个“天坑”,没错,一个耗了大半天也没解决的bug,最好幸好 @破鱼缸 的点拨,茅塞顿开。记录一下

####具体业务就不说了,问题重现步骤抽象如下:

新建一个php文件,test.php

1
2
3
4
5
6
7
8
9
10
11
12
<?php
// 把session的类引进来,看这里[RedisSessionHandler]("http://minishine.github.io/2015/07/29/session存储到redis/", "Title")。把文件下面的测试部分的代码去掉
session_start(); // 开启一个会话
$_SESSION['name'] = "luren5"; // 在session里面加点内容
$redis = new Redis();
$redis->connect("172.32.1.201", 6379);
$key = session_id();
$redis->del($key); //显式的删除这个session
print_r($_SESSION); //还是可以正常打印出数据,去库里查看这条数据还在

要达到目的可以直接把session_id 对应的内容置为空即可

vim下NERDTree配置及快捷键

###配置NERDTree
NERDTree是vim下的一个很好用的插件,它可以把所有文件以树形菜单的形式展现出来,类似于IDE那样

1、下载插件,解压后把 plugin/NERD_tree.vimdoc/NERD_tree.txt 分别拷贝到 ~/.vim/plugin~/.vim/doc 目录下。

2、安装已经完成,进入需要编辑的目录后输入vim,然后再 shift + : 输入NERDTree就可以看到树形菜单了。不过每次都是要输入NERDTree非常麻烦, 改可以简化一下。

3、编辑 ~/.vimrc文件(如果没有自己新建一个),在最后一行添加一句

Read More

设计模式分享

mark~在新浪的时候,一个小组技术分享会

###什么是设计模式?
设计模式是一套代码设计经验的总结

###为什么要提倡“Design Pattern“
根本原因是为了代码复用,增加可维护性

###几个误区
设计模式并非起源于计算机科学,而是建筑学

###设计模式并非只有23种
设计模式并不只适用于面向对象

###面向对象设计的5大原则

####1)单一职责原则
避免相同的职责分散到不同的类中;避免一个类承担太多的职责
eg:活字印刷术,拆分成词?
工厂模式,只负责生产对象,但是不负责对象的具体实现

####2)接口隔离原则
一个类对另一个类的依赖性应当是建立在最小的接口上的;客户端程序不应该依赖它不需要的接口方法
eg: 缓存基类,(连接、关闭,get、set操作)但是不应该有(zset、zget)此类操作
多继承防止胖接口, 或者考虑组合

####3)开放封闭原则
一个模块在可扩展性方面应该是开放的,在可更改方面应该是封闭的
eg: 电脑组装的案例

4)里氏替换原则

子类必须能够替换掉它们的父类型、并出现在父类能够出现的任何地方
eg: 手机 到 智能机 (最基本的电话短信功能,可以添加任何其它功能 mp3,导航等,它依然是手机,但是如果它不能打电话发短信呢?最多是个pad)

####5)依赖倒置原则
上层模块不应该依赖于下层模块 ,它们共同依赖于一个抽象(父类不能依赖于子类,它们都要依赖抽象类),抽象不应该依赖于具体,具体应该依赖于抽象
因为抽象是相对稳定,不易变化的
eg: 给前端同事提供接口,基类两个抽象方法 (接收并检查参数,返回约定格式的结果) 那么不管你是怎么具体来实现的,谁来实现,都应该依赖于这个抽象

###设计模式的分类,总体来说设计模式分为三大类:

创建型模式,共五种

工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种

适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种

策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

下面与大家分享10种常用的设计模式

1、单例模式

保证某个类只有一个实例

class MysqlStorage {

private static $_instance = null;

public function __constant() {

// do something

}

public static function getInstance() {

if(self::$_instance == null ) {

self::$_instance = new MysqlStorage;

}

return self::$_instance;

}

}

Q2:php是非常驻内存的,脚本执行完之后就释放所有内存,那么这个单例模式的好处是什么呢?

2、工场模式

创建对象的类

abstract class Operation {

abstract public function operate($num1, $num2);

}

class operationAdd extends Operation {

public function operate($num1, $num2) {

return $num1 + $num2;

}

}

class operationSub extends Operation {

public function operate($num1, $num2) {

return $num1 - $num2;

}

}

// ……

class Factory {

public static function createObj($operate) {

$class = “operation”.ucfirst(strtolower($operate));

return new $class;

}

}

$test = Factory::createObj(‘add’);

echo $test->operate(23, 0);

如果我们再添加一个 取余运算,传统的方法会让switch分支添加,代码庞杂,不易维护。如果用工厂模式直接再添加一个运算类继承基类,这样就避免修改原来的代码,很好的实现 开放封闭原则、而工厂类只负责对象的生产,而不负责对象的具体实现,也体现了单一职责原则。

3)、抽象工厂模式

抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。

他与工厂方法模式的区别就在于,工厂模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。

也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。

产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族

抽象工厂模式所提供的一系列产品就组成一个产品族;

abstract class Engine {

public function get(){}

}

//轿车引擎

class CarEngine extends Engine{

public function get(){

echo ‘get car engine’;

}

}

//巴士引擎

class BusEngine extends Engine{

public function get(){

echo ‘get bus engine’;

}

}

//车轮

abstract class Wheel{

public function get(){}

}

//轿车车轮

class CarWheel extends Wheel{

public function get(){

  echo 'get car wheel';

}

}

//巴士车轮

class BusWheel extends Wheel{

public function get(){

 echo 'get bus wheel';

}

}

//工厂

abstract class Factory {

public static function create($class){}

}

//轿车工厂

class CarFactory extends Factory{

public static function create($class){

$class = ‘Car’.$class;

return new $class;

}

}

//巴士工厂

class BusFactory extends Factory{

public static function create($class){

$class = ‘Bus’.$class;

return new $class;

}

}

//使用例子:创建轿车的轮子,巴士的引擎

CarFactory::create(“Wheel”)->get();

BusFactory::create(“Engine”)->get();

适用场景
当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。

假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。

4)、观察者模式

定义对象之间一对多的关系,当被观察的对象状态发生改变的时候,所有观察它的对象都会得到提醒并做出相应的改变

class Location{

private $_observers = array();

public function register($sub){ / 注册观察者 /

$this->_observers[] = $sub;

}

public function trigger(){ / 统一得到更新 /

if(!empty($this->_observers)){

foreach($this->_observers as $observer){

$observer->update();

}

}

}

}

interface Observerable{

public function update();

}

class Subscriber implements Observerable{

public function update(){

echo “Callbackn”;

}

}

$location->register(new Subscriber());

$location->register(new Subscriber1());

$location->register(new Subscriber2());

$paper->trigger();

eg: 这是一种很常见的设计模式,比如美团客户端。 位置对象(获取当前的地理坐标),酒店Obj、美食Obj、KTV Obj等都观察位置对象,如果位置对象发生改变,那些这些观察它的对象也要相应发生变化

5)、策略模式

定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。策略模式使得算法可独立于使用它的客户而变化。

interface yueHui {

public function eat();

}

//策略A

class StrategyA implements yueHui {

public function eat() {

echo “我们去吃海底捞吧!”;

}

}

class StrategyB implements yueHui {

public function eat() {

echo “我们去吃麻辣烫吧,6块钱的那种!”;

}

}

// 环境类

class ownContext {

private $_strategy = null;

public function __construct(yueHui $strategy) {

$this->_strategy = $strategy;

}

public function eat() {

$this->_strategy->eat();

}

}

// 含蓄性妹子,使用策略A

$oc = new ownContext(new StrategyA);

$oc->eat();

// 奔放性妹子,使用策略B

$oc = new ownContext(new StrategyB);

$oc->eat();

6) 迭代器模式

迭代器模式提供一种访问一个容器对象中的各个元素,而又不暴露其内部细节的方法

提供一种通过对象集合或对象数组封装迭代的方法。如果需要遍历集合中不同类型的对象,则使用这种模式尤为便利。

使用迭代器可以对不同数据结构的集合封装,外部只需调用迭代器提供的接口即可,提高了应用的可扩展性。

A、通过遍历数组的方法去遍历对象 http://php.net/manual/zh/language.oop5.iterations.php

a、直接遍历

b、继承iterator接口,实现 current(), key(), next(), rewind(), valid() 这几个方法

c、实现IteratorAggregate 接口以替代实现所有的 Iterator 方法

IteratorAggregate 只需要实现一个方法IteratorAggregate::getIterator(),其应返回一个实现了 Iterator 的类的实例。

d、使用反射api

$reflect = new ReflectionObject($student);

$props = $reflect->getProperties(); // 获取属性列表

$m = $reflect->getMethods(); // 获取方法列表

e、使用class函数

get_object_vars($student);

get_class_methods(get_class($student));

B、遍历文件夹(递归,实现Iterator接口)

a、递归

b、使用DirectoryIterator类(已经实现了Iterator接口)

$dir = new DirectoryIterator(dirname(FILE));

foreach($dir as $fileinfo) {

if(!$fileinfo->isDir()) {

echo $fileinfo->getFilename(), “t”, $fileinfo->getSize(), PHP_EOL;

}

}

7) 命令模式

将一个请求封装为一个对象,从而你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销操作。

eg: 用户请求action(可能是 login、register、logout等操作),命令模式可以干掉大量的if else 操作(或者 switch)

interface ICommand {

function onCommand($name, $args);

}

class LoginCommand implements ICommand {

public function onCommand($name, $args) {

if ($name != ‘login’) {

return false;

} else {

// 执行登录命令

}

}

}

class RegisterCommand implements ICommand {

public function onCommand($name, $args) {

if ($name != ‘register’) {

return false;

} else {

// 执行注册命令

}

}

}

class CommandChain {

private $_commands = array();

public function addCommand($cmd) {

$this->_commands []= $cmd;

}

public function removeCommand() {

// 删除命令

}

public function runCommand($name, $args) {

foreach($this->_commands as $cmd) {

if ($cmd->onCommand($name, $args)) return;

}

}

}

$cc = new CommandChain();

$cc->addCommand(new LoginCommand());

$cc->addCommand(new RegisterCommand());

$cc->runCommand(‘login’, array(‘username’, ‘password’));

$cc->runCommand(‘register’, array(‘username’, ‘password’));

8)建造者模式

将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示

class Product {

public $_type = null;

public $_price = null;

public $_color = null;

public function setType($type) {

echo ‘set the type of the product,’;

$this->_type = $type;

}

public function setPrice($price) {

echo ‘set the price of the product,’;

$this->_price = $price;

}

public function setColor($color) {

echo ‘set the color of the product,’;

$this->_color = $color;

}

}

$config = array( ‘type’ => ‘shirt’, ‘price’ => 100, ‘color’ => ‘red’);

class ProductBuilder

{

public $_config = null;

public $_object = null;

public function ProductBuilder($config) {

$this->_object = new Product();

$this->_config = $config;

}

public function build() {

echo ‘
Using builder pattern:
‘;

$this->_object->setType($this->_config[‘type’]);

$this->_object->setPrice($this->_config[‘price’]);

$this->_object->setColor($this->_config[‘color’]);

}

public function getProduct() {

return $this->_object;

}

}

$objBuilder = new ProductBuilder($config);

$objBuilder->build();

$objProduct = $objBuilder->getProduct();

eg : 在创建不同的 数据库对象 实例的时候,构建的过程是一样的,但是可能因为db不同最后创建的实例不同

9)外观模式

为一个分层或一个子系统创建一个单一的入口 , 外观设计模式隐藏了调用对象的复杂性。

eg: liangliang 包接口

class SubSystem1{

public function method1(){

echo ‘ SubSystem1 method1’;

}

}

class SubSystem2{

public function method2(){

echo ‘ SubSystem2 method2’;

}

}

class SubSystem3{

public function method3(){

echo ‘ SubSystem3 method3’;

}

}

class Facade{

private $_object1 = null;

private $_object2 = null;

private $_object3 = null;

public function __construct(){

$this->_object1 = new SubSystem1();

$this->_object2 = new SubSystem2();

$this->_object3 = new SubSystem3();

}

public function methodA(){

echo ‘Facade methodA ‘;

$this->_object1->method1();

$this->_object2->method2();

}

public function methodB(){

echo ‘Facade methodB ‘;

$this->_object2->method2();

$this->_object3->method3();

echo ‘
‘;

}

}

$facade = new Facade();

$facade->methodA();

$facade->methodB();

10) 备忘录模式

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复到保存的状态

类对于对象而言是个模具, 同一类对象是具有相同的属性和方法,只是它们的属性值是不同的

eg: 爱迪生造电灯,不停的测试,材料为钨丝的时候感觉效果比较好,这个时候又把材料切换成bbb这种……最后还是发现铁丝的比较好,于是要还原原来的状态

class Light {

private $state = null;

public function __construct($state) {

$this->_state = $state;

}

//创建备忘录,将当前要保存的信息导入并实例化备忘录

public function createMemento() {

return new Memento($this->state);

}

//恢复备忘录,将Memento导入并将相关数据恢复

public function setMemento(Memento $memento) {

$this->state = $memento->state;

}

// 设置状态

public function setStatus($status) {

$this->_status = $status;

}

//展示状态数据

public function show() {

echo ‘当前状态是:’.$this->_state;

}

}

//备忘录类Memento

class Memento {

private $state;

public function __construct($state) {

$this->$_state = $state;

}

public function getState() {

return $this->_state;

}

}

//管理者类Caretaker

class Caretaker {

private $memento;

public function __set($key, $value) {

$this->$key = $value;

}

public function __get($key) {

if(isset($this->$key)) {

return $this->$key;

} else {

return NULL;

}

}

}

$light = new Light();

$light->setStatus(“钨”);

$light->show(); //初始状态为钨,比较好的状态

//创建备忘录并保存状态

$caretaker = new Caretaker();

$caretaker->memento = $light->createMemento();

//更改状态

$light->state = ‘铁’;

$light->show();

//恢复到原始状态

$light->setMemento($caretaker->memento);

$light->show();

?>

最后,感谢大家! 多有不足之处,烦请拍砖斧正…