__call()是一个魔术方法,可以处理类内未定义的方法,让浏览器友好输出,对用户友好输出。__call()有两个参数,使用的时候需要传入两个参数,第一个参数是方法名称,第二个参数是包含传递给该方法的参数的所有值。
在php中内置了一些特书的方法,这些特殊方法被称之为魔术方法,其也有特殊的命名规则,以“__”双下划线开头的方法和函数名,所以我们自定义的函数不应该用双下划下开头,目的是为了区分魔术方法。
__construct(), __autoload(),__destruct(), __call(), __callStatic(), __get()
, __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() 和 __debugInfo() 等方法在 PHP 中被称为魔术方法(Magic methods)。在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能。
__call()是一个魔术方法,可以处理类内未定义的方法,让浏览器友好输出,对用户友好输出。__call()有两个参数,使用的时候需要传入两个参数,第一个参数是方法名称,第二个参数是包含传递给该方法的参数的所有值。
public mixed __call ( string $methord , array $arguments )
PHP的魔术方法都是成对出现,所以和__call()成对出现的是__callStatic()方法,在静态上下文中调用一个不可用的方法时会执行这个方法。(PHP 5.3.0 版本以上)
public static mixed __callStatic ( string $methord , array $arguments )
参数 | 描述 |
---|---|
string $methord | 是要调用的方法名。 |
array $arguments | 参数是一个枚举数组,包含着要传递给 $methord 的参数。 |
在这个示例中我们随便构建一个Person类,然后当我们先实例化一个对象然后通过对象调用一个它并不包含的getUser()方法时,就会自动调用类中__call()方法。当我们调用一个这个类中并不存在的静态方法getUser()时,则会自动调用类中__callStatic()方法。
<?php
class Person
{
public function __call($methord, $arguments)
{
// 注意:$methord的值区分大小写
echo "Calling object method '$methord' " . implode(', ', $arguments) . "\n";
}
// PHP 5.3.0之后的版本
public static function __callStatic($methord, $arguments)
{
echo "Calling static method '$methord' " . implode(', ', $arguments) . "\n";
}
}
//实例化类
$obj = new Person;
$obj -> getUser('in object context');
echo "<br/>";
// PHP 5.3.0 版本以后
//使用类名调用静态方法
Person::getUser('in static context');
Calling object method 'getUser' in object context
Calling static method 'getUser' in static context
一个使用场景就是,如果调用一个对象中不存在或被权限控制的方法,不希望给我们处理报错提醒,__call()方法将会被自动调用。比如ThinkPHP3.2 Model.class.php 基类模型中的__call()方法,利用__call方法实现一些特殊的Model方法。
在下面这个示例中,连贯操作的实现、统计查询的实现、根据某个字段获取记录、根据某个字段获取记录的某个值、命名范围的单独调用支持,使用__call()方法,我们就可以实现链式操作。
/**
* 利用__call方法实现一些特殊的Model方法
* @access public
* @param string $method 方法名称
* @param array $args 调用参数
* @return mixed
*/
public function __call($method, $args)
{
if (in_array(strtolower($method), $this->methods, true)) {
// 连贯操作的实现
$this->options[strtolower($method)] = $args[0];
return $this;
} elseif (in_array(strtolower($method), array('count', 'sum', 'min', 'max', 'avg'), true)) {
// 统计查询的实现
$field = isset($args[0]) ? $args[0] : '*';
return $this->getField(strtoupper($method) . '(' . $this->db->parseKey($field, true) . ') AS tp_' . $method);
} elseif (strtolower(substr($method, 0, 5)) == 'getby') {
// 根据某个字段获取记录
$field = parse_name(substr($method, 5));
$where[$field] = $args[0];
var_dump($where);
return $this->where($where)->find();
} elseif (strtolower(substr($method, 0, 10)) == 'getfieldby') {
// 根据某个字段获取记录的某个值
$name = parse_name(substr($method, 10));
$where[$name] = $args[0];
return $this->where($where)->getField($args[1]);
} elseif (isset($this->_scope[$method])) {
// 命名范围的单独调用支持
return $this->scope($method, $args[0]);
} else {
E(__CLASS__ . ':' . $method . L('_METHOD_NOT_EXIST_'));
return;
}
}
下载ThinkPHP3.2,在Home模块中直接使用M()方法查询数据,使用链式调用,Mode.class.php中不存在的方法,将直接调用__call()方法;
首先进行数据库配置:
<?php
return array(
//'配置项'=>'配置值'
'DB_TYPE' => 'mysql', // 数据库类型
'DB_HOST' => 'localhost', // 服务器地址
'DB_NAME' => 'test', // 数据库名
'DB_USER' => 'root', // 用户名
'DB_PWD' => 'root', // 密码
'DB_PORT' => '3306', // 端口
'DB_PREFIX' => '', // 数据库表前缀
);
我们已经有了数据库test,其中存在一个表:demo,直接在Home模块Index控制器中使用M方法链式查询demo表;
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller
{
public function index()
{
$list_name = M('demo')->getByName('小明');//查询name为小明的记录
print_r($list_name);
echo "<br>";
$id_avg = M('demo')->avg('id');//查询id的平均值
print_r($id_avg);
$this->show('<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} body{ background: #fff; font-family: "微软雅黑"; color: #333;font-size:24px} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.8em; font-size: 36px } a,a:hover{color:blue;}</style><div style="padding: 24px 48px;"> <h1>:)</h1><p>欢迎使用 <b>ThinkPHP</b>!</p><br/>版本 V{$Think.version}</div><script type="text/javascript" src="http://ad.topthink.com/Public/static/client.js"></script><thinkad id="ad_55e75dfae343f5a1"></thinkad><script type="text/javascript" src="http://tajs.qq.com/stats?sId=9347272" charset="UTF-8"></script>','utf-8');
}
}
/*
Navicat MySQL Data Transfer
Source Server : localhost
Source Server Version : 50553
Source Host : localhost:3306
Source Database : test
Target Server Type : MYSQL
Target Server Version : 50553
File Encoding : 65001
Date: 2020-09-30 00:53:05
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for demo
-- ----------------------------
DROP TABLE IF EXISTS `demo`;
CREATE TABLE `demo` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`title` varchar(30) NOT NULL COMMENT '标题',
`name` varchar(20) NOT NULL COMMENT '名称',
`message` mediumtext NOT NULL COMMENT '描述',
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '日期',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='注释';
-- ----------------------------
-- Records of demo
-- ----------------------------
INSERT INTO `demo` VALUES ('1', '设计师', '小明', '小明讲课', '2020-09-30 00:08:24');
INSERT INTO `demo` VALUES ('2', '客服', '上飞燕', '飞燕客服', '2020-09-30 00:20:44');
INSERT INTO `demo` VALUES ('3', '前台', '农章霞', '前台小思', '2020-09-30 00:21:42');
INSERT INTO `demo` VALUES ('4', '经理', '胡适', '设计经理', '2020-09-30 00:21:42');
INSERT INTO `demo` VALUES ('5', '研发部门经理', '曹丽', '项目经理', '2020-09-30 00:23:35');
转载注明:
感谢博主,喝杯咖啡~
感谢博主,喝杯咖啡~
还没有人发表评论