在一个大项目,有很多个功能,每个功能定义一个类文件,如果每次调用是都include或require加载这些类文件,会非常耗内存开销,并且还有一些类文件中功能并没有使用,造成资源的浪费。
比如
这时,用**__autoload()类的自动加载函数可以解决这个问题,即类的按需加载**。
__autoload()是php中的系统函数,是自动调用的,函数只有一个参数className就是类名。
什么情况下类会自动调用__autoload()函数呢?
在类的new实例化、类::方法名(调用静态方法)、类的继承和实现接口时,会自动调用__autoload()函数。
1、将每一个功能,单独定义成一个类文件;
2、每一个类文件,尽量以”.class.php”结尾;例如:Student.class.php
3、类文件的主名,要与类名一致;例如:class Student{}
4、类名命名方式,尽量使用“大驼峰式”命名,每个单词首字母大写;例如:class ConnMySQL
5、方法命名方式,尽量使用“小驼峰式”命名,第1个单词全小写,后面每个单词首字母大写;例如:getCode()
6、属性命名方式,尽量使用“小驼峰式”命令,与方法命名一致。
而__autoload()函数做了两件事:
1、构建(引用)类文件的真实路径
2、判断并包含(加载)类文件代码
比如
以上是常规的类自动加载
注意!
当类的定义不在同一个文件目录,或者类的命名方式不同,用__autoload()函数就不太适用,显得很臃肿。
比如
这时,用自定义类文件加载函数(spl_autoload_register)就很恰当了,当然,用compose方式更为恰当,不妨看看这个 https://www.php.cn/blog/detail/24131.html
spl_autoload_register():更加灵活地实现类的自动加载,官方定义是注册给定的函数作为 __autoload 的实现
1、注册多个类加载函数,形成了一个类文件的队列,按照注册时的顺序,依次执行。哪个类文件存在,就包含哪个类文件。
2、每个函数就是一种类文件的加载规则。
3、语法:spl_autoload_register(autoload_function,throw,prepend)
第一个参数:autoload_function
这是一个函数【方法】名称,可以是字符串或者数组(调用类方法使用),也可以是匿名函数(建议用这种方式),后面两个参数默认为true可以不传,比如
spl_autoload_register(function ($className)
{
$classFileName = "./public/{$className}.php";
include $classFileName;
}, true, true);
$objDemo = new AutoloadClass();
这个函数(方法)的功能就是,来把需要new 的类文件包含include(requeire)进来,这样new的时候就不会找不到文件了。其实就是封装整个项目的include和require功能。
第二个参数:throw
此参数设置了 autoload_function 无法成功注册时, spl_autoload_register()是否抛出异常。
第三个参数:prepend
如果是 true,spl_autoload_register() 会添加函数到队列之首,而不是队列尾部。
比如
除了new关键字可以创建对象,克隆方式用clone关键字也可以创建对象。
克隆对象后,如果想修改对象的属性可以使用克隆方法__clone(魔术方法,在对象克隆完成后自动调用),但克隆方法的权限不能是private,而是public,不然会报错。
比如
在类内可以遍历所有属性,在类外可以遍历公共属性
比如
魔术方法在特定条件下自动调用,有点意思
具体调用请看这个 https://www.php.cn/php-weizijiaocheng-483366.html
或者 https://www.php.net/manual/zh/language.oop5.magic.php
说到类的魔术方法,我们又可以回顾面向对象多态的中重载。
1、 php中的“重载”与其它绝大多数面向对象语言不同。传统的“重载”是用于提供多个同名的类方法,但各方法的参数类型和个数不同。
2、php所提供的"重载"(overloading)是指动态地"创建"类属性和方法。我们是通过魔术方法来实现的。
3、当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。
4、所有的重载方法都必须被声明为 public。
5、属性重载只能在对象中进行。在静态方式中,这些魔术方法将不会被调用。所以这些方法都不能被声明为 static。
这些魔术方法的参数都不能通过引用传递
属性的重载
__set()
描述:在给不可访问属性赋值时,__set() 会被调用。
语法:public void __set ( string $name , mixed $value )
__get()
描述:读取不可访问属性的值时,__get() 会被调用。
语法:public mixed __get ( string $name )
__isset()
描述:当对不可访问属性调用 isset() 或 empty() 时,__isset()会被调用。
语法:public bool __isset ( string $name )
__unset()
描述:当对不可访问属性调用 unset() 时,__unset()会被调用。
语法:public void __unset ( string $name )
方法的重载
__call()
描述:在对象中调用一个不可访问方法时,__call() 会被调用。
语法:public mixed __call ( string $name , array $arguments )
__callStatic()
描述:用静态方式中调用一个不可访问方法时,__callStatic() 会被调用。
语法:public static mixed __callStatic ( string $name , array $arguments )
什么是静态延时绑定?
自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。
“后期绑定"的意思是说,static::不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为"静态绑定”,因为它可以用于(但不限于)静态方法的调用。
我们需要一个在调用执行时才确定当前类的一个特征,就是说将static关键字对某个类的绑定推迟到调用执行时,就叫静态延迟绑定!
语法:static::静态属性,静态方法,成员方法,类常量
在继承环境下,static代表最后执行的那个类(静态延时绑定)。
说到面向对象,不得不说设计模式,设计模式是代码设计经验的总结,可以实现代码的充用,节省时间提高开发效率,使得代码易维护和拓展。
1一、单例模式(防止一个对象的重复创建)
单例设计的要求(三私一公)
1、一私:私有的静态的保存对象的属性;
2、一私:私有的构造方法,阻止类外new对象;
3、一私:私有的克隆方法,阻止类外clone对象;
4、一公:公共的静态的创建对象的方法
其中,instanceof关键字
描述:判断一个对象是不是某个类产生的对象。
语法:$obj instanceof ClassName
返回:如果$obj是ClassName的对象,则返回TRUE,否则,返回FALSE。
二、工厂模式
根据传递的不同类名,创建不同类的对象;生产不同类对象的工厂,避免使用new关键字,可以来理解为改变了创建对象的方式。
工厂模式的设计要求
1、工厂模式,可以设计一个工厂类;
2、工厂类中有一个私有的静态的属性,用来存储不同类的对象;
3、工厂类中有一个公共的静态的创建对象的方法。该静态方法的功能代码:判断当前类的对象是否存在,如果存在,直接返回;如果不存在,则创建一个对象,再返回。
注意:该工厂类不创建对象。工厂类本身不是单例的。
单例的工厂类
多个对象,共同实现单例效果。
什么是类型约束?
1、Java属于强类型语言,变量在程序运行过程中,类型不可以改变。
2、PHP和JS属于弱类型语言,变量在程序运行过程中,类型是可以改变的。
3、PHP5.3以后,还有了类型约束。PHP的类型约束,主要指方法参数或函数参数,其它地方还不行。
4、PHP的类型约束有三种:数组约束、对象约束、接口约束。
魔术常量
LINE,当前行号
FILE,当前文件名
DIR,当前目录名
FUNCTION,当前函数名
CLASS,当前类名
METHOD,当前方法
NAMESPACE,当前空间名
类和对象的操作函数
1、判断类、接口、方法、属性是否存在
class_exists()判断类是否存在
interface_exists()判断接口是否存在
method_exists()判断方法是否存在
property_exists()判断属性是否存在
2、获取类名
get_class()根据对象返回类名
get_parent_class()返回父类名称
最后,说一下序列化。
什么是序列化?
1、变量序列化:将变量转成可存储或传输的字符串的过程,会保留变量的类型和结构。
2、变量反序化:将序列化的字符串,再还原成原始变量。
3、除了资源变量外,其它变量都可以序列化。
实现序列化
serialize()
描述:产生一个可存储的值的表示
语法:string serialize ( mixed $value )
实现反序列化
unserialize()
描述:从已存储的表示中创建 PHP 的值
语法:mixed unserialize ( string $str )
以上是变量的序列化
什么是对象序列化?
1、对象的序列化过程,与其它变量数据一样;
2、当序列化对象时,PHP 将试图在序列化动作之前调用该对象的成员函数 __sleep()。这样就允许对象在被序列化之前做任何清除操作。
3、__sleep()魔术方法功能:此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。对象序列化的内容只能包含成员属性,不能包含常量、静态属性、成员方法、静态方法。
对象的反序列化
1、对象的反序列化过程,与其它变量数据一样;
2、若反序列化的变量是一个对象,在成功地重新构造对象之后,PHP 会自动地试图去调用 __wakeup()成员函数(如果存在的话)。
3、unserialize() 会检查是否存在一个 __wakeup()方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。__wakeup() 经常用在反序列化操作中,进行一些初始化操作,例如重新建立数据库连接,或执行其它初始化操作。