1、static方法就相当于普通的方法一模一样,但是给方法分了个类。语义化代码。
2、实例化class时不会重新将static方法声明第二遍
3、静态方法不需要所在类被实例化就可以直接使用。
4、静态方法效率上要比实例化高,静态方法的缺点是不自动进行销毁,而实例化的则可以做销毁。
5、静态方法和静态变量创建后始终使用同一块内存,而使用实例的方式会创建多个内存。
6、静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)
7、由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。
8、有了static的静态延迟绑定功能,可以在运行时动态确定归属的类
static final $this abstract self parent
我觉得一个比较复杂的静态
class A {
public static $a = 1;
public static function foo() {
static::who();
}
public static function who() {
echo __CLASS__."\n";
}
}
class B extends A {
public static $a = 2;
public static function test() {
A::foo(); // A
parent::foo(); // C
self::foo(); // C
echo parent::$a; // 1
echo self::$a; // 2
}
public static function who() {
echo __CLASS__."\n";
}
}
class C extends B {
public static $a = 3;
public static function who1() {
echo __CLASS__."\n";
}
}
C::test();
printf
printf() 函数输出格式化的字符串。
printf(format,arg1,arg2,arg++)
final
final类不能被继承
final方法不能被覆盖
class BaseClass {
public function test() {
echo "BaseClass::test() called\n";
}
final public function moreTesting() {
echo "BaseClass::moreTesting() called\n";
}
}
class ChildClass extends BaseClass {
public function moreTesting() {
echo "ChildClass::moreTesting() called\n";
}
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()
final class BaseClass {
public function test() {
echo "BaseClass::test() called\n";
}
// 这里无论你是否将方法声明为final,都没有关系
final public function moreTesting() {
echo "BaseClass::moreTesting() called\n";
}
}
class ChildClass extends BaseClass {
}
// 产生 Fatal error: Class ChildClass may not inherit from final class (BaseClass)
范围解析操作符 (::)
范围解析操作符(也可称作 Paamayim Nekudotayim)或者更简单地说是一对冒号,可以用于访问静态成员,类常量,还可以用于覆盖类中的属性和方法。如 self,parent 和 static
echo gettype("1111"); // string
$straa = "22";
echo settype($straa,'integer'); // 1
var_dump($straa); // int 22
array
array_push(数组名称,添加的内容) 给数组最后添加一个元素
array_pop(数组名称) 删除并返回数组最后一个元素
array_unshift(数组名称,添加的内容) 给数组最前面添加一个元素
array_shift(数组名称) 删除并返回数组第一个元素
array_keys(数组名称) 返回一个指定数组的所有键名的新数组
array_values(数组名称) 返回一个指定数组的所有键值的新数组
shuffle(数组名称)打乱数组的排列顺序
array_reverse(数组名称)将数组反转
string
strlen(字符串) 获取字符串长度
strstr(操作对象,需要查找的子字符串);用来检测一个字符串中是否包含子字符串
strpos(操作对象,子字符串);用于定位子字符串在操作对象中的位置
substr(操作对象,截取字符的起始位置[,截取字符的长度])
$str = "1234567";
echo "截取".substr($str ,-2,2).'<br>'; // 67
echo $str ; // 1234567
strtok(操作对象,分割字符)分割字符串
strip_tags(操作对象,处理规则)用来格式化字符串
$str = '<b>1111111<br/>1111111<br/>1111111111111</b>'
strip_tags($str,"<br/><p>") // 作用就是屏蔽html标签
substr_replace(需要替换的内容,替换内容,操作对象[,发生替换的次数]) 把【操作对象】中【需要替换的内容替】换成【替换内容】,
$find = array("Hello", "world");
$replace = array('b');
$arr = array("Hello", "world", "!");
print_r(str_replace($find, $replace, $arr)) ;//Array ( [0] => b [1] => [2] => ! )
//如果$replace = array('b','c','d') /Array ( [0] => b [1] =>c [2] => ! )
转换大小写
echo strtoupper("aaaaaaaaa"); // AAAAAAAAA
echo strtolower( strtoupper("aaaaaaaaa")); //aaaaaaaaa
explode(分割字符,操作对象); 把字符打散成数组
$str = "www.runoob.com";
print_r (explode(".",$str));
// Array
// (
// [0] => www
// [1] => runoob
// [2] => com
// )
isset() 看当前这个变量是否为非null
unset()把变量清空 清除全局变量 global $a $global['a']
局部清理全局如果在函数中 unset() 一个静态变量,那么在函数内部此静态
变量将被销毁。
但是,当再次调用此函数时,此静态变量将被复原为上次被销毁之前的值。
如果在局部使用global $a引入全局变量的话unset($a)不会影响全局变量只会影响全局变量在局部中的数值
如果在局部使用 $global['a'] unset($global['a'])就会影响到全局变量
::class
自 PHP 5.5 起,关键词 class 也可用于类名的解析。使用 ClassName::class 你可以获取一个字符串,包含了类 ClassName 的完全限定名称。这对使用了 命名空间 的类尤其有用。
namespace NS {
class ClassName {
}
echo ClassName::class; // NS\ClassName
}
test_input()
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
trim()去除空格
stripslashes()去除字符串中的反斜杠\
htmlspecialchars()将字符串中的特殊字符转化成html实体
preg_match()
$name = test_input($_POST["name"]);
// 检测名字是否只包含字母跟空格
if (!preg_match("/^[a-zA-Z ]*$/",$name))
{
$nameErr = "只允许字母和空格";
}
抽象类(abstract )
abstract class chou{}
就是一个抽象类
abstract function fa(){}
就是一个抽象方法
注意:抽象方法只能定义在抽象类中,抽象方法无法实现,只能定义
抽象类无法实例化只能被继承,当被继承的抽象类中有抽象方法时,其子类必须要实现该抽象方法
abstract class AbstractClass
{
// 强制要求子类定义这些方法
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// 普通方法(非抽象方法)
public function printOut() {
print $this->getValue() . "\n";
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue() {
return "ConcreteClass2";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass2";
}
}
$class1 = new ConcreteClass1;
$class1->printOut(); // ConcreteClass1
echo $class1->prefixValue('FOO_') ."\n"; // FOO_ConcreteClass1
$class2 = new ConcreteClass2;
$class2->printOut(); // ConcreteClass2
echo $class2->prefixValue('FOO_') ."\n"; // FOO_ConcreteClass2
abstract class AbstractClass
{
// 我们的抽象方法仅需要定义需要的参数
abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
// 我们的子类可以定义父类签名中不存在的可选参数
public function prefixName($name, $separator = ".") {
if ($name == "Pacman") {
$prefix = "Mr";
} elseif ($name == "Pacwoman") {
$prefix = "Mrs";
} else {
$prefix = "";
}
return "{$prefix}{$separator} {$name}";
}
}
$class = new ConcreteClass;
echo $class->prefixName("Pacman"), "\n";// Mr. Pacman
echo $class->prefixName("Pacwoman"), "\n";// Mrs. Pacwoman
对象接口(interface)
接口和抽象类的区别主要是定义后方法可不可以实现
抽象方法和接口中定义的方法大同小异
使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口中定义的所有方法都必须是公有,这是接口的特性。
interface A{
// 定义接口
public function fa($can) // 定义方法但是不能实现
}
interface B extends A{ // 接口继承接口 extends
}
class C implements B{ //类继承接口 implements
public function fa($can){ // 必须实现
}
}
interface a
{
const b = 'Interface constant';
}
// 输出接口常量
echo a::b; // Interface constant
class C implements A,B{ // 继承多个要用逗号隔开
public function fa($can)
{
}
}
类的自动加载( spl_autoload_register()
)
当一个实例化一个类时,自己身上找不到时,就回去执行spl_autoload_register()
中的函数
PRINTIT.class.php
<?php
class PRINTIT {
function doPrint() {
echo 'hello world';
}
}
function loadprint( $class ) {
$file = $class . '.class.php';
if (is_file($file)) {
require_once($file);// 表示执行一次引入的文件
}
}
spl_autoload_register( 'loadprint' );
$obj = new PRINTIT();
$obj->doPrint(); // 'hello world'
trait
关键字trait
、use
自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。
Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。
1、无法定义常量
2、self、parent、static等关键字代表的类,在被使用后才确定
3、优先级:当类中自己有要使用的方法或者属性时,就不会去use的trait
4、要use多个trait的话,中间用逗号隔开
5、trait中也可以定义抽象方法
trait VV{
const cc = 0; // 这里会报错说是不让在trait中定义常量
static $b = 1;
function a(){
return self::$c;
}
}
class bbb {
use VV;
static $c = 2;
}
$aa = new bbb();
echo $aa->a(); // 2
echo bbb::$b; // 1
------------------------------分割线------------------------------------------------------------------------
class Base {
public function sayHello() {
echo 'Hello ';
}
}
trait SayWorld {
public function sayHello() {
parent::sayHello();
echo 'World!';
}
public function sayHello1() {
echo 'Hello World!';
}
}
class MyHelloWorld extends Base {
use SayWorld;
public function sayHello1() {
echo 'Hello class!';
}
}
$o = new MyHelloWorld();
$o->sayHello(); // Hello World!
$o->sayHello(); // Hello class! 优先级问题自己身上有就不去use的trait中找了
匿名类
PHP 7 开始支持匿名类。 匿名类很有用,可以创建一次性的简单对象。
new class
核心 注 可能会报错 因为 编译软件的中php版本
$class = new class(10){
static $a = 111;
public $s;
public function __construct($bain)
{
$this->s = $bain;
}
public function abc(){
echo "abc";
}
};
$class->abc(); // abc
echo $class->s;// 10
类型于一个生产匿名类的类
class Create
{
public $classname;
public function getLogger(){
return $this->classname;
}
public function setLogger($class){
$this->classname = $class;
}
}
$create = new Create;
$create->setLogger(new class(){
public function text(){
echo '测试';
}
});
$create->getLogger()->text(); // 测试
重载以及魔术方法
这里主要以魔术方法举例
下面用到的魔术方法__get获取属性时、__set修改属性时、__isset对象属性使用isset时、__unset对属性使用unset时
<?php
class Chong{
private $var = 0;
private $un = 1;
public function __set($name, $value)
{
echo $this->$name.'到'.$value.'<br>';
$this->$name = $value;
// TODO: Implement __set() method.
}
public function __get($name)
{
echo "获取.$name".'<br>';
if (isset( $this->$name))
{
return $this->$name;
}
else{
return null;
}
// TODO: Implement __get() method.
}
public function __unset($name)
{
echo "销毁".__CLASS__.'::'.$name."<br>";
unset($this->$name);
// TODO: Implement __unset() method.
}
public function __isset($name)
{
echo "检测".__CLASS__.'::'.$name."<br>";
return isset($this->$name);
// TODO: Implement __isset() method.
}
}
$chong = new Chong();
echo $chong->var;
$chong->var = 111;
echo "<br>";
echo $chong->var;
var_dump(isset($chong->un));
unset($chong->un);
var_dump($chong->un);
以下是打印结果
下面魔术方法__call 调用不存在的方法时执行、__callStatic(注意该function定义时必须是静态方法)调用不存在的静态方法时执行
class MethodTest
{
public function a(){
echo "该方法存在所以不会执行__call";
}
public function __call($name, $arguments)
{
echo "一个不存在的的方法".$name."被调用"."<br>".implode(" ,",$arguments)."<br>";
// TODO: Implement __call() method.
}
public static function __callStatic($name, $arguments)
{
echo "一个不存在的的静态方法".$name."被调用"."<br>".implode(" ,",$arguments);
// TODO: Implement __callStatic() method.
}
}
$obj = new MethodTest;
$obj->a();
echo "<br>";
$obj->runTest('in object context',"2222");
$obj::runTest('in object context',"1112222");
关于变量对象属性
foreach
class MyClass
{
public $var1 = 'value 1';
public $var2 = 'value 2';
public $var3 = 'value 3';
protected $protected = 'protected var';
private $private = 'private var';
public function iterateVisible(){
foreach ($this as $key=>$value){
echo "$key=>$value\n";
}
}
}
$class = new MyClass();
foreach ($class as $key=>$value){
echo "$key=>$value\n";
}
echo "<br>";
$class->iterateVisible();
上述结果产生的原因 是 属性的可读性
魔术方法
__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() 和 __debugInfo() 等方法在 PHP 中被称为魔术方法
__construct()在类实例化时执行
__destruct() 在类解析时执行(执行完后实例化后的对象就销毁了)
__call(), __callStatic(), __get(), __set(), __isset(), __unset() 上面重载里有
__string()
需要指出的是在 PHP 5.2.0 之前,__toString() 方法只有在直接使用于 echo 或 print 时才能生效。PHP 5.2.0 之后,则可以在任何字符串环境生效(例如通过 printf(),使用 %s 修饰符),但不能用于非字符串环境(如使用 %d 修饰符)。自 PHP 5.2.0 起,如果将一个未定义 __toString() 方法的对象转换为字符串,会产生 E_RECOVERABLE_ERROR 级别的错误。
class TestClass
{
public $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
public function __toString() {
return $this->foo;
}
}
$class = new TestClass('Hello');
echo $class; // Hello
__invoke
当把一个对象尝试当作一个函数执行时,会执行__invoke
class CallableClass
{
function __construct($x)
{
var_dump($x);
}
function __invoke($x) {
var_dump($x);
}
}
$obj = new CallableClass(4);
$obj(5);
var_dump(is_callable($obj))
__set_state
调用 var_export() 导出类时,此静态 方法会被调用。
var_export() 函数返回关于传递给该函数的变量的结构信息,它和 var_dump() 类似,不同的是其返回的表示是合法的 PHP 代码。var_export必须返回合法的php代码, 也就是说,var_export返回的代码,可以直接当作php代码赋值个一个变量。 而这个变量就会取得和被var_export一样的类型的值
<?php
class A
{
public $var1;
public $var2;
public static function __set_state($an_array) // As of PHP 5.1.0
{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);
?>
返回结果
object(A)#2 (2) {
[“var1”]=>
int(5)
[“var2”]=>
string(3) “foo”
}
__debugInfo
当使用var_dump() print_r()
打印实列对象时会执行__debugInfo中的内容
class C {
private $prop;
public function __construct($val) {
$this->prop = $val;
}
public function __debugInfo() {
return [
'propSquared' => $this->prop ** 2,
];
}
}
print_r(new C(42));
结果
C Object ( [propSquared] => 1764 )
__clone与复制对象
__clone在当前对象被克隆时执行
class A{
public $a = 1;
public function __clone()
{
echo "clone".'<br>';
// TODO: Implement __clone() method.
}
}
$obj1 = new A;
$obj2 = $obj1;
$obj3 = clone $obj1;
echo $obj1->a."\n";
echo $obj2->a."\n";
echo $obj3->a."\n";
echo "<br>";
$obj1->a = 2;
echo $obj1->a."\n";
echo $obj2->a."\n";
echo $obj3->a."\n";
返回结果
clone
1 1 1
2 2 1
对象序列化和__sleep以及__wakeup
serialize() 函数用于序列化对象或数组,并返回一个字符串。
unserialize()函数用于序列化后的对象或数组,并返回一个序列化之前的内容。
__sleep()对类进行序列化时执行
__wakeup()对类进行反序列化时执行
<?php
classa.php文件
class A {
public $one = 1;
public function __sleep()
{
echo "sleep";
return [];
// TODO: Implement __sleep() method.
}
public function __wakeup()
{
echo "wakeup";
// TODO: Implement __wakeup() method.
}
public function show_one() {
echo $this->one;
}
}
include("classa.php");
page1.php文件
$a = new A;
$s = serialize($a);
// 把变量$s保存起来以便文件page2.php能够读到
file_put_contents('store', $s);
// sleep
page2.php文件
include("classa.php");
$s = file_get_contents('store');
echo $s;
$a = unserialize($s);
// 现在可以使用对象$a里面的函数 show_one()
$a->show_one();
// wakeup 1
时间
time()获取当前时间戳
转换时间戳 getdate()
getdate() 转化时间戳,返回一个数组,包含日期时间等所有信息
print_r(getdate(time())) // Array ( [seconds] => 46 [minutes] => 2 [hours] => 9 [mday] => 6 [wday] => 5 [mon] => 3 [year] => 2020 [yday] => 65 [weekday] => Friday [month] => March [0] => 1583485366 )
在php.ini中搜索date.timezone修改时区 Aisa/ShangHai(有错)
date()用来获取格式化时间
echo date("Y-m-d H-i-s A",mktime(8,57,42,11,21,2020)); // 2020-11-21 08-57-42 AM
mktime(时,分,秒,月,日,年) //给一个时间返回一个时间戳
checkdate(月,日,年); // 检测日期是否合法
echo checkdate(12,1,1976); // 1 日期合法返回 1
echo checkdate(14,1,1976); // 这个明显是错的 false