ฉันจะรับชื่อคลาสจากการเรียกแบบคงที่ในคลาส PHP เพิ่มเติมได้อย่างไร


93

ฉันมีสองคลาส: ActionและMyAction. หลังถูกประกาศเป็น:

class MyAction extends Action {/* some methods here */}

สิ่งที่ฉันต้องการคือเมธอดในActionคลาส (เฉพาะในนั้นเนื่องจากจะมีคลาสที่สืบทอดมาจำนวนมากและฉันไม่ต้องการใช้เมธอดนี้ในทุกคลาส) ซึ่งจะส่งคืนชื่อคลาสจากการเรียกแบบคงที่ นี่คือสิ่งที่ฉันกำลังพูดถึง:

Class Action {
 function n(){/* something */}
}

และเมื่อฉันเรียกมันว่า:

MyAction::n(); // it should return "MyAction"

แต่การประกาศแต่ละครั้งในคลาสพาเรนต์มีสิทธิ์เข้าถึงเฉพาะ__CLASS__ตัวแปรคลาสพาเรนต์ซึ่งมีค่า“ Action”

มีวิธีใดบ้างที่เป็นไปได้ในการดำเนินการนี้

คำตอบ:


176

__CLASS__ส่งคืนชื่อของคลาสที่ใช้อยู่เสมอดังนั้นจึงไม่ได้ช่วยอะไรมากนักสำหรับวิธีการคงที่ หากวิธีนี้ไม่คงที่คุณสามารถใช้get_class ($ this) ได้ เช่น

class Action {
    public function n(){
        echo get_class($this);
    }

}

class MyAction extends Action {

}

$foo=new MyAction;

$foo->n(); //displays 'MyAction'

การผูกแบบคงที่ในช่วงปลายมีให้ใน PHP 5.3+

ตอนนี้ PHP 5.3 เปิดตัวแล้วคุณสามารถใช้การโยงแบบคงที่ในช่วงปลายซึ่งช่วยให้คุณสามารถแก้ไขคลาสเป้าหมายสำหรับการเรียกเมธอดแบบคงที่ที่รันไทม์แทนที่จะกำหนดไว้

แม้ว่าคุณลักษณะนี้จะไม่แนะนำค่าคงที่เวทย์มนตร์ใหม่เพื่อบอกชื่อคลาสที่คุณถูกเรียกใช้ แต่ก็มีฟังก์ชันใหม่get_called_class ()ซึ่งสามารถบอกชื่อคลาสที่มีการเรียกเมธอดแบบคงที่นี่คือตัวอย่าง:

Class Action {
    public static function n() {
        return get_called_class();
    }
}


class MyAction extends Action {

}


echo MyAction::n(); //displays MyAction

ปัญหาเดียวสำหรับ OP คือฟีเจอร์ยังไม่พร้อมใช้งาน PHP 5.3 ยังอยู่ในรุ่นเบต้า
Ionuț G. Stan

3
@ พอลขอบคุณ! คุณเพิ่งบันทึกวัน ... หรือคืนของฉันด้วยget_called_class():)
Marecky

1
ความปรารถนาของคนที่ผมสามารถช่วยฉันกับปัญหาที่คล้ายกัน สคริปต์ PHP ตายอย่างเงียบ ๆ เมื่อดำเนินการnew static();จากภายในวิธีการคงที่ส่วนตัว (ใช้ xampp บน windows และ php> 5.5) :s
Stphane

$ foo = MyAction ใหม่; เสียงสะท้อน get_class ($ foo); นอกจากนี้ยังพิมพ์ MyAction
sammry

42

ตั้งแต่ 5.5 คุณสามารถใช้classคำสำคัญสำหรับการแก้ปัญหาชื่อคลาสซึ่งจะเร็วกว่าการเรียกใช้ฟังก์ชันมาก ยังใช้งานได้กับอินเทอร์เฟซ

// C extends B extends A

static::class  // MyNamespace\ClassC when run in A
self::class    // MyNamespace\ClassA when run in A
parent::class  // MyNamespace\ClassB when run in C
MyClass::class // MyNamespace\MyClass

16

ไม่ใช่ทางออกที่ดี แต่ใช้ได้กับ PHP <5.3.0

คัดลอกรหัสมาจากsepturo.com

if(!function_exists('get_called_class')) {
    class class_tools {
        static $i = 0;
        static $fl = null;

        static function get_called_class() {
            $bt = debug_backtrace();

            if (self::$fl == $bt[2]['file'].$bt[2]['line']) {
                self::$i++;
            } else {
                self::$i = 0;
                self::$fl = $bt[2]['file'].$bt[2]['line'];
            }

            $lines = file($bt[2]['file']);

            preg_match_all('/([a-zA-Z0-9\_]+)::'.$bt[2]['function'].'/',
                $lines[$bt[2]['line']-1],
                $matches);

            return $matches[1][self::$i];
        }
    }

    function get_called_class() {
        return class_tools::get_called_class();
    }
}


2
class MainSingleton { 
  private static $instances = array(); 
  private static function get_called_class() {
    $t = debug_backtrace();
    return $t[count($t)-1]["class"];
  }  

  public static function getInstance() { 
    $class = self::get_called_class();
    if(!isset(self::$instances[$class]) ) { 
      self::$instances[$class] = new $class; 
    } 
    return self::$instances[$class]; 
  } 

}

class Singleton extends MainSingleton { 
  public static function getInstance()
  {
    return parent::getInstance();
  }     
  protected function __construct() { 
    echo "A". PHP_EOL; 
  } 

  protected function __clone() {} 

  public function test() { 
    echo " * test called * "; 
  } 
} 

Singleton::getInstance()->test(); 
Singleton::getInstance()->test();

0

ไม่มีวิธีใดในเวอร์ชัน PHP ที่มีให้ทำในสิ่งที่คุณต้องการ วิธีแก้ปัญหาของ Paul Dixon มีเพียงหนึ่งเดียว ฉันหมายถึงตัวอย่างโค้ดเนื่องจากคุณลักษณะการผูกแบบคงที่ตอนปลายที่เขาพูดถึงนั้นมีให้ใน PHP 5.3 ซึ่งอยู่ในรุ่นเบต้า


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.