php 生僻知识点认知
资料引用来源:http://www.runoob.com/php/php-tutorial.html
echo 和 print 区别:
- echo - 可以输出一个或多个字符串
- print - 只允许输出一个字符串,返回值总为 1
提示:echo 输出的速度比 print 快, echo 没有返回值,print有返回值1。
- 变量名必须以字母或者下划线字符开始
- 变量名只能包含字母数字字符以及下划线(a-z、0-9 和 _ )
- 变量名是区分大小写的($y 和 $y 是两个不同的变量)
php 是一门弱类型语言
php 会根据变量的值,自动把变量转换为正确的数据类型。
在强类型的编程语言中,我们必须在使用变量前先声明(定义)变量的类型和名称。
在所有函数外部定义的变量,拥有全局作用域。除了函数外,全局变量可以被脚本中的任何部分访问,要在一个函数中访问一个全局变量,需要使用 global 关键字。
当一个函数完成时,它的所有变量通常都会被删除。然而,有时候您希望某个局部变量不要被删除。
要做到这一点,请在您第一次声明变量时使用 static 关键字:
php eof(heredoc) 使用说明
- 1. 必须后接分号,否则编译通不过。
- 2. eof 可以用任意其它字符代替,只需保证结束标识与开始标识一致。
- 3. 结束标识必须顶格独自占一行(即必须从行首开始,前后不能衔接任何空白和字符)。
- 4. 开始标识可以不带引号或带单双引号,不带引号与带双引号效果一致,解释内嵌的变量和转义符号,带单引号则不解释内嵌的变量和转义符号。
- 5. 当内容需要内嵌引号(单引号或双引号)时,不需要加转义符,本身对单双引号转义,此处相当与q和qq的用法。
-
1.以 <<<eof 开始标记开始,以 eof 结束标记结束,结束标记必须顶头写,不能有缩进和空格,且在结束标记末尾要有分号 。
2.开始标记和结束标记相同,比如常用大写的 eot、eod、eof 来表示,但是不只限于那几个(也可以用:json、html等),只要保证开始标记和结束标记不在正文中出现即可。
3.位于开始标记和结束标记之间的变量可以被正常解析,但是函数则不可以。在 heredoc 中,变量不需要用连接符 . 或 , 来拼接
整型可以用三种格式来指定:十进制, 十六进制( 以 0x 为前缀)或八进制(前缀为 0)。
可以通过设置变量值为 null 来清空变量数据:
一个常量由英文字母、下划线、和数字组成,但数字不能作为首字母出现。 (常量名不需要加 $ 修饰符)。
注意: 常量在整个脚本中都可以使用。
strpos() 函数用于在字符串内查找一个字符或一段指定的文本。
如果在字符串中找到匹配,该函数会返回第一个匹配的字符位置。如果未找到匹配,则返回 false。
自 php 5.3 起,可以省略三元运算符中间那部分。表达式 expr1 ?: expr3 在 expr1 求值为 true 时返回 expr1,否则返回 expr3。
注意:php_eol 是一个换行符,兼容更大平台。
运算符的等级
必须要注意的是 elseif 与 else if 只有在使用花括号的情况下才认为是完全相同。如果用冒号来定义 if/elseif 条件,那就不能用两个单词的 else if,否则 php 会产生解析错误。 详见 http://php.net/manual/zh/control-structures.elseif.php
- 数值数组 - 带有数字 id 键的数组
- 关联数组 - 带有指定的键的数组,每个键关联一个值
- 多维数组 - 包含一个或多个数组的数组
- sort() - 对数组进行升序排列
- rsort() - 对数组进行降序排列
- asort() - 根据关联数组的值,对数组进行升序排列
- ksort() - 根据关联数组的键,对数组进行升序排列
- arsort() - 根据关联数组的值,对数组进行降序排列
- krsort() - 根据关联数组的键,对数组进行降序排列
php 超级全局变量列表:
- $globals
- $_server
- $_request
- $_post
- $_get
- $_files
- $_env
- $_cookie
- $_session
do...while 语句
- 函数名称以字母或下划线开头(不能以数字开头)
php 魔术常量
php 向它运行的任何脚本提供了大量的预定义常量。
不过很多常量都是由不同的扩展库定义的,只有在加载了这些扩展库时才会出现,或者动态加载后,或者在编译时已经包括进去了。
有八个魔术常量它们的值随着它们在代码中的位置改变而改变。
例如 __line__ 的值就依赖于它在脚本中所处的行来决定。这些特殊的常量不区分大小写
__line__
__file__
__dir__
__function__
__class__
__trait__
__method__
__namespace__
自 php 5.4.0 起,php 实现了代码复用的一个方法,称为 traits
优先顺序是当前类中的方法会覆盖 trait 方法,而 trait 方法又覆盖了基类中的方法
php 命名空间(namespace)是在php 5.3中加入的
php 命名空间可以解决以下两类问题:
- 用户编写的代码与php内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
- 为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。
如果一个文件中包含命名空间,它必须在其它所有代码之前声明命名空间
在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句
<?php declare(encoding='utf-8'); //定义多个命名空间和不包含在命名空间中的代码 namespace myproject { const connect_ok = 1; class connection { /* ... */ } function connect() { /* ... */ } }
<html> <?php namespace myproject; // 命名空间前出现了“<html>” 会致命错误 - 命名空间必须是程序脚本的第一条语句 ?>
对象的3大特性:封装、继承,多态
- public(公有):公有的类成员可以在任何地方被访问。
- protected(受保护):受保护的类成员则可以被其自身以及其子类和父类访问。
- private(私有):私有的类成员则只能被其定义所在的类访问。
php 不会在子类的构造方法中自动的调用父类的构造方法。要执行父类的构造方法,需要在子类的构造方法中调用 parent::__construct(),但是如果子类没有构造方法的话会自动继承父类的构造方法
php 5 新增了一个 final 关键字。如果父类中的方法被声明为 final,则子类无法覆盖该方法。如果一个类被声明为 final,则不能被继承
声明类属性或方法为 static(静态),就可以不实例化类而直接访问。
静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。
由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。
静态属性不可以由对象通过 -> 操作符来访问。
自 php 5.3.0 起,可以用一个变量来动态调用类。但该变量的值不能为关键字 self,parent 或 static。
<?php
class foo {
public static $my_static = 'foo';
public function staticvalue() {
return self::$my_static;
}
public static function getvalue() {
return self::$my_static;
}
}
print foo::$my_static . php_eol;
$foo = new foo();
print $foo->staticvalue() . php_eol;
print $foo::staticvalue() . php_eol;
print $foo->getvalue() . php_eol;
print $foo::getvalue() . php_eol;
?>
可以把在类中始终保持不变的值定义为常量。在定义和使用常量的时候不需要使用 $ 符号
接口
使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口中定义的所有方法都必须是公有,这是接口的特性。
要实现一个接口,使用 implements 操作符。类中必须实现接口中定义的所有方法,否则会报一个致命错误。类可以实现多个接口,用逗号来分隔多个接口的名称。
抽象类
任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。
定义为抽象的类不能被实例化。
被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。
继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。
子类方法可以包含父类抽象方法中不存在的可选参数。
抽象类和接口的概念要分清楚,容易混淆
命名空间的理解有深度,需要花点力气学习下
php 命名空间中的类名可以通过三种方式引用:
-
非限定名称,或不包含前缀的类名称,例如 $a=new foo(); 或 foo::staticmethod();。如果当前命名空间是 currentnamespace,foo 将被解析为 currentnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,则 foo 会被解析为foo。 警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称。
-
限定名称,或包含前缀的名称,例如 $a = new subnamespace\foo(); 或 subnamespace\foo::staticmethod();。如果当前的命名空间是 currentnamespace,则 foo 会被解析为 currentnamespace\subnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,foo 会被解析为subnamespace\foo。
-
完全限定名称,或包含了全局前缀操作符的名称,例如, $a = new \currentnamespace\foo(); 或 \currentnamespace\foo::staticmethod();。在这种情况下,foo 总是被解析为代码中的文字名(literal name)currentnamespace\foo。
注意访问任意全局类、函数或常量,都可以使用完全限定名称,例如 \strlen() 或 \exception 或 \ini_all。
在命名空间内部访问全局类、函数和常量:
<?php namespace foo; function strlen() {} const ini_all = 3; class exception {} $a = \strlen('hi'); // 调用全局函数strlen $b = \ini_all; // 访问全局常量 ini_all $c = new \exception('error'); // 实例化全局类 exception ?>
关键字 namespace 可用来显式访问当前命名空间或子命名空间中的元素。它等价于类中的 self 操作符。
namespace操作符,命名空间中的代码
<?php namespace myproject; use blah\blah as mine; // see "using namespaces: importing/aliasing" blah\mine(); // calls function blah\blah\mine() namespace\blah\mine(); // calls function myproject\blah\mine() namespace\func(); // calls function myproject\func() namespace\sub\func(); // calls function myproject\sub\func() namespace\cname::method(); // calls static method "method" of class myproject\cname $a = new namespace\sub\cname(); // instantiates object of class myproject\sub\cname $b = namespace\constant; // assigns value of constant myproject\constant to $b ?>
使用命名空间:别名/导入
php 命名空间支持 有两种使用别名或导入方式:为类名称使用别名,或为命名空间名称使用别名。
在php中,别名是通过操作符 use 来实现的. 下面是一个使用所有可能的三种导入方式的例子:
1、使用use操作符导入/使用别名
<?php namespace foo; use my\full\classname as another; // 下面的例子与 use my\full\nsname as nsname 相同 use my\full\nsname; // 导入一个全局类 use \arrayobject; $obj = new namespace\another; // 实例化 foo\another 对象 $obj = new another; // 实例化 my\full\classname 对象 nsname\subns\func(); // 调用函数 my\full\nsname\subns\func $a = new arrayobject(array(1)); // 实例化 arrayobject 对象 // 如果不使用 "use \arrayobject" ,则实例化一个 foo\arrayobject 对象 ?>
导入操作是在编译执行的,但动态的类名称、函数名称或常量名称则不是。
3、导入和动态名称
<?php use my\full\classname as another, my\full\nsname; $obj = new another; // 实例化一个 my\full\classname 对象 $a = 'another'; $obj = new $a; // 实际化一个 another 对象 ?>
全局空间
如果没有定义任何命名空间,所有的类与函数的定义都是在全局空间,与 php 引入命名空间概念前一样。在名称前加上前缀 \ 表示该名称是全局空间中的名称,即使该名称位于其它的命名空间中时也是如此。
使用全局空间说明
<?php namespace a\b\c; /* 这个函数是 a\b\c\fopen */ function fopen() { /* ... */ $f = \fopen(...); // 调用全局的fopen函数 return $f; } ?>
名称解析遵循下列规则:
- 对完全限定名称的函数,类和常量的调用在编译时解析。例如 new \a\b 解析为类 a\b。
- 所有的非限定名称和限定名称(非完全限定名称)根据当前的导入规则在编译时进行转换。例如,如果命名空间 a\b\c 被导入为 c,那么对 c\d\e() 的调用就会被转换为 a\b\c\d\e()。
- 在命名空间内部,所有的没有根据导入规则转换的限定名称均会在其前面加上当前的命名空间名称。例如,在命名空间 a\b 内部调用 c\d\e(),则 c\d\e() 会被转换为 a\b\c\d\e() 。
- 非限定类名根据当前的导入规则在编译时转换(用全名代替短的导入名称)。例如,如果命名空间 a\b\c 导入为c,则 new c() 被转换为 new a\b\c() 。
- 在命名空间内部(例如a\b),对非限定名称的函数调用是在运行时解析的。例如对函数 foo() 的调用是这样解析的:
- 在当前命名空间中查找名为 a\b\foo() 的函数
- 尝试查找并调用 全局(global) 空间中的函数 foo()。
- 在命名空间(例如a\b)内部对非限定名称或限定名称类(非完全限定名称)的调用是在运行时解析的。下面是调用 new c() 及 new d\e() 的解析过程: new c()的解析:
- 在当前命名空间中查找a\b\c类。
- 尝试自动装载类a\b\c。
- 在类名称前面加上当前命名空间名称变成:a\b\d\e,然后查找该类。
- 尝试自动装载类 a\b\d\e。