1、变量引用和传递引用:默认情况下,是传递引用。传递的都是变量的值,php会复制相应的值,并提供对该副本的访问和操作。对这个副本的任何修改都不会影响到原来变量中的值。要实现变量引用,需要特别对待,在变量的前面加上&符号,这样对这个值得操作就会直接作用到这个变量上面。
多数语言中,传递变量引用能够获得比传递变量值速度更快的好处。但这个快速,可能会比较小。
1.1 设定默认值:1)所有指定了默认值的参数必须出现在未指定默认值的参数后面,否则php无法判定省略了那个参数;
2)指定的值必须是常量,而不能是变量;
1.2 使用命名的参数:通过名字来为一个函数指定参数,而不是受限于调用函数时参数的位置。
1)让函数只接受一个参数,但该参数是一个关联数组;(在使用关联数组中的参数时,最好用isset()函数来检查参数是否存在并且设置了值。防止报错)
1.3 创建可接受可变参数的函数:1)使用数组;
2、创建可变数目的参数函数:(1)向函数传递一个数组,并把要传递的参数变量作为数组的元素; (2)使用function处理函数。
func_num_args():获取传递给函数的参数的个数。
func_get_args():获取参数列表,数组形式的。
func_get_arg():获取具体的参数值,参数为偏移量。
function mean2(){
$sum = 0;
$size = func_num_args();
for($i=0; $i<$size;$i++){
$sum += func_get_arg($i);
}
$average = $sum / $size;
return $average;
}
3、返回变量的引用:返回变量的引用是把&放在函数名的前面(与传递变量引用将&放在变量前不同)。同时,在调用这个函数时,必须使用=&赋值操作符来进行赋值,而不是单纯的=操作符。
function &get($needle, &$haystack){
foreach($haystack as $k=>$v){
if($needle == $v){
return $haystack[$k];
}
}
}
$m = array('bob', 'scott', 'prince', 'charles');
$prince =& get('prince', $m);
$prince = 'dsfa';
print_r($m); //Array ( [0] => bob [1] => scott [2] => dsfa [3] => charles )
注意这里是不能返回非变量的值,因为这不具有任何逻辑上的意义。=&就说明php返回变量的值,而非引用。
4、返回多个值:(1)返回一个数组,然后用list()来分离其中的元素(性能并不好);
5、跳跃选择返回的值:在list(0中忽略不关心的变量。
function time_parts($time){
return explode(':', $time);
}
list(,$minute,) = time_parts('12:34:45');
echo $minute; // 34
6、回调函数:
call_user_func():调用回调函数。第一个参数为需要调用的函数名称,后面的参数为传入的参数。
call_user_func_array():通过数组的方式传递参数给回调函数。
如果需要调用两个及以上的回调函数,就要使用一个包含这些函数名的关联数组。
class Foo {
static public function test() {
print "Hello world!\n";
}
}
call_user_func('Foo::test');
7、变量作用域:声明变量的位置决定了变量的作用域,变量的作用域决定了程序的那些部分可以访问该变量,那些部分不可以访问该变量,在PHP中,变量的作用域范围可以分为四类:局部变量、函数参数、全局变量和静态变量。
局部变量:在一个函数中声明一个变量是那个函数的局部变量,也就是说该变量只能被函数内部成员访问,函数外部成员是不能访问该变量,并且不可见。
全局变量:全局变量可以在整个PHP程序中,任何地方访问,但是如果要在函数中访问全局变量,必须在修改该变量的函数中显式的声明为全局变量,在函数中显示声明全局变量很简单,只需在函数中使用global关键字声明就可以了。这样就不会认为这个变量时局部变量了。也可以使用PHP的$GLOBALS数组来取得全局变量的值。
$a = 0 ;
//global $$a; //ok
//global $a=0; //wrong
function Test()
{
global $a;
$a =1;
}
Test();
echo $a;
超全局变量:
$GLOBALS:包含一个引用指向当前脚本的全局范围内有效的变量,该数组的键名为全局变量的名称。 $_SERVER:变量由web服务器设定或者直接与当前脚本的执行环境相关联。(类似于$HTTP_SERVER_VARS数组,但不建议使用) $_GET:经由URL请求提交至脚本的变量。(类似于$HTTP_GET_VARS数组,但不建议使用) $_POST:经由HTTP POST 方法提交至脚本的变量。(类似于$HTTP_POST_VARS数组,但不建议使用) $_COOKIE:经由 HTTP Cookies 方法提交至脚本的变量。(类似于$HTTP_COOKIE_VARS数组,但不建议使用) $_FILES:经由 HTTP POST 文件上传而提交至脚本的变量。(类似于$HTTP_POST_FILES数组,但不建议使用)$_ENV:执行环境提交至脚本的变量。(类似于$HTTP_ENV_VAR数组,但不建议使用)
$_REQUEST:经由 GET,POST 和 COOKIE 机制提交至脚本的变量,因此该数组并不值得信任。
8、创建动态函数:create_function()。第一个参数是函数的参数,第二个参数是函数的函数体。缺点就是速度比预定义函数要慢。
9、构造函数:具有构造函数的类会在每次创建新对象时先调用此方法,非常适合在使用对象前做的初始化工作。
如果子类中定义了构造函数则不会隐式的调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中通过parent::_construst()来显示的调用父类的构造函数。但是,如果子类没有定义构造函数则如果普通的类方法一样从父类中继承过来构造函数。
为了实现向后兼容性,如果 PHP 5 在类中找不到 __construct() 函数并且也没有从父类继承一个的话,它就会尝试寻找旧式的构造函数,也就是和类同名的函数。
析构函数:__destruct(),会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。
和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。此外也和构造函数一样,子类如果自己没有定义析构函数则会继承父类的。
析构函数即使在使用 exit() 终止脚本运行时也会被调用。在析构函数中调用exit() 将会中止其余关闭操作的运行。
10、final关键字
如果父类中的方法被声明为 final,则子类无法覆盖该方法。如果一个类被声明为 final,则不能被继承。
最终类是不能被子类化的(即继承),属性不能被定义为 final,只有类和方法才能被定义为 final。
10.1 __toString():定义字符串的输出格式,php为对象提供了一种控制如何转换为字符串的方法,在输出对象时,php就会主动调用这个对象的__toString()方法。注意的是,toString返回的必须是一个字符串,否则会报错。为了确保这个问题不会出现,可以在返回时强制转换一下。
可以根据需要直接调用toString()方法。【如:$me->__toString()】
11、接口:可以指定某个类必须实现哪些方法,但不需要定义方法的具体内容。
接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。接口中定义的所有方法都必须是公有,这是接口的特性所决定的。
要检查一个类是否实现了特殊的接口,可以使用class_implements()。
这个方法就是根据指定的类名(php5.2以后,可以直接通过这种形式)或者类对象,来查找这个类继承的接口数组。
class Book implements Name{
}
$interfaces = class_implements('Book');
if(isset($interfaces['Name'])){
}
也可以使用反射类来检查:
class Book implements Name{
}
$rc = new ReflectionClass('Book');
if($rc->implementsInterface('Name')){
}
12、php反射类
// 获取反射类中的所有存在的方法
$class=new ReflectionClass("ReflectionClass");
$methods=$class->getMethods();
foreach($methods as $method)
print($method->getName()."<br>");
反射类使用的一个实例:
class fuc { //定义一个类
static function ec() {
echo 'I am a class';
}
}
$c=new ReflectionClass('fuc'); //建立 fuc这个类的反射类
//echo $c; //输出这反射类
$fuc = $c->newInstance();
$fuc->ec();
13、抽象类:定义为抽象的类不能被实例化。任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。
继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。
如果子类没有实现父类中的所有抽象方法,则这个类仍然是抽象类,必须由另外一个类来进一步扩展这个类。
14、传递对象的引用:php5中,使用‘=’进行对象的赋值,并没有创建该对象的副本,而是传递一个对该对象的引用。而对其他类型的变量传递的则是值的副本;php4中,所有的变量都是传递值的副本,要想建立对象的连接,则需要使用‘=&’。
15、对象的克隆:要想基于相同的内容创建包含独立值的技巧,可以使用另一种称为拷贝值的方式,即clone关键字。这样就第二个变量中保存的就不是对第一个对象的引用,而是与第一个对象独立的值。
克隆会把第一个对象中所有的属性都拷贝到第二个对象中,其中也包括属性中保存的对象。这里的克隆是浅克隆。
要想在php5中控制如何克隆对象,通过在相应的类中实现一个__clone()方法来达到,如果这个方法存在了。php会允许__clone()覆盖默认的行为。
16、php不支持方法多态性的内在特性。即无法根据传递参数的数量和类型来决定执行不同的方法。
17、定义类常量:1)使用const;2)类常量的前面是不需要多了符($)的;3)访问同访问静态属性类似,不需要实例化类对象,直接使用‘::’来访问,在同一个类内部访问该常量使用self::访问。
class MyClass{
const constant = 'constant value';
function showConstant() {
echo self::constant . "\n";
}
}
echo MyClass::constant . "\n";
$classname = "MyClass";
echo $classname::constant . "\n"; // 自 5.3.0 起
$class = new MyClass();
$class->showConstant();
echo $class::constant."\n"; // 自 PHP 5.3.0 起
18、在对象实例化期间自动地加载类文件
当使用一个类的时候,必须将该类文件使用include或required加进来,这样才可以使用这个类。
<?php
//PHP4 写法,之前必须加载类文件
include_once "cls/clsA.php";
include_once "cls/clsB.php";
$obj_A = new clsA();
$obj_B = new clsB();
?>
它的处理加载步骤是:1)加载类文件;2)实例化类
<?php
// PHP5 Used __autoload function
$obj_A = new clsA();
$obj_B = new clsB();
function __autoload($className){
include_once "cls/$className.php";
}
?>
它的处理加载步骤是:1)创建对象(伪实例);2)调用__autoload函数,将伪实例的类名传入;3)使用__autoload函数中预先写好的加载规则进行加载类文件;4)实例化对象(真实的实例)