如何防止调用不存在的方法而出错,使用__call魔术重载方法.

__call方法原型如下:
mixed __call(string $name,array $arguments)
当调用一个不可访问的方法(如未定义,或者不可见时), __call()就会被调用.其中$name参数是要调用的方法名称.$arguments参数是一个数组,包含者要传递给方法的参数,
如下所示:

<?php
class HandsonBoy
{
private $name = 'chenqionghe';
private $age = 18;
public function __call($name,$arguments)
{
switch(count($arguments))
{
case 2:
echo $arguments[0] * $arguments[1],PHP_EOL;
break;
case 3:
echo array_sum($arguments),PHP_EOL;
break;
default:
echo '参数不对',PHP_EOL;
break;
}
}
}
$a = new HandsonBoy();
$a->make(5);
$a->make(5,6);
以上代码模拟了类似其他语言中的根据参数类型进行重载.跟__call配套的魔方方法是__callStatic.
当然,使用魔术方法"防止调用不存在的方法面报错",并不是魔术方法的本质.实际上,魔术方法使用方法的动态创建变为可能.这在MVC等框架设计中是很有用的语法.假设一个控制器调用了不存在的方法,那么只要定义了__call魔术方法,就能很友好地处理这种情况.
以下代码通过使用_callStatic这一魔术方法进行方法的动态创建和延迟绑定,实现一个简单的ORM模型

<?php
abstract class ActiveRecord
{
protected static $table;
protected $fieldvalue;
public $select;
static function findById($id)
{
$query = "SELECT * FROM " . static::$table . " WHERE id=$id";
return self::createDomain($query);
}
function __get($fieldname)
{
return $this->fieldvalues[$fieldname];
}
static function __callStatic($method,$args)
{
$field = preg_replace('/^findBy(\w*)$/', '$1' , $method);
$query = "SELECT * FROM " . static::$table . " WHERE $field='$args[0]'";
return self::createDomain($query);
}
private static function createDomain($query)
{
$class = get_called_class();//获取静态方法调用的类名
$domain = new $class();
$domain->fieldvalues = array();
$domain->select = $query;
foreach ($class::$fields as $field => $type)
{
$domain->fieldvalues[$field] = 'TODO:set from sql result by ' . $field;
}
return $domain;
}
}
class Customer extends ActiveRecord
{
protected static $table = 'custdb';
protected static $fields = array(
'id' => 'int',
'email' => 'int',
'lastname' => 'varchar'
);
}
class Sales extends ActiveRecord
{
protected static $table = 'salesdb';
protected static $fields = array(
'id' => 'int',
'item' => 'varchar',
'qty' => 'int'
);
}
var_dump(Customer::findById(123)->select);
var_dump(Customer::findById(123)->email);
var_dump(Sales::findByLastname('Denoncourt')->select);

参考:https://jingyan.baidu.com/article/48a42057fd2890a92425043c.html

转:https://www.cnblogs.com/chenqionghe/p/4735703.html?tvd

参考:http://www.php.net/manual/zh/language.oop5.magic.php

最新文章

  1. shell-script的简单举例
  2. 关于arcgis engine的工作空间(IWorkspace)和选择集(FeatureSelection)
  3. javascript中值传递与值引用的研究
  4. js基础知识点总结
  5. 有关PHP安装,基础学习
  6. Android中如何像 360 一样优雅的杀死后台服务而不启动
  7. Android利用Fiddler进行网络数据抓包,手机抓包工具汇总
  8. javascript权威指南(1)
  9. Linux tomcat部署War包,Linux在Tomcat部署JavaWeb项目,Linux部署War包
  10. 转接口IC ADV7280/ADV7280-M:CVBS转MIPI转接口芯片 10位、4倍过采样标清电视视频解码器,支持去隔行
  11. RAC和单节点数据库的区别有哪些?RAC最有用的功能是什么?
  12. Android之Animation动画各属性的参数意思(二)
  13. vue组件之间的传值方式
  14. 使用HUI-admin过程中,返回上级页面并刷新
  15. web@css样式进阶--图形字体、动画、显隐....
  16. 在Centos7 上安装SVN
  17. oracle 创建表同时添加注释
  18. python内置函数的简单使用和介绍
  19. pthread mutex
  20. MariaDB 表的基本操作(3)

热门文章

  1. Phpstorm-svn配置
  2. sSkinProvider.pas
  3. DN安卓2014版(5-9)
  4. CDHtmlDialog 基本使用
  5. iOS:iOS中的几种动画
  6. PHP之is_a()函数执行代码之总结
  7. 在Ubuntu Server上源码安装OpenERP 8.0,并配置wsgi和nginx运行环境
  8. :视频播放器与Handler 完美调用
  9. Python 爬取汽车领域问答语料(自用)
  10. 【java】Could not find or load main class