__call、__set 和 __get的用法

1. __call的用法

PHP5 的对象新增了一个专用方法 __call(),这个方法用来监视一个对象中的其它方法。如果你试着调用一个对象中不存在的方法,__call 方法将会被自动调用。

例:__call

  1. <?php
  2. class foo {
  3. function __call($name,$arguments) {
  4. print("Did you call me? I'm $name!<br>");
  5. print_r($arguments);
  6. print("<br><br>");
  7. }
  8. function doSecond($arguments)
  9. {
  10. print("Right, $arguments!<br>");
  11. }
  12. }
  13. $test = new foo();
  14. $test->doFirst('no this function');
  15. $test->doSecond('this function exist');
  16. ?>

2. __call 实现“过载”动作

这个特殊的方法可以被用来实现“过载(overloading)”的动作,这样你就可以检查你的参数并且通过调用一个私有的方法来传递参数。

例:使用 __call 实现“过载”动作

  1. <?php
  2. class Magic {
  3. function __call($name,$arguments) {
  4. if($name=='foo') {
  5. if(is_int($arguments[0])) $this->foo_for_int($arguments[0]);
  6. if(is_string($arguments[0])) $this->foo_for_string($arguments[0]);
  7. }
  8. }
  9. private function foo_for_int($x) {
  10. print("oh an int!");
  11. }
  12. private function foo_for_string($x) {
  13. print("oh a string!");
  14. }
  15. }
  16. $test = new Magic();
  17. $test->foo(3);
  18. $test->foo("3");
  19. ?>

3.  面向对象重载

  1. <?php
  2. /*__call(string $name,array $arg)的用法
  3. *当调用一个不可访问的方法的时候调用$name是方法名称 $arg是个数组包含要传递给方法的参数
  4. */
  5. class Account{
  6. private $user=1;
  7. private $pwd=2;
  8. public function __call($name,$arg){
  9. switch(count($arg)){
  10. case 2:
  11. echo $arg[0]*$arg[1],PHP_EOL;
  12. break;
  13. case 3:
  14. echo array_sum($arg),PHP_EOL;
  15. break;
  16. default:
  17. echo "参数不对",PHP_EOL;
  18. break;
  19. }
  20. }
  21. }
  22. $a= new Account();
  23. //这里模拟了重载
  24. //重载:一个类中可以定义参数列表不同但名字相同的多个方法
  25. $a->make(5);
  26. $a->make(5,6);

4. 使用__call()方法来实现数据库连贯操作

  1. <?php
  2. // 使用__call()方法来实现数据库连贯操作
  3. // 申明一个Db类(数据库操作类)的简单操作模型
  4. class Db{
  5. private $sql = array(
  6. "field" => "",
  7. "where" => "",
  8. "order" => "",
  9. "limit" => "",
  10. "group" => "",
  11. "having" => "",
  12. );
  13. // 连贯操作调用field() where() order() limit() group() having()方法,组合sql语句
  14. function __call($methodName,$args){
  15. // 将第一个参数(代表不存在方法的方法名称),全部转成小写方式,获取方法名称
  16. $methodName = strtolower($methodName);
  17. // 如果调用的方法名和成员属性数组$sql下标对应上,则将第二个参数给数组中下标对应的元素
  18. if(array_key_exists($methodName,$this->sql)){
  19. $this->sql[$methodName] = $args[0];
  20. }else{
  21. echo '调用类'.get_class($this).'中的方法'.$methodName.'()不存在';
  22. }
  23. // 返回自己对象,则可以继续调用本对象中的方法,形成连贯操作
  24. return $this;
  25. }
  26. // 输出连贯操作后组合的一个sql语句,是连贯操作最后的一个方法
  27. function select(){
  28. echo "SELECT {$this->sql['field']} FROM  user {$this->sql['where']} {$this->sql['order']} {$this->sql['limit']} {$this->sql['group']}
  29. {$this->sql['having']}";
  30. }
  31. }
  32. $db = new Db();
  33. // 连贯操作
  34. $db->field('sex, count(sex)')
  35. ->where('where sex in ("男","女")')
  36. ->group('group by sex')
  37. ->having('having avg(age) > 25')
  38. ->select();
  39. ?>

5.  __set 和 __get的用法

这是一个很棒的方法,__set 和 __get 方法可以用来捕获一个对象中不存在的变量和方法。

例: __set 和 __get

  1. <?php
  2. class foo {
  3. function __set($name,$val) {
  4. print("Hello, you tried to put $val in $name<br>");
  5. }
  6. function __get($name) {
  7. print("Hey you asked for $name<br>");
  8. }
  9. }
  10. $test = new foo();
  11. $test->__set('name','justcoding');
  12. $test->__get('name');
  13. ?>
上一篇:HOOK相关原理与例子


下一篇:day08 跟着太白老师学python 文件操作