前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PHP类,魔术方法

PHP类,魔术方法

作者头像
宣言言言
发布于 2019-12-19 04:23:38
发布于 2019-12-19 04:23:38
93000
代码可运行
举报
文章被收录于专栏:宣言(Siam)博客宣言(Siam)博客
运行总次数:0
代码可运行

以下方法在 PHP 中被称为魔术方法(Magic methods)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
__construct()
__destruct()
__call()
__callStatic()
__get()
__set()
__isset()
__unset()
__sleep()
__wakeup()
__toString()
__invoke()
__set_state()
__clone()
__debugInfo()

在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能。

下面介绍每个方法的作用

__construct

构造函数,在实例化类的时候会隐式调用该方法,可以接收传参。如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A{
    public function __construct($size) {
        $this->maxSize = $size; // 做一些初始化设置等等
        echo $this->maxSize;
    }
}

new A(3);

如果有一个类B继承了上面的类A ,如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class B extends A{
    public function __construct($size) {
        echo "hello";
    }
}

new B(3);

在此例子中,不会设置和输出maxSize属性,只会输出hello。

因为在子类重写构造方法时,需要显式调用父类构造函数 parent::__construct()

注意

如果在A类的构造函数,不是写为public,而是private,则无法被子类继承使用。

__destruct

析构函数,当类被手动销毁,或者脚本结束时,gc回收触发。可以执行一些后置操作,比如删除临时目录下的文件。

注意

  • 哪怕脚本调用exit(),die() 类的析构函数也会被执行
  • 如果在析构函数中调用exit() 则该函数内部的逻辑后续不再执行
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public __destruct()
{
    echo 1;
    exit();
    echo 2;// 不会输出
}
  • 与构造函数相同,子类继承后需要显式调用父类的析构函数
  • 试图在析构函数(在脚本终止时被调用)中抛出一个异常会导致致命错误。

__call

当调用一个对象中的不能用的方法的时候就会执行这个函数。有两个参数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function __call($function_name, $args)

测试

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A{
    public function __call($funcname, $args){
        var_dump($funcname);
        var_dump($args);
    }
}

$a = new A();
$a->one();
$a->tow('一个参数');

// 以下是输出

/*
string(3) "one"
array(0) {
}
string(3) "tow"
array(1) {
  [0]=>
  string(12) "一个参数"
}
string(5) "three"
array(2) {
  [0]=>
  string(12) "一个参数"
  [1]=>
  string(12) "两个参数"
}
*/

__callStatic

跟__call一样,但是该函数触发的是调用的静态方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
A::test();

__get

读取不可访问属性的值时,__get() 会被调用。

猜想:在thinkphp框架的ORM中,关联模型

先在Orders模型中设置大概如下的方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 本模型的user ,代表要关联Users模型的一个数据,本模型的u_id = Users模型的id
public function user()
{
    return $this->belongTo('Users', 'u_id', 'id');
}

当在程序中调用,因为本身的Orders模型没有该属性,所以会尝试是否有设置该关系的方法,有则调用,然后返回Users的信息。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$orders = Orders::get(1);
var_dump(orders->user);

__set

在给不可访问属性赋值时,__set() 会被调用。

__isset

当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。

__unset

当对不可访问属性调用 unset() 时,__unset() 会被调用。

__sleep

__wakeup

这两个魔术方法是 类的序列化 使用的,后续会有一篇专门的文章讲解。

__toString

__toString() 方法用于一个类被当成字符串时应怎样回应。

比如,在我们接入微信支付的时候,经常需要把参数排序、拼接成url格式

我们完全可以定义一个类,然后在toString魔术方法中,写明排序、转换为url格式的操作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 伪代码

$params = new SiamWechatParams();
$params->appid = '1';
$params->total_fee = 200;

// http请求
Curl::send(self::url, $params->__toString());

// 其他地方直接输出,不手动显式调用
echo $params;

__invoke

当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A
{
    function __invoke($params) {
        var_dump($params);
    }
}
$obj = new A();
$obj(5);
var_dump(is_callable($obj));

__set_state

自 PHP 5.1.0 起当调用 var_export() 导出类时,此静态 方法会被调用。

__clone

当对象复制完成时调用

__debugInfo

当调用var_dump函数时候,定义需要显示的属性列表

如果没有在对象上定义该方法,那么将显示所有公共、受保护和私有属性。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.08.04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
iOS13 Scene Delegate
iOS13以后,SceneDelegate将负责AppDelegate的某些功能。 window(窗口)的概念被window(场景)的概念所代替, 一个scene现在可以作为您应用程序的用户界面和内容的载体。iOS13以前一个应用程序可以有不止一个window,同样现在一个应用程序也可以有不止一个scene。
conanma
2021/11/04
5.8K0
iOS中OC给Category添加属性
很多人知道可以用Category给已有的类添加一些新方法,但是不同于swift中的extension,Objective-C中的Category(类别)是不支持直接添加属性的,那如果就是需要添加新的属性怎么办呢?有一个办法,使用Runtime中的关联对象技术就可以实现。关于Runtime的说明可以查看这篇博客:传送门:OC中Runtime浅析
Cloudox
2021/11/23
1.4K0
iOS中OC给Category添加属性
iPadOS上启动黑屏翻车问题分析(二)
昨天我们说了旧的项目在iOS 13下完全启动之后黑屏的问题,然后紧跟问题通过UI图层分析方式一步步的分析基本找到了问题的根源---iPadOS的底层以及操作思路转变啦
大话swift
2019/10/14
2K0
iPadOS上启动黑屏翻车问题分析(二)
iOS开发之Xcode11后纯代码项目工程设置
Xcode 11发布之后,新建iOS项目工程时,会有很多变化,最大的变化是多了文件SceneDelegate,此时如果希望通过纯代码设置界面,流程与以往会有一些不一样,本文简单介绍一下。
YungFan
2019/12/26
1.9K0
iOS开发之Xcode11后纯代码项目工程设置
iOS 新创建项目中的SceneDelegate适配
Xcode 11之后新建工程,默认为有SceneDelegate,但是SceneDelegate是从iOS 13之后才有的,如果最低兼容版本到iOS 13以下,需要怎么做呢?
莫空9081
2021/04/21
3.5K0
Xcode12 删除Scene
1、Deployment Info Main Interface 清空 截屏2021-08-30 09.26.16.png 2、AppDelegate 删除如下代码 #pragma mark - UISceneSession lifecycle - (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)conne
赵哥窟
2021/12/16
8910
Xcode12 删除Scene
iOS18适配指南之UITabBarController
YungFan
2024/09/17
1.5K0
从0开发一款IOS APP(第一天)
实例化的时候使用TestView:TestView *view2 = [[TestView alloc] init];
zx钟
2019/07/19
1.2K0
iOS开发UI篇--一个侧滑菜单SlidingMenu
侧滑菜单已经成为app一个极常用的设计,不管是事务类,效率类还是生活类app。侧滑菜单因Path 2.0和Facebook为开发者熟知,国内目前也有很多流行app用到了侧滑菜单,比如QQ、网易邮箱、知乎等等。 IOS官方并没有提供类似于侧滑栏之类的组件,所以我们需要自己写一个侧滑栏控件,为了不要重复造轮子,我在github上找到了一个使用简单方便,新手容易入手的侧滑菜单控件,Demo下载地址:这是一个我的iOS交流群:624212887,群文件自行下载,不管你是小白还是大牛热烈欢迎进群 ,分享面试经验,讨论技术, 大家一起交流学习成长!希望帮助开发者少走弯路。
楚阳
2018/12/13
1.3K0
Unity项目嵌入现有iOS项目的方法
因为现有项目有个功能需要调用Unity页面,所以就叫同事用Unity打一个包给我嵌入到现有iOS工程,就一个导入过程就非常曲折。(泪奔~~o(>_<)o ~~) 以下所有的文件结构和TARGETS配置
傅_hc
2018/07/04
3K0
ios5开发-UITableView开启编辑功能
该例子添加UITableView编辑功能 具体功能如下 功能很简单但很实用  @implementation AppDelegate @synthesize window = _window; @s
阿新
2018/04/12
8150
ios5开发-UITableView开启编辑功能
Xcode11 删除Storyboard 之后黑屏
今天新写一个项目,不需要Storyboard,本以为很简单,删除之后黑屏踩了一个坑,在此记录一下。这个解决办法不一定是正确,但是这么做确实可行。
赵哥窟
2020/07/10
1.6K0
Xcode11 删除Storyboard 之后黑屏
UITabBarController实现Tab切换
在很多的应用中,基本都是使用Tab方式进行模块间的切换。在Android中很多控件可以实现这类效果,TabLayout、TabHost… 而在iOS中系统为我们提供了UITabBarController类来实现Tab页面之间的切换。有几个页面我们就创建几个UINavigationController,然后通过tabbar.viewControllers = @[navi1, navi2, navi3…]; 设置给UITabBarController。在进行Tab切换的设计思想上Android和iOS是
xiangzhihong
2018/02/06
2K0
UITabBarController实现Tab切换
React Native 系列(三) -- 项目结构介绍
前言 本系列是基于React Native版本号0.44.3写的,相信大家看了本系列前面两篇文章之后,对于React Native的代码应该能看懂一点点了吧。本篇文章将带着大家来认识一下React Native的项目结构。由于之前的项目被我们改动了很多,因此,这里我们重新创建一个项目。 初始化 React Native 工程 自动创建 iOS/Android 工程和对应的JS文件,index.iOS.js,index.android.js 并且通过npm加载package.json里面的依赖库到node_m
Scott_Mr
2018/05/16
1.3K0
iOS-UIWindow详解
1.UIWindow简介 UIWindow是一种特殊的UIView,通常在一个app中至少会有一个UIWindow。 iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的View,最后将控制器的View添加到UIWindow上,于是控制器的View就显示在屏幕上了。 一个iOS程序之所以能显示在屏幕上,完全是因为它有UIWindow,也就是说,没有UIWindow就看不到任何UI界面。 状态栏和键盘都是特殊的UIWindow。 那么UIWindow是如何将View显示到屏幕上的呢
xx_Cc
2018/05/10
2K0
iOS-如何创建一个新的App基础框架
删掉自带的ViewController,并且分别创建Main ViewController View Model
Wilbur-L
2021/09/24
1.2K0
iOS 前台重启应用和清除角标的问题已知条件:问题描述:调试分析解决问题
前台时重启应用调用了applicationWillEnterForeground:
且行且珍惜_iOS
2019/01/03
1.8K0
Hello, SwiftUI
.edgesIgnoringSafeArea(.top)
大话swift
2019/07/04
1.4K0
Hello, SwiftUI
原生iOS嵌入Unity导出的Xcode工程
将classes中main.mm 中的代码复制到项目的main.m中 并把后缀也改为mm 并将
老沙
2019/09/27
2.3K0
iOS多控制器之UINavigationController&UITableBarController1. 多控制器2. UINavigationController3. UITableBarCont
1. 多控制器 一个iOS的app很少只由一个控制器组成,除非这个app极其简单 当app中有多个控制器的时候,我们就需要对这些控制器进行管理 有多个view时,可以用一个大的view去管理1个或者多个小view 控制器也是如此,用1个控制器去管理其他多个控制器 比如,用一个控制器A去管理3个控制器B、C、D 控制器A被称为控制器B、C、D的“父控制器” 控制器B、C、D的被称为控制器A的“子控制器” 为了便于管理控制器,iOS提供了2个比较特殊的控制器: UINavigationControl
stanbai
2018/06/28
1.4K0
相关推荐
iOS13 Scene Delegate
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档