Ironbin


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

安装 Composer

发表于 2016-03-05 | 分类于 php | | 阅读次数:

Composer 是一个 PHP 依赖管理程序。可以按照下面的步骤以全局方式安装到 Linux 系统。

  • 第一步:下载 composer.phar
1
2
3
cd /tmp  

curl -sS https://getcomposer.org/installer | php
  • 第二步:移动到全局目录
1
mv composer.phar /usr/local/bin/composer

现在能够以全局方式在命令行中执行 composer

javascript 编码常规

发表于 2015-07-03 | 分类于 javascript | | 阅读次数:

标题写成常规,非规范,是由于只要没有语法错误,如何写代码本身就是编码者的一个喜好而已,但是好的习惯有助于提高可读性,减少错误,尤其提高团队合作的效率。

下面内容搜集了业内顶级开发者的习惯,来源见底部附录。

JavaScript 文件

所有 javascript 文件根据依赖关系,按序放置在 <body> 结束标签前。
原因:

  • 不会因为 javascript 文件的加载和解析延缓页面显示
  • 防止标签在加载完成前被 js 代码调用。

缩进 Indentation

  • 使用空格代替 tab
  • 缩进单位是2个空格

代码行

  • 每行不超过80字符
  • 换行缩进8个空格

注释 Comment

  • 尽量多地注释代码的思路、注意点等
  • 修改代码时同步更新注释

命名

  • 使用26大写和小写字母(A .. Z, a .. z),10个数字(0 .. 9),下划线(_)。不要使用 $ (dollar sign) 或 \ (backslash)
  • 首尾不使用下划线
  • 变量或方法遵守驼峰(camelCase)规则
  • 构造函数遵守大写驼峰规则
  • 全局变量遵守全大写规则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var MESSAGE_TYPE_BROADCAST = 0,    // 全局变量
MESSAGE_TYPE_PERSON = 1,
MESSAGE_TYPE_GROUP = 2;

function sendMessage(messageType, message){ // 方法名

var httpStatus,
sendResult; // 变量

// detect message target by message type
...

httpStatus = httpRequest(message);

// handle result
...

return sendResult;
}

变量 Variable

  • 所有变量在使用前声明,var 应该是 Function 第一行语句
  • 变量及其注释单独一行
  • 变量名遵守驼峰(camelCase)规则

    1
    2
    3
    var currentEntry, // currently selected table entry
    level, // indentation level
    size; // size of table

方法 Function

  • 方法名遵守驼峰(camelCase)规则
  • 立即执行的方法使用小括号封装

    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
    var collection = (function () {
    var keys = [], values = [];

    return {
    get: function (key) {
    var at = keys.indexOf(key);
    if (at >= 0) {
    return values[at];
    }
    },
    set: function (key, value) {
    var at = keys.indexOf(key);
    if (at < 0) {
    at = keys.length;
    }
    keys[at] = key;
    values[at] = value;
    },
    remove: function (key) {
    var at = keys.indexOf(key);
    if (at >= 0) {
    keys.splice(at, 1);
    values.splice(at, 1);
    }
    }
    };
    }());

格式示例

if 语句(Statement)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (condition) {
statements
}

if (condition) {
statements
} else {
statements
}

if (condition) {
statements
} else if (condition) {
statements
} else {
statements
}

for 语句

1
2
3
4
5
6
7
8
9
for (initialization; condition; update) {
statements
}

for (variable in object) {
if (filter) {
statements
}
}

while 语句

1
2
3
while (condition) {
statements
}

do 语句

1
2
3
do {
statements
} while (condition);

Unlike the other compound statements, the do statement always ends with a ; (semicolon).

switch 语句

1
2
3
4
5
6
7

switch (expression) {
case expression:
statements
default:
statements
}

每一组必须有结束代码:break, return, or throw

try 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14

try {
statements
} catch (variable) {
statements
}

try {
statements
} catch (variable) {
statements
} finally {
statements
}

continue 语句

不要使用

with 语句

不要使用

eval 语句

不要使用

参考:

Javascript编程风格
Code Conventions for the JavaScript Programming Language
Google JavaScript Style Guide

url 编码常规

发表于 2015-07-03 | 分类于 php | | 阅读次数:

MVC 框架支持的模式(Pattern):

  • GET 模式: fumujidi.com/index.php?controller=life&action=books
  • Path Info 模式: fumujidi.com/index.php/life/books.html
  • SEO 模式: fumujidi.com/life/books.html
    NODIR 模式: fumujidi.com/life-books.html

我们使用:

  • SEO 模式
  • 使用连字符规则,不使用大写
  • 命名首选 RESTful 方式
  • 每个尽量不要超过2个单词,多个单词使用 hyphens(dash) 格式

php 编码常规

发表于 2015-07-03 | 分类于 php | | 阅读次数:

MVC 框架命名规范

控制器(controller)

  • 类名遵守大写CamelCase,继承RootController
1
class UserController extends RootController   // 类后缀为 Controller
  • Action名、变量名、方法名采用小写camelCase:
1
public function loginAction () {...}    // Action 后缀为 Action
  • Action 名与 url 的映射关系:
1
high-school -> highSchoolAction

模型(model)

  • 类名遵守大写CamelCase,继承RootModel
1
class UserModel entends RootModel    //类后缀为 Model
  • 类方法和变量遵守小写camelCase
1
public function calculateScore () {...}

视图(view)

  • 视图模板(tpl)文件路径
1
views/<Controller>/<action>.tpl.php
  • 目录名对应 Controller,首字母大写
  • 文件名对应 action,首字母小写

bower usage

发表于 2015-06-11 | 分类于 javascript | | 阅读次数:

1. 安装 nodejs

1
$ brew install nodejs

NPM是node程序包管理器。它是捆绑在nodejs的安装程序上的,所以一旦你已经安装了node,NPM也就安装好了。

2. 安装 bower

1
$ npm install -g bower

3. 使用 bower 安装其它库

1
$ bower install jquery

NPM是node程序包管理器。它是捆绑在nodejs的安装程序上的,所以一旦你已经安装了node,NPM也就安装好了。

osx配置xdebug

发表于 2015-06-04 | 分类于 php | | 阅读次数:

一、xdebug 工作原理

引用 xdebug 的文档:Communication Set-up

当远程调试时,xdebug 充当着客户端的角色,而 IDE 像是服务器,它会侦听调试端口,就是默认的9000,等待 xdebug 建立远程调试的连接。如下图所求:

  • The IP of the server is 10.0.1.2 with HTTP on port 80
  • The IDE is on IP 10.0.1.42, so xdebug.remote_host is set to 10.0.1.42
  • The IDE listens on port 9000, so xdebug.remote_port is set to 9000
  • The HTTP request is started on the machine running the IDE
  • Xdebug connects to 10.0.1.42:9000
  • Debugging runs, HTTP Response provided

当使用匿名IP时,是通过配置 xdebug.remote_connect_back,工作流程像下图所求:

  • The IP of the server is 10.0.1.2 with HTTP on port 80
  • The IDE is on an unknown IP, so xdebug.remote_connect_back is set to 1
  • The IDE listens on port 9000, so xdebug.remote_port is set to 9000
  • The HTTP request is made, Xdebug detects the IP addres from the HTTP headers
  • Xdebug connects to the detected IP (10.0.1.42) on port 9000
  • Debugging runs, HTTP Response provided

当有了侦听端口的机制,那他们是如何配合起来工作的呢?

HTTP Debug Sessions

Xdebug 是依靠 cookies 来跟踪来自浏览器的请求. 工作流程是这样:

  1. 使用GET或POST的请求参数:XDEBUG_SESSION_START=name, 当有请求参数时会忽略 XDEBUG_SESSION cookies 的值。
  2. 设置请求的cookies值 XDEBUG_SESSION

当xdebug检测到 XDEBUG_SESSION_START 或 XDEBUG_SESSION时,会尝试连接调用的客户端

当xdebug检测到 XDEBUG_SESSION_STOP 时,会终止调试。

二、配置 xdebug

首先安装 xdebug 模块

1
sudo pecl install xdebug

配置 php.ini:

1
2
3
4
5
6
7
[xdebug]
zend_extension=/usr/local/Cellar/php56/5.6.8/lib/php/extensions/no-debug-non-zts-20131226/xdebug.so
xdebug.remote_enable=1
xdebug.remote_autostart=1
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9001
xdebug.idekey = "PHPSTORM"

更多配置参数请查看:XDebug 参数列表

如何知道配置成功了?

通过 phpinfo(),如何看到启动的模块中包含 xdebug 信息,且配置如上面所示,则表示成功了。

四、配置IDE

这里使用 phpstrom。

  1. 配置 phpstorm 的侦听端口:

  2. 启动侦听端口

  3. (可选)安装浏览器插件,设置idekey
    如果你使用不同的IDE调试,每个IDE的key是不一样的,你可以通过安装浏览器插件,让它配置key并插入cookies,比如chrome插件xdebug helper

如何知道IDE配置成功了?

通过 terminal,执行 sudo lsof -n -i4TCP:9001 | grep LISTEN,如果看到IDE在侦听该端口,则表示成功了。

五、开始调试

设置断点,然后浏览器打开要调试的url。

osx安装php扩展

发表于 2015-06-03 | 分类于 chromium | | 阅读次数:

一、安装xcdoe命令行

1
xcode-select --install

二、通过PECL来安装PHP扩展

在 /usr/lib/php 目录下有个 install-pear-nozlib.phar 文件(怎么来的?),通过它首先安装 PECL 管理器

1
sudo php install-pear-nozlib.phar

三、获取所需的扩展

比如,我们安装 xdebug

1
sudo pecl install xdebug

四、更新 php 配置文件

打开 php.ini,配置新获取的扩展(略)

osx 常用命令

发表于 2015-06-02 | 分类于 osx | | 阅读次数:

一、网络

查看谁在侦听端口

1
sudo lsof -n -i4TCP:$PORT | grep LISTEN

lsof is a command meaning “list open files”, which is used in many Unix-like systems to report a list of all open files and the processes that opened them.

修改 Host

1
sudo vi /etc/hosts

注意 ::1 的写法:

如果地址中出现连续的0,则可以用“::”号来压缩(称为零压缩),进一步简化IP v6地址表示。例如,地址FE80:0:0:0:2AA:FF:FE9A:4CA2 可以压缩成FE80::2AA:FF:FE9A:4CA2;FF02:0:0:0:0:0:0:2 可以压缩成 FF02::2。零压缩只能用于压缩冒号十六进制地址中一个连续的16位块,不能压缩部分16位信息块,例如,不能将FF02:30:0:0:0:0:0:5 表示成 FF02:3::5。用 :: 表示0位的数量用(8-n)×16公式来计算,其中n为地址中的16位块的数量。例如,在地址FF02::2中,被压缩了96=(8-2)×16个0。零压缩只能在给定地址中使用一次,否则,就无法确定每个双冒号 (::)实例所表示的 0位数量。

特殊地址。IP v6中有两个特殊地址:

  • 未指定地址(0:0:0:0:0:0:0:0 或::):仅用于指出某个地址不存在,它等价于 IP v4 未指定地址0.0.0.0。未指定地址通常作为源地址来验证暂定地址的惟一性,但不会用作目的地址。
  • 环回地址(0:0:0:0:0:0:0:1或::1):用来标识环回接口,允许节点自发自收,它等价于IP v4环回地址 127.0.0.1。

统计代码行数

  • 列出每个文件的行数
1
find . -name "*.m" -or -name "*.h" -or -name "*.xib" -or -name "*.c" |xargs wc -l
  • 列出代码行数总和
1
find . -name "*.m" -or -name "*.h" -or -name "*.xib" -or -name "*.c" |xargs grep -v "^$"|wc -l

查看正在运行的进程

  • 通过进程名查看
1
ps aux|grep "Application Name"
  • 按 CPU 排序
1
top -o cpu
  • 按内存使用排序
1
top -o rsize

创建 Chromium Extension Event

发表于 2015-05-23 | 分类于 chromium | | 阅读次数:

一、创建事件名

  • 打开 chrome/browser/extensions/event_names.h

添加

1
2
3
4
5
namespace event_names {
...

+ extern const char kOnLoginByCertComplete[];
}
  • 打开 chrome/browser/extensions/event_names.cc

添加

1
2
3
4
5
6
namespace event_names {
...

+ const char kOnLoginByCertComplete[] = "wintrust.onLoginByCertComplete";

}

二、添加事件的描述

  • 打开 chrome\common\extensions\api\wintrust.json

添加

1
2
3
4
5
6
7
8
9
10
11
12
[{
"namespace": "wintrust",
...

+ "events": [{
+ "name": "onLoginByCertComplete",
+ "description": "Fired when login vpn by cert.",
+ "type": "function",
+ "parameters": [{"name": "success", "type":"boolean"}]
+ }]

}]

三、添加触发扩展事件的事件

  • 打开 content\public\browser\notification_types.h

添加

1
2
3
4
5
6
7
enum NotificationType {
...

+// 证书登录的结果
+NOTIFICATION_LOGIN_BY_CERT_COMPLETE,

}

四、绑定第三步事件的回调

  • 打开 chrome/browser/extensions/browser_event_router.cc

添加绑定

1
2
3
4
5
6
7
8
BrowserEventRouter::BrowserEventRouter(Profile* profile)
: profile_(profile) {
...

registrar_.Add(this,
content::NOTIFICATION_LOGIN_BY_CERT_COMPLETE,
content::Source<Profile>(profile_));
}

实现回调

1
2
3
4
5
6
7
8
9
10
11
12
13
void BrowserEventRouter::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
...
} else if (type == content::NOTIFICATION_LOGIN_BY_CERT_COMPLETE) {
scoped_ptr<ListValue> args(new ListValue());
bool value = *(content::Details<const std::string>(details).ptr()) == "true";
args->Append(Value::CreateBooleanValue(value));
DispatchEvent(profile_, events::kOnLoginByCertComplete, args.Pass(), EventRouter::USER_GESTURE_UNKNOWN);
} else {
NOTREACHED();
}
}

五、实现触发消息

在某个合适和需要的位置以下列的代码触发 NOTIFICATION_LOGIN_BY_CERT_COMPLETE 事件

1
2
3
4
5
+  std::string detail("false");
+ content::NotificationService::current()->Notify(
+ content::NOTIFICATION_LOGIN_BY_CERT_COMPLETE,
+ content::Source<Profile>(browser_->profile()),
+ content::Details<const std::string>(&detail));

六、测试新事件

  1. 在扩展的 manifest 里首先声明对 wintrust 命名空间的权限

    1
    2
    3
    4
       "permissions": [
    "*://*/*",
    "wintrust"
    ]
  1. 绑定事件回调函数

    1
    2
    3
    chrome.wintrust.onLoginByCertComplete.addListener(function(success){
    console.log('Login result is: ', success);
    })
  1. 触发第五步定义的条件,使事件发生。

创建 Chromium Extension API

发表于 2015-05-22 | 分类于 chromium | | 阅读次数:

一、添加新接口描述文件

  1. 新建描述文件

    创建 chrome\common\extensions\api\wintrust.json

    添加接口描述代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    [
    {
    // 获取浏览器模块目录
    {
    "name": "versionDirectory",
    "type": "function",
    "parameters": [{
    "type": "function",
    "name": "callback",
    "parameters": [{
    "type": "string",
    "name": "path"
    }]
    }]
    }
    ]
    }
    ]
  2. 添加新文件到 GYP

    打开 src\chrome\common\extensions\api\api.gyp, 添加:

    1
    2
    3
    4
    5
    6
    ...
    'schema_files': [
    ...
    + # 新接口
    + 'wintrust.json',
    ],
  3. 添加新文件到 grd

    打开 src\chrome\common\extensions_api_resources.grd,添加

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?xml version="1.0" encoding="UTF-8"?>
    <grit latest_public_release="0" current_release="1">
    <outputs>
    <output filename="grit/extensions_api_resources.h" type="rc_header">
    <emit emit_type='prepend'></emit>
    </output>
    <output filename="extensions_api_resources.pak" type="data_package" />
    <output filename="extensions_api_resources.rc" type="rc_all" />
    </outputs>
    <release seq="1">
    <includes>
    ...
    <include name="IDR_EXTENSION_API_JSON_WINTRUST" file="extensions\api\wintrust.json" type="BINDATA" />
    </includes>
    </release>
    </grit>

二、添加新接口头文件和实现

  1. 新建头文件和实现文件

    创建 src\chrome\browser\extensions\api\wintrust\wintrust_api.h 和 src\chrome\browser\extensions\api\wintrust\wintrust_api.cc

  2. 添加新文件到 GYP

    打开 src\chrome\chrome_browser_extensions.gypi, 添加:

    1
    2
    3
    4
    5
    6
    7
    'sources': [
    ...

    + # win-trust 添加的插件接口
    + 'browser/extensions/api/wintrust/wintrust_api.h',
    + 'browser/extensions/api/wintrust/wintrust_api.cc',
    ]
  3. 实现 wintrust_api.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#pragma once
#include "chrome/browser/extensions/extension_function.h"

namespace extensions {
class WintrustVersionDirectoryFunction : public SyncExtensionFunction {
public:
WintrustVersionDirectoryFunction();
virtual bool RunImpl() OVERRIDE;
protected:
virtual ~WintrustVersionDirectoryFunction(){};
private:
DECLARE_EXTENSION_FUNCTION("wintrust.versionDirectory", WINTRUST_VERSIONDIRECTORY);
};
}
  1. 实现 wintrust_api.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "chrome/browser/extensions/api/wintrust/wintrust_api.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "chrome/browser/profiles/profile.h"

namespace extensions{

WintrustVersionDirectoryFunction::WintrustVersionDirectoryFunction(){}

bool WintrustVersionDirectoryFunction::RunImpl() {
base::FilePath path;
PathService::Get(base::DIR_MODULE, &path);

scoped_ptr<base::StringValue> value (base::Value::CreateStringValue(path.value().c_str()));

SetResult(value.release());

return true;
}
}

三、重新生成项目(sln)

执行 python build\gyp_chromium

四、为新接口定义C++常量

  • 打开 src\chrome\browser\extensions\extension_function_histogram_value.h

添加下面代码, 转换示例: Example: "tabs.create" -> TABS_CREATE

1
2
3
4
5
6
7
8
9
enum HistogramValue {
UNKNOWN = 0,
...

+ // 赢达信客户端添加的接口
+ WINTRUST_VERSIONDIRECTORY,

ENUM_BOUNDARY // Last entry: Add new entries above.
};

五、注册新接口类(class)

  • 打开 src\chrome\browser\extensions\extension_function_registry.cc

添加下面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 赢达信客户端接口
#include "chrome/browser/extensions/api/wintrust/wintrust_api.h"

void ExtensionFunctionRegistry::ResetFunctions() {
#if defined(ENABLE_EXTENSIONS)

// Register all functions here.

...

// 赢达信客户端定义的接口
RegisterFunction<extensions::WintrustVersionDirectoryFunction>();


// Generated APIs
extensions::api::GeneratedFunctionRegistry::RegisterAll(this);

#endif // defined(ENABLE_EXTENSIONS)
}

六、定义新接口的访问权限

  1. 定义该接口可用于的扩展程序类型:

    打开 src\chrome\common\extensions\api\_permission_features.json

    添加下面代码, extension_types 定义了哪些类型的扩展可以使用新接口。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Copyright (c) 2012 The Chromium Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.

    {
    ...
    + // 赢达信的接口
    + "wintrust": {
    + "channel": "stable",
    + "extension_types": ["extension", "packaged_app","platform_app","hosted_app"]
    + }
    }
  2. 定义权限的键名,该常量也显示到 manifest permission 中

    打开 src\chrome\common\extensions\permissions\api_permission.h,添加

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    enum ID {
    // Error codes.
    kInvalid = -2,
    kUnknown = -1,

    // Real permissions.
    ...
    + kWintrust,
    kEnumBoundary
    };
  3. 实现该键名

    打开 src\chrome\common\extensions\permissions\chrome_api_permissions.cc,添加

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    std::vector<APIPermissionInfo*> ChromeAPIPermissions::GetAllPermissions()
    const {
    struct PermissionRegistration {
    APIPermission::ID id;
    const char* name;
    int flags;
    int l10n_message_id;
    PermissionMessage::ID message_id;
    APIPermissionInfo::APIPermissionConstructor constructor;
    } PermissionsToRegister[] = {

    // Register extension permissions.
    ...
    { APIPermission::kWintrust, "wintrust" },

    ...

七、测试新接口

  1. 创建扩展 manifest 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    {
    "name": "WinTrust API",
    "manifest_version": 2,
    "version": "1.1",
    "description": "Test new extenslion api",

    "browser_action": {
    "default_icon": {
    "19": "img/icon19.png",
    "38": "img/icon38.png"
    },
    "default_title": "VPN",
    "default_popup": "popup.html"
    },

    "background": {
    "page": "background.html"
    },

    "permissions": [
    "*://*/*",
    "wintrust"
    ]
    }
  2. 创建扩展 manifest 文件

    1
    2
    3
    chrome.wintrust.versionDirectory(function(path){
    console.log('Test reust:', path);
    })
1…9101112
程学彬

程学彬

117 日志
48 分类
99 标签
Creative Commons
Links
  • ShinySky
0%
© 2014 — 2020 程学彬