Bagaimana saya bisa mendapatkan nama kelas dari panggilan statis di kelas PHP diperpanjang?

93

Saya memiliki dua kelas: Actiondan MyAction. Yang terakhir dinyatakan sebagai:

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

Yang saya butuhkan hanyalah metode di Actionkelas (hanya di dalamnya, karena akan ada banyak kelas yang diwariskan, dan saya tidak ingin menerapkan metode ini di semua kelas), yang akan mengembalikan nama kelas dari panggilan statis. Inilah yang saya bicarakan:

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

Dan saat saya menyebutnya:

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

Tetapi setiap deklarasi di kelas induk memiliki akses hanya ke __CLASS__variabel kelas induk , yang memiliki nilai "Tindakan".

Apakah ada cara yang mungkin untuk melakukan ini?

Anton
sumber

Jawaban:

176

__CLASS__selalu mengembalikan nama kelas tempat ia digunakan, jadi tidak banyak membantu dengan metode statis. Jika metode ini tidak statis Anda bisa menggunakan get_class ($ this). misalnya

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

}

class MyAction extends Action {

}

$foo=new MyAction;

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

Binding statis terlambat, tersedia dalam PHP 5.3+

Sekarang PHP 5.3 dirilis, Anda dapat menggunakan binding statis terbaru , yang memungkinkan Anda menyelesaikan kelas target untuk panggilan metode statis pada waktu proses, bukan saat ditentukan.

Meskipun fitur ini tidak memperkenalkan konstanta ajaib baru untuk memberi tahu Anda nama kelas tempat Anda dipanggil, fitur ini menyediakan fungsi baru, get_called_class () yang dapat memberi tahu Anda nama kelas tempat metode statis dipanggil. Berikut ini contohnya:

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


class MyAction extends Action {

}


echo MyAction::n(); //displays MyAction
Paul Dixon
sumber
Satu-satunya masalah untuk OP adalah fitur tersebut belum tersedia. PHP 5.3 masih dalam versi beta.
Ionuț G. Stan
3
@Paul, terima kasih! Anda baru saja menyelamatkan hari ... atau malam saya dengan get_called_class():)
Marecky
1
Saya berharap seseorang dapat membantu saya dengan masalah serupa . Skrip PHP mati secara diam-diam setelah dijalankan new static();dari dalam metode statis pribadi (menggunakan xampp di windows dan php> 5.5). :s
Stphane
$ foo = MyAction baru; echo get_class ($ foo); Ini juga mencetak MyAction.
sammry
42

Sejak 5.5 Anda dapat menggunakan classkata kunci untuk resolusi nama kelas , yang akan jauh lebih cepat daripada membuat panggilan fungsi. Juga berfungsi dengan antarmuka.

// 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
Ian Bytchek
sumber
16

Ini bukan solusi ideal, tetapi berfungsi pada PHP <5.3.0.

Kode tersebut disalin dari 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();
    }
}
Jrgns
sumber
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();
Lulu
sumber
0

Tidak ada cara, dalam versi PHP yang tersedia, untuk melakukan apa yang Anda inginkan. Solusi Paul Dixon adalah satu-satunya. Maksud saya, contoh kode, karena fitur binding statis terakhir yang dia bicarakan tersedia mulai PHP 5.3, yang dalam versi beta.

Ionuț G. Stan
sumber
0

(PHP 5> = 5.3.0, PHP 7)
get_called_class - Nama kelas "Late Static Binding"

<?php

class Model
{
  public static function find()
  {
    return get_called_class();
  }
}

class User extends Model
{
}


echo User::find();

link ini mungkin bisa membantu

Biswajit Biswas
sumber