5.3 迁移 5.6 需要注意的问题

👁代表额外需要注意的,✅代表遇到过

5.3 Migrating 5.4

重点

  1. breakcontinue不再接受可变参数(break 1 + max(x, y)),break 0;continue 0不允许出现
  2. 现在参数名使用全局变量将会导致一个致命错误。禁止类似 function foo($_GET, $_POST) {} 这样的代码。
  3. 非数字的字符串偏移量👁
    $a = '12345';
     var_dump(isset($a['x']); // 5.3 true, 5.4 false
  1. 调用时的引用传递👁
 function f(&$v){$v = true;}
 f(&$v); // 5.3 no problem 5.4 PHP Fatal error

 function f1($v){$v = true;}
 f1(&$v); // 5.3 no problem 5.4 PHP Fatal error

function f2(&$v){$v = true;}
f2($v); // ok

一些不常用的

  1. 不支持安全模式
  2. 移除魔术引号
  3. register_globals 和 register_long_arrays php.ini 指令被移除。

    PHP: 不向后兼容的变更 - Manual

5.4 Migrating 5.5

重点

  1. 原始的 MySQL 扩展 现在被废弃,当连接到数据库时会产生一个 E_DEPRECATED 错误。👁

PHP: 不向后兼容的变更 - Manual

5.5 Migrating 5.6

重点

  1. json_decode 严格模式
  2. cURL文件上传 👁✅
    > 必须先设置 CURLOPT_SAFE_UPLOAD为 FALSE 才能够使用 @file 语法来上传文件。 建议使用 CURLFile 类来上传文件。
  3. 使用::调用非静态方法,现在产生 E_DEPRECATED 错误 (以前是 E_STRICT)
  4. 使用 always_populate_raw_post_data 会导致在填充 $HTTP_RAW_POST_DATA 时产生 E_DEPRECATED 错误。 请使用 php://input 替代 $HTTP_RAW_POST_DATA, 因为它可能在后续的 PHP 版本中被移除。 在php.ini中设置 always_populate_raw_post_data 为 -1 (这样会强制 $HTTP_RAW_POST_DATA 未定义,所以也不回导致 E_DEPRECATED 的错误) 👁✅
  5. 使用数组标识符为类定义数组类型的属性时,数组的键不会被覆盖
    class C {
    const ONE = 1;
    public $array = [
        self::ONE => 'foo',
        'bar',
        'quux',
    ];
}
var_dump((new C)->array);
/* 5.5 before array(2) {
  [0]=>
  string(3) "bar"
  [1]=>
  string(4) "quux"
}
*
* 5.6 
* array(3) {
  [1]=>
  string(3) "foo"
  [2]=>
  string(3) "bar"
  [3]=>
  string(4) "quux"
}
*/

PHP: 向后不兼容 - Manual

其他问题

  1. 线上的php5.6没有编译fileinfo,这个会导致读不到文件信息,因为运维都是统一安装的,所以最好看一下是否enable-fileinfo

  2. 启用 Opcache,之前因为出现了一些问题,运维那边关掉这个缓存,最好和运维沟通,并测试缓存是否正确使用、正常更新。

    现代 PHP 新特性系列(六) —— Zend Opcache

PHP闭包

闭包的介绍

闭包是词法作用域的体现,一般编程语言有这些特性

  1. 函数是一阶值(First-class value),即函数可以作为另一个函数的返回值或参数,还可以作为一个变量的值。
  2. 函数可以嵌套定义,即在一个函数内部可以定义另一个函数。

三个关键点

  1. 函数
  2. 自由变量
  3. 作用域

自由变量

let a = 1
let b = function(){
    console.log(a)
}

在这个例子里函数b因为捕获了外部作用域(环境)中的变量a,因此形成了闭包。 而由于变量a并不属于函数b,所以在概念里被称之为「自由变量」。

注意点:

  1. 在一些语言里,「捕获」这一行为还有一个特点:闭包只会捕获自由变量的引用。
  2. 在PHP中,需要使用use关键词显示调用自由变量

作用域

可以使用外部的「自由变量」,内部变量不能被访问,形成一个相对安全的访问环境

总结

  1. 记住定义当时的外部环境
  2. 封闭外部环境
  3. 延迟执行

基本使用

$func = function () {

};

$func();

$a = '1';
$func = function () use ($a) {

}

$func();

作用域

  1. 闭包拥有独立的作用域,基本等同普通函数
  2. 在方法中使用时,等同于实例的方法,可以直接使用$this(>=5.4)

注意点

$this 的使用

在一次开发中遇到关于闭包的一个问题

class Demo
{
    /**
     *
     */
    public function test()
    {
        $data = $this->isCache('name', function () {
            $this->sayHello();
        });
    }

    /**
     *
     */
    protected function sayHello()
    {
        echo 'Hello, World';
    }

    /**
     * @param $name
     * @param $callback
     * @return array
     */
    public function isCache($name, $callback)
    {
        $callback();
        return array();
    }
}

我希望在一个闭包中调用这个类的一个受保护的方法(这里假设是sayHello),结果在运行的时候,直接出现了语法级别的报错。

查了一些资料发现了问题

  1. 5.3 版本不能直接在闭包中使用$this

PHP的bug,在5.4中得以修复

$that = $this;        
$data = $this->isCache('name', function () use ($that) {
    $that->sayHello(); // 这里只能是public
});

看似这个问题解决了,不过在stackoverflow上一位热心人士的提醒中,这样是会出现一些问题的,因为这样传递$this, 是赋值传递,也就是说,在闭包中调用方法导致实例属性的变化不会反应到闭包外面,这样在一些特殊情况,会导致闭包内外属性不一致,所以这里最好使用引用传递除非你知道你在干什么!

$that = $this;        
$data = $this->isCache('name', function () use (&$that) {
    $that->sayHello(); // 这里只能是public
});

如果在5.4版本下,不但可以直接使用$this,而且作用域等同于实例中的方法

$data = $this->isCache('name', function () {
    $that->sayHello(); // 这里可以是任意限制符
});

Closure类

bind和bindTo的区别

// bind,相当把一个类的加上加上一个方法,并且将该方法转换成闭包
class A {
    private static $sfoo = 1;
    private $ifoo = 2;
}
$cl1 = static function() {
    return A::$sfoo;
};
$cl2 = function() {
    return $this->ifoo;
};

$bcl1 = Closure::bind($cl1, null, 'A');
$bcl2 = Closure::bind($cl2, new A(), 'A');
echo $bcl1(), "\n"; // 1
echo $bcl2(), "\n";// 2

// bindTo,改变指定的$this对象和类作用域

class A {
    function __construct($val) {
        $this->val = $val;
    }
    function getClosure() {
        //returns closure bound to this object and scope
        return function() { return $this->val; };
    }
}

$ob1 = new A(1);
$ob2 = new A(2);

$cl = $ob1->getClosure();
echo $cl(), "\n";
$cl = $cl->bindTo($ob2);
echo $cl(), "\n";


虽然两者看上去像,实际上不是一回事。

webpack基础入门

modules with dependencies ---webpack---> static assets

使用的DEMO

介绍

模块打包工具(不仅仅只是打包js)

模块

现在的网站都在演变成为Web Apps:

  • 页面上的JavaScript越来越多。
  • 在现代浏览器上用户可以做更多的事情了。
  • 整个页面重新加载的情况更少了,与此同时,页面上的代码量更大了。

结果就是:客户端的代码量变得越来越庞大,庞大的代码量意味着我们需要适当地组织代码,而模块系统则提供了把代码分割成不同模块的功能。

模块化历史进程

  • Script标签形式
  • CommonJS(CMD)
  • AMD和一些变种实现
  • ES6模块
  • 其它

目的

  • 把依赖树按需分割
  • 把初始加载时间控制在较低的水平
  • 每个静态资源都应该能成为一个模块
  • 能把第三方库继承到项目里来成为一个模块
  • 能定制模块打包器的每个部分
  • 能适用于大型项目

简单使用

几个名称
1. node

js的服务端实现,基于CMD

  1. npm

    > node 官方认证的包管理工具,类似于php composer。非常慢(加上代理也是慢)。

  2. cnpm

    > 阿里巴巴出品的包管理工具,兼容大部分npm功能,使用淘宝源,项目结构必npm简单,更新安装新的依赖快。

  3. yarn

    > facebook 出品的包管理工具,和cnpm类似,诞生时间多,但是比cnpm热,中国码农的国际影响力不行啊,有好东西不知道宣传,cnpm比yarn不知道早多久了。yarn 比cnpm突出的一点是:默认使用lock文件,固定版本,有利于大型项目规定依赖版本。

推荐使用yarn(不过cnpm更简单一些,所以可以先用cnpm)

npm install -g cnpm --registry=https://registry.npm.taobao.org

安装Webpack-cli

cnpm install webpack -g

使用命令行

 // 最简单的命令 webpack <entry> <output>
webpack ./app.js bundle.js

额外参数

  1. -p 压缩js并且丑化
  2. --watch 监控文件改动
  3. --progress 显示构建的详细过程

详细参数文档

使用配置文件

对于一般的项目,直接使用cli是不太可能的,所以我们需要配置文件,使用配置文件有两种方式

  1. cli
  2. node api

CLI

创建 webpack.config.js 文件

 module.exports = {
     entry: './src/app.js',
     output: {
         path: './dist',
         filename: 'app.bundle.js'
     }
 };

然后在webpack.config.js文件的目录下面执行命令webpack

webpack 会自动查找目录下面的webpack.config.js,如果需要指定,可以使用--config 指定配置文件。

NODE API

创建webpack.node.js文件

var webpack = require("webpack");

webpack({
    entry: './src/app.js', // 原文件
    output: {
        path: './dist', // 输出路径
        filename: 'app.bundle.js' // 输出文件名
    }
}, function (err, stats) {
});

然后在webpack.config.js文件的目录下面执行命令node webpack.node.js

DEMO2

ES6

一个很好的ES6指南

为什么要ES6?随波逐流是个好选择,不过就自己来说我喜欢ES6的这几个方面

  1. module管理,import和export使用非常爽
  2. let不自动扩展作用域
  3. =>,解决了function this的问题

下面我们使用ES6的module管理来编写一段程序

log.js

var log = function (text) {
    console.log(text);
}

export {log};

app.js

var log = function (text) {
   console.log(text);
};

export log;

不过es6现在不是浏览器的主流支持版本,所以需要转义成es5,这里就需要使用babel

修改package.json,加入babel依赖

{
  "name": "webpack-demo",
  "version": "0.0.1",
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "^1.14.0",
    "babel-core": "^6.18.2",
    "babel-loader": "^6.2.8",
    "babel-plugin-transform-runtime": "^6.15.0",
    "babel-polyfill": "^6.16.0",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-stage-2": "^6.18.0"
  }
}

再修改webpack.config.js

module.exports = {
    entry: './src/app.js',
    output: {
        path: './dist',
        filename: 'app.bundle.js'
    },
  module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader?cacheDirectory=true'
            }
        ]
    }
};

这里使用了webpack的loader功能,这是webpack最重要的功能了,加载各个模块,打包到指定的地方。

之后我们还需要指定babel使用的规范,这里有两个选择,一个是写在webpack的config文件中,还有一个是在root dir下面创建.babelrc来指定规范,这里选择第二种(因为这样可以确保别人能一眼看出你代码书写的规范),在当前目录创建.babelrc

{
  "presets": ["es2015", "stage-2"],
  "plugins": ["transform-runtime"],
  "comments": false
}

然后在webpack.config.js文件的目录下面执行命令webpack

DEMO4

关于其他loader使用,一般是**-loader

  • url-loader
  • file-loader
  • style-loader
  • vue-loader

不过每个loader都存在一些使用的差异性,需要去查看各自的文档。

插件

之前可以使用webpack -p 压缩并且丑化js,不过在配置文件可以更详细的配置这些操作

module.exports = {
    entry: './src/app.js',
    output: {
        path: './dist',
        filename: 'app.bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader'
            }
        ]
    },
        plugins: [
            // 压缩代码
            new webpack.optimize.UglifyJsPlugin({
                compress: {
                    warnings: false
                }
            }),
            // 删除重复的依赖
            new webpack.optimize.DedupePlugin()
    ]
};

再使用webpack试试看

加入Vue

使用vue需要vue-loader这个依赖,修改package.json,这些依赖是必须要的must

{
  "name": "webpack-demo",
  "version": "0.0.1",
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "^1.14.0",
    "babel-core": "^6.18.2",
    "babel-loader": "^6.2.8",
    "babel-plugin-transform-runtime": "^6.15.0",
    "babel-polyfill": "^6.16.0",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-stage-2": "^6.18.0",
    "css-loader": "^0.25.0",
    "file-loader": "^0.9.0",
    "style-loader": "^0.13.0",
    "url-loader": "^0.5.7",
    "vue-html-loader": "^1.0.0",
    "vue-loader": "^8.0.0",
    "vue-style-loader": "^1.0.0",
    "vue-template-compiler": "^2.1.0"
  },
  "dependencies": {
    "vue": "2.*"
  }
}

webpack.config.js

var webpack = require("webpack");

module.exports = {
    entry: './src/main.js',
    output: {
        path: './dist',
        publicPath: 'dist/',
        filename: 'app.bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            },
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader'
            },
                        {
                test: /\.css$/,
                loader: 'style-loader!css-loader'
            },
            {
                test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
                loader: 'file-loader?name=font/[hash:8].[ext]'
            },
            {
                test: /\.(png|jpe?g|gif|svg)(\?\S*)?$/,
                loader: 'file-loader?name=image/[hash:8].[ext]'
            }
        ]
    },
    vue: {
        loaders: {
            js: 'babel?cacheDirectory=true'
        }

    },
    resolve: {
        alias: {
            vue: 'vue/dist/vue.js'
        }
    },
    plugins: [
        // 压缩代码
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            }
        }),
        // 删除重复的依赖
        new webpack.optimize.DedupePlugin()
    ]
};

执行webpack,为了查看具体效果,创建一个index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <div id="app"></div>

<script src="dist/app.bundle.js"></script>
</body>
</html>

浏览index.html查看具体效果吧

DMOE6


一个悲痛的消息!webpack1(就是上面的)被放弃了,现在官方推行webpack2(有一些配置的不同),据说可以减少打包文件的大小,具体还要看实际效果。

官方文档

更全面的DEMO

PHP 自动加载总结

自动加载的测试代码

https://github.com/bayuexiong/simple-composer

1. 自动加载

php的加载文件,一般分为三种情况

  1. 直接include/require,不属于自动加载,一般用于PHP5以前的版本。
  2. 使用__autoload(),PHP5.0引入,在PHP5.1.12之后不再推荐使用。
  3. 使用spl_auoload_register(),现在使用比较多,于PHP5.1.12之后加入,提供了一种更加灵活的方式加载文件。

具体实例

第一种没什么说的。主要还是看第二种和第三种。

假设在一个项目里面有两个文件

Demo.php

class Demo
{
# coding
}

index.php

function __autoload($class_name)
{
$file = dirname(__FILE__) . '/' . $class_name;
if (file_exist($file)) {

include($file);

}

}

$obj = new Demo();

Demo.phpindex.php只要在一个同级目录内,php变会很智能的加载Demo.php,不需要显示的操作。

但是这里还是存在弊端的,比如一个项目中只能有一个__autoload(),这也意味着自动加载的价值变得很低,于是PHP便在PHP5.1.12版本之后添加了spl_autoload_register(),它接受一个回调函数,使得自动加载更加的灵活。

修改index.php

function my_autoload($class_name)

{

$file = dirname(__FILE__) . '/' . $class_name;

if (file_exist($file)) {

include($file);

}

}

spl_autoload_register('my_autoload');

$obj = new Demo();

之前的Demo.php不做修改,将index.php如此修改,便可以同样的功能。

关于spl_autoload_register()更多的内容可以查看官方文档。

http://php.net/manual/zh/function.spl-autoload-register.php

 TIPS
注意类名和文件名必须保持一致!!!

2. Composer

在5.3之后,Composer大行其道,号称PHP未来的希望。。。

使用Composer自动加载时只要引入一个自动加载文件就可以了。

include_once('vendor/autoload.php');

那么Composer的自动加载时怎么实现的呢,其实也是依靠spl_autoload_register()

首先Composer存储三对数组

class=>dir
namespace=>array(dir, dir, dir)
PSR4=>array(dir, dir1, dir2...)

然后在autoload.php, 存在一个loader,可以触发spl_autoload_register,
一旦触发,Composer会对触发的类型进行分析,选择合适的数组,将真实的地址提取出来,然后include,原理还是很简单,推荐大家自行查看一下Composer的自动加载的代码。

关于composer的一个Tips

在上线代码时可以使用composer dump-autoload -o 转换PSR-0/4 autoloadingclassmap 获得更快的载入速度。这特别适用于生产环境,但可能需要一些时间来运行,因此它目前不是默认设置。至于为什么,看完源代码就清晰了。

3. 简单实现一个Composer自动加载

简单实现ClassMap的自动加载功能

https://github.com/bayuexiong/simple-composer/tree/master/vendor

使用代码和Composer一样。

include 'vendor/autoload.php';

$obj = new Demo('gg');

$obj->sayName();

$obj2 = new Other('aa');

$obj2->sayName();

4. 如何选择自动加载机制

  1. 在程序一开始运行的时候,使用数组,将项目内所有的文件记录下来,实现自动加载(如果使用cache,应该还hold的住),symfony使用这种形式,代码如下。
    https://github.com/symfony/class-loader/blob/master/ClassMapGenerator.php
  2. class名和路径对应,便于查找,但是这样缺乏灵活性,框架的侵入性太强了,代码很受框架的限制,像ThinkPHP,CI就是使用这种形式。
  3. 组合使用,像Laravel就是使用PSR4和symfony的classLoader。

5. CI框架的自动加载

现在公司使用CI框架的情况比较多,所以对CI框架的自动加载做一些详细的介绍。

对于一个普通的CI加载类的方式:

 $this->load->library('myclass');

CI框架的内部是如何运行的呢?首先上个流程图

QQ截图20160314174227

具体的实现可以查看源代码,都在system/core/Loader.php文件下面。

其实CI框架的自动加载并没有借助spl系列的函数,而是直接查找文件的方式来自动加载,这可能与CI框架诞生的年岁有关,在那个时期不失为一种优秀的自动加载方法。

但是现在来说,算不上优秀,其对命名的规范太过苛刻了,效率也谈不上高效,当然CI框架的整体速度还是很快的,毕竟像symfony之流的框架为了实现完全解耦,付出了很多性能上的代价。

Tips

对于一个普通的加载类
$this->load->library($library, $param, $object_name);
1. $library 可以是一个数组key代表需要加载的类,value则是obejct_name。
2. $param 需要一个数组,作于传入构造器中的值
3. $object_name$this->load->model(calss, object_name)中第二个参数一样,加载完之后可以$this->object_name->sayHello()

具体的可以结合CI的文档再加上阅读CI的源代码,的确CI的文档相比其他的框架比较全面,但是一些技巧也没有详尽的介绍。

6. 小结

使用Composer吧!使用RSP4命名空间规范吧!这样各个组件与组件之间,自己的代码和别人的代码都可以无痛的结合,不需要花费额外的精力去处理文件加载的问题。

7. 补充

  1. 命名空间,命名空间提供了一种灵活的效率更高的辅助自动加载的方法。
  2. PSR4 规范命名空间的定义,是最近比较流行的命名空间规范。

材料参考:

  1. https://github.com/qinjx/adv_php_book/blob/master/class_autoload.md
  2. spl_autoload_register
  3. __atuoload

VIM PHP IDE的安装步骤

前言

操作文档的链接

文件包所在

\\192.168.0.18\运维网络硬盘\y袁亮\vim-php-ide
  • php-vim-fool.tgz是fool式安装
  • php-vim-full.tgz是full式安装

其实就是相差一个YCM插件,YCM插件需要clang编译,所以比较烦。

FOOL安装

最好要求php5.3.9以上版本,也最好安装php-xml

yum install php-xml

关于自动补全

  • 最好,也至少安装一下ctags不然很多东西用不起了。
  • yum install ctags
  • 如果没有权限安装,那也只能作罢。

fool版的代价是不太友好的自动补全,当然也没有路径补全了=_=

安装步骤:

  • 使用winscpphp-vim-fool.tgz上传到工作用户目录下。
  • 执行指令tar xzvf php-vim-fool.tgz -C ~/
  • 然后就ok了

关于配置文件

  • 位置在~/.vimrc
  • 打开vim ~/.vimrc,先使用zM折叠所有方便查找,za单独打开和关闭折叠。

full安装(其实就是自动补全的差距)

需要安装的外部依赖:

  • git是必须的yum install git
  • gcc gcc-c++ yum install gcc gcc-c++
  • clang 
    • 先添加epel源, yum install epel-release
    • yum install clang
  • python-devel yum install python-devel
  • cmake yum install cmake
  • ctags yum install ctags
  • 可能需要php5.3.9以上的版本,不然需要关闭phpmd检查

安装vim-php

  • 使用winscpphp-vim-full.tgz上传到工作用户的目录下,即~/下面,github太慢,还是直接压缩包来得好。
  • tar xzvf php-vim-full.tgz -C ~/
  • vim ~/.vimrc 查看有没有报错(一般没有),然后:PluginUpdate,时间可能有点久,这不是必要的,可以直接下一步。
  • 进入~/.vim/bundle/YouCompleteMe/, 执行./install.py编译一下,可能比较久。 
    • 提示缺少argparse 安装pip install argparse
    • 如果没有pip,安装yum install python-pip
  • 如果编译失败,请查看依赖有没有安装成功
  • 安装成功后可以在vim下键入:PluginUpdate vim-shippets更新模块。

VIM PHP IDE的基本操作

前言

 安装步骤的链接

关于安装步骤:

  • 分full和fool两个版本,版本差距在自动补全的插件。
  • 最好安装ctags,如果不安装ctags自动补全将不完善,tagbar也无法工作。
  • 可以考虑一下vim的练级攻略

语法检查

文件在保存时会检查语法错误和规范

一共有三种警告:

  • p> php的语法错误, 可以使用:Php主动检查
  • s> 不符合prs2规范, 可以使用:Phpcs主动检查
  • m> 质量检验, 可以使用:Phpmd主动检查

格式修复

vim-php-cs-fixer

nnoremap <silent><F7> :call PhpCsFixerFixDirectory()<CR>
nnoremap <silent><F8> :call PhpCsFixerFixFile()<CR>

F8可以修复一些不符合psr2的规范,但是存在一些问题,如果只是定义了函数名或是类名的一些没有实际作用的代码可能会被删除,安全性有待评估。

自动补全

YCM

full基本操作:

  • 两个字符后开始自动补全
  • tab键选择,shift-tab逆向选择
  • 可以使用ctrl-n向下,或是ctrl-p向上选择

如果是fool版:

  • 不能自动开启补全,不能像图中那样方便。
  • 必须使用<ctrl-x><ctrl-o>开启补全
  • ctrl-nctrl-p无法选择, tab可以使用
  • 其他相同

一般只支持系统函数补全,如果要支持自己编写的函数补全,需要如此:

  1. 在项目顶层目录下执行指令 ctags -R
  2. 必需在项目顶层目录,即ctags文件所在的目录打开vim
  3. 打开文件,不要退出vim,使用NERDTreectrl-p查找和打开文件,如果需要创建文件,可以使用ctrl-p打开文件。
  4. 如果创建了新的类,将必须在项目顶层目录执行ctags -R的指令,当然可以在vim执行:!ctags -R,在不退出vim的情况下更新ctags文件

可以通过tags来实现require的补全

对于composer的补全,默认composer是全局安装的,好像失败了。

代码块

u

已经将php的模板文件软连接到用户主目录下,可以自行查看修改 
vim ~/php.shippets

?-tab 可以生成这样的代码 <?php ?>

f-tab可以生成这样的代码

function ()
{

}

pub-tab可以生成

/*
 * undocumented function
 * @return void
 * /
public function name($param)
{
    return null;
}

c-tab

class filename
{

}

class-tab可以生成一个带注释的class

文件目录和代码浏览

NERDTree 
NERDTree

F2 打开文件目录 
在NERDTree中按?呼出帮助文档

tagbar

需要安装ctags 
tagbar
F3 打开代码浏览

模糊搜索

ctrl-p 
ctrl-p
基本不需要设置

ctrl-p 打开模糊搜索

ctrl-k  ctrl-j 可以在搜索结果中上下选择 
ctrl-t 在新标签页打开 
ctrl-v 分割打开 
ctrl-y 新建文件, 需要先敲入路径和文件名

html tag跳转

在一个html tag上使用%可以跳转与之匹配的tag

官方文档

将光标移动到需要查看的函数上,使用shift-k,就可以查看官方文档a。

符号补全

在使用', ", (, [, {时,会自动补全另一半,同时如果再按各个匹配的另一半,则会跳出。

 

全局搜索

可以使用命令

:CtrlSF param

也可以设置

nmap <leader><leader>f <Plug>CtrlSFPrompt

<leader>默认是\,所以快捷就是 \\f

因为是全局搜索,所以不要在太顶层目录使用,具体请查看CtrlSF

多光标

ctrl-n 开启选择/选择下一个 
下面操作需要在ctrl-n执行后 
ctrl-p 取消一个选择 
ctrl-x 跳过一个选择 
详细vim-multiple-cursor

PS: 可以通过结合全局搜索实现重构

注释

\cc 注释当前行 
\cu 反注释当前行 
可以通过shift-v实现多行操作

撤销树

此处输入图片的描述 
gundo

F4呼出撤销树,查看之前的撤销修改

其它一些插件

php.vim

更好的代码高亮

PHP-Indenting-for-vim

在php 和 html代码混杂在一起时提供更好的缩进

vim-airline

状态栏美化

vim-trailing-whitespace

显示多余的空格