global vs $_GLOBALS
1.global
在函数体内定义的global变量,函数体外可以使用,在函数体外定义的global变量不能在函数体内使用,
function f()
{
global $a;
}
$a = 456;
f();
echo $a; //456
global $a;
function f()
{
$a = 456;
}
f();
echo $a; //empty
exit;
2.global vs $_GLOBALS
global 改变外部会改变内部 改变内部不会改变外部
$_GLOBALS 外部就是内部,所以改变外部就是改变内部,改变内部也改变外部
php语法中,很多人都认为global和$GLOBALS[]只是写法上面的差别,其实不然
根据官方的解释是
1.$GLOBALS[‘var’]是外部的全局变量本身
2.global $var是外部$var的同名引用或者指针。
举例说明一下:
<?php
$var1 = 1;
$var2 = 2;
function test(){
$GLOBALS[‘var2′] = &$GLOBALS[‘var1′];
}
test();
echo $var2;
?>
正常打印结果为1
<?php
$var1 = 1;
$var2 = 2;
function test(){
global $var1,$var2;
$var2 = &$var1;
}
test();
echo $var2;
?>
意外打印结果为2
为什么会打印结果为2呢?其实就是因为$var1的引用指向了$var2的引用地址。导致实质的值没有改变。
我们再来看一个例子吧。
<?php
$var1 = 1;
function test(){
unset($GLOBALS[‘var1′]);
}
test();
echo $var1;
?>
因为$var1被删除了,所以什么东西都没有打印
<?php
$var1 = 1;
function test(){
global $var1;
unset($var1);
}
test();
echo $var1;
?>
意外的打印了1。证明删除的只是别名|引用,起本身的值没有受到任何的改变
明白了吧?
也就是说global $var其实就是$var = &$GLOBALS[‘var’]。调用外部变量的一个别名而已
1.global
在函数体内定义的global变量,函数体外可以使用,在函数体外定义的global变量不能在函数体内使用,
function f()
{
global $a;
}
$a = 456;
f();
echo $a; //456
global $a;
function f()
{
$a = 456;
}
f();
echo $a; //empty
exit;
2.global vs $_GLOBALS
global 改变外部会改变内部 改变内部不会改变外部
$_GLOBALS 外部就是内部,所以改变外部就是改变内部,改变内部也改变外部
php语法中,很多人都认为global和$GLOBALS[]只是写法上面的差别,其实不然
根据官方的解释是
1.$GLOBALS[‘var’]是外部的全局变量本身
2.global $var是外部$var的同名引用或者指针。
举例说明一下:
<?php
$var1 = 1;
$var2 = 2;
function test(){
$GLOBALS[‘var2′] = &$GLOBALS[‘var1′];
}
test();
echo $var2;
?>
正常打印结果为1
<?php
$var1 = 1;
$var2 = 2;
function test(){
global $var1,$var2;
$var2 = &$var1;
}
test();
echo $var2;
?>
意外打印结果为2
为什么会打印结果为2呢?其实就是因为$var1的引用指向了$var2的引用地址。导致实质的值没有改变。
我们再来看一个例子吧。
<?php
$var1 = 1;
function test(){
unset($GLOBALS[‘var1′]);
}
test();
echo $var1;
?>
因为$var1被删除了,所以什么东西都没有打印
<?php
$var1 = 1;
function test(){
global $var1;
unset($var1);
}
test();
echo $var1;
?>
意外的打印了1。证明删除的只是别名|引用,起本身的值没有受到任何的改变
明白了吧?
1.NULL 表示变量没有值
$a=null;
$b='value';
unset($b);
var_dump($a);直接赋值null
var_dump($b);$b被销毁了,null
var_dump($c);没有$c,null
2.数据类型转换:
bool(true 1 |false 0) and null(0) ==>int float(int 转成 float后运算)
string==>int float 字符串先转为数字后运算
3.预定义常量:
1)__FUNCTION__: 函数名称(PHP 4.3.0 新加).自 PHP 5 起本常量返回该函数被定义时的名字(区分大小写).在 PHP 4 中该值总是小写字母的.
2)__FILE__: 文件的完整路径和文件名.如果用在包含文件中,则返回包含文件名.自 PHP 4.0.2 起,__FILE__ 总是包含一个绝对路径,而在此之前的版本有时会包含一个相对路径.
3)__LINE__: 文件中的当前行号
4)__CLASS__: 类的名称(PHP 4.3.0 新加).自 PHP 5 起本常量返回该类被定义时的名字(区分大小写).在 PHP 4 中该值总是小写字母的.
5)__METHOD__: 类的方法名(PHP 5.0.0 新加).返回该方法被定义时的名字(区分大小写).
6)DIRECTORY_SEPARATOR: windows下的是\和/,而LINUX下的是/,以前觉得既然windows,LINUX 都支持/,那都用成 / 得了,这是没错的.可是从这个例子可以看出,当要对路径字符串进行处理的时候,就比较危险了,所以最好还是用DIRECTORY_SEPARATOR吧.
4.运算符:
算术 字符串 赋值 比较 逻辑 位 其他
php传值
1.静态 vs 引用
//静态 初值
class Child{
public $name;
//这里定义并初始化一个静态变量 $nums
public static $nums=0;
function __construct($name){
$this->name=$name;
}
public function join_game(){
//self::$nums 使用静态变量
self::$nums+=1;
echo $this->name."加入堆雪人游戏";
}
}
//创建三个小孩
$child1=new Child("李逵");
$child1->join_game();
$child2=new Child("张飞");
$child2->join_game();
$child3=new Child("唐僧");
$child3->join_game();
//看看有多少人玩游戏
echo "<br/> 有这".Child::$nums;
//引用 内外
function func1($a) {
$a = $a + 1;
}
function func2(&$a) {
$a = $a + 1;
}
$sample = 1;
func1($sample);
echo $sample; // 输出 1
$sample = 1;
func2($sample);
echo $sample; // 输出 2
2. $GLOBALS vs global
+$global 传参,$GLOBALS 赋值
$a = 1;
$b = 5;
function aa()
{
global $a,$b;
$b = &$a;
$b = 10;
}
aa();
echo $b; //5
?>
*
*
为什么$b 还是 5 ?
因为,如果在一个函数内部给一个声明为 global 的变量赋于一个引用,该引用只在函数内部可见。
可以通过使用 $GLOBALS 数组避免这一点:
*
*
<?php
$var1 = "Example variable";
$var2 = "";
function global_references($use_globals)
{
global $var1, $var2;
if (!$use_globals) {
$var2 =& $var1; // visible only inside the function
} else {
$GLOBALS["var2"] =& $var1; // visible also in global context
}
}
global_references(false);
echo "var2 is set to '$var2'/n"; // var2 is set to ''
global_references(true);
echo "var2 is set to '$var2'/n"; // var2 is set to 'Example variable'
?>
+变量传递,两者结果是相同的,只是global要求变量名也必须相同,而引用就不用了,因为它是同名指向的
<?php
function foo($a)
{
global $a;
$a++;
}
$a=5;
foo($a);
echo $a;
function fooUse(&$var)
{
$var++;
}
$a=5;
fooUse($a);
echo $a;
?>
+global 从外面拿到里面来用的案例,(提示:global在函数外声明global,是拿不进来的)
//不在外面声明global,在函数内声明global后直接拿来在函数内局部使用的,
include('./lib.php');//$sys = array('default'=>'value');
function useGlobal(){
global $sys; //不加global $sys ,函数里面无法打印出值
var_dump($sys);
}
useGlobal();
function f()
{
global $a;
$a=456;
}
f('456');
var_dump( $a); //null
function give(&$value){
$value =4;
}
give($me);
var_dump($me);//4
3.foreach
error_reporting(0);
$arr = array(1,2,3);
foreach($arr as &$value){
$value .= '4';
}
unset($value);
var_dump($arr);
php原理
结构体的结构,决定了引用产生的相关问题,写时拷贝和引用计数和引用传值
1.变量结构体
struct_zval_struct {
/* Variable information */
zvalue_value value; /*变量的值,是个联合体*/
zend_uint refcount__gc; /*指向次数*/
zend_uchar type; /* 变量类型*/
zend_uchar is_ref__gc; /*是否引用*/
};
type字段的值为以下常量
IS_NULL,IS_BOOL,IS_LONG,IS_DOUBLE
IS_STRING,IS_ARRAY,IS_OBJECT
IS_RESOURCE
联合体中的值
typedefunion _zvalue_value{
long lval; /* long value */
double dval; /* double value */
struct{
char *val;
intlen;
} str;
HashTable*ht; /* hash table value */
zend_object_valueobj;
}zvalue_value;
联合中为什么只列出了5种值?
NULL不用,zval的type为IS_NULL即可
Bool以1,0存储在lval上
resource的type为resource,其resource的内容用long来标志(资源标记)
$str = 'hello' 就是is_string 并赋值为hello,同时加入符号表(变量名->zval结构体地址)
2.常量结构体:常量是全局有效的,它的哈希表只有一个EG
typedefstruct _zend_constant {
zval value; //变量结构体
int flags; //标志,是否大小写敏感等
char *name; //常量名
uint name_len;
int module_number;//模块名
}zend_constant;
3.内存管理和垃圾回收
PHP封装了对系统内存请求,不要直接用malloc直接请求内存
各种符号表全是hash表,如全局 局部 常量和函数符号表等的
引用计数器:
$a= 1;
$b= $a;//这个时候$a和$b同享一个结构体,只是recount_gc由1变成2
$b=6//写时拷贝,这时重新复制了了一个结构体,引用也变成了1,
$b= &$a;//引用传值,就是recount_gc增加了1,同时is_ref_gc由0变成1
$b=6//这时$b变了,也影响了$a,因为is_ref_gc为1,就直接修改value,而不是复制了一份
$a = 1;
$b = &$a;
$c = $b;
$a = 9;
a和b引用计数,所以直接变成9,但是c写时拷贝了,就是1了
$a=9
$b=9
$c=1
$foo['love'] = 1;
$bar = &$foo['love'];
$tipi = $foo;//就认为它是引用了,此时is_ref_gc已为1,没有对$tipi['love']写时拷贝
$tipi['love'] = '2';
echo $foo['love'];
http://www.php-internals.com/book/?p=chapt06/06-06-copy-on-write
foreach怪问题:
问题1:
$arr = array(1,2,3);
foreach($arr as $k => &$v) {
$v = $v * 2;
}
// now $arr is array(2, 4, 6)
foreach($arr as $k => $v) {
echo "$k", " => ", "$v";
}
先从简单的开始,如果我们尝试运行上述代码,就会发现最后输出为0=>2 1=>4 2=>4 。
为何不是0=>2 1=>4 2=>6 ?
其实,我们可以认为 foreach($arr as $k => $v) 结构隐含了如下操作,分别将数组当前的'键'和当前的'值'赋给变量$k和$v。具体展开形如:
foreach($arr as $k => $v){
//在用户代码执行之前隐含了2个赋值操作
$v = currentVal();
$k = currentKey();
//继续运行用户代码
……
}
根据上述理论,现在我们重新来分析下第一个foreach:
第1遍循环,由于$v是一个引用,因此$v = &$arr[0],$v=$v*2相当于$arr[0]*2,因此$arr变成2,2,3
第2遍循环,$v = &$arr[1],$arr变成2,4,3
第3遍循环,$v = &$arr[2],$arr变成2,4,6
随后代码进入了第二个foreach:
第1遍循环,隐含操作$v=$arr[0]被触发,由于此时$v仍然是$arr[2]的引用,即相当于$arr[2]=$arr[0],$arr变成2,4,2
第2遍循环,$v=$arr[1],即$arr[2]=$arr[1],$arr变成2,4,4
第3遍循环,$v=$arr[2],即$arr[2]=$arr[2],$arr变成2,4,4
详细:http://www.jb51.net/article/39299.htm
数组:
说明:一般的,数组的curd和sort全是操作数组本身,指针也是。
补充一点,就是curd(array,value)而search是(value,array)
===================================================1.0===================================================
net work: gethostbyaddr gethostbyname
stream:stream_context_create
url:urlencode urldecode http_build_query parse_url
http:header
dir:dir opendir closedir
file:fopen(r w a +是读写方式打开 w和a都是写入,w是删除后写入,a是追加在末尾) stat pathinfo file_get/put_contents
math:ceil floor round mt_rand
hash:hash
session:id name path expire cookie | session_start/destroy/unset | session_set_save_handler
setcookie(name,value,expire,path,domain,https) ==>add del session | session_destroy
date:date(J 日 N星期 W周 L闰年) getdate checkdate strtotime
variable:empty isset is_numeric/scalar
array:
1、元素 shift pop push end reset count
2、集合 intersect diff
3、排序 array_multisort sort
4、搜索 array_search array_keys in_array
5、创建 array array_keys/values array_merge array_flip array_list array_combine array_chunk array_slice
6、kv each unique array_reverse
7、array_filter array_walk array_map
string:
1、转换 strtolower strtoupper ucfirst ucwords html_entities/specials strip/add_slashes trim
2、编码 ord md5 sha1
3、输出 echo printf
4、分割 explode implode str_splice/replace substr strlen strcmp
5、搜索 str i(大小写)r(最后一个) pos(第一个)/str(末尾)
6、preg preg_grep/match/replace/split
php:
排序冒泡 插入 快排 选择 |
变量与引用:只有变量才可以有地址,UNSET()删除时,只删除引用关系;如果重新给一个变量新的引用,引用关系发生改变;php中引用采用的是“写时拷贝”的原理,$a=$b=1 两个变量指向同一个内存地址,$a=$b=2 但重新赋值就会新申请内存
垃圾回收:refcount__gc 表示引用计数 1 is_ref__gc 表示是否为引用 0 value 存储变量的值 type 变量具体的类型 unset() 并不会直接销毁变量 只有当refcount=0时才会被PHP的垃圾回收机制回收