부모 클래스의 자식 클래스 이름 가져오기(정적 컨텍스트)
재사용과 심플함을 염두에 두고 ORM 라이브러리를 구축하고 있습니다.어처구니없는 상속 제한에 얽매인 것 이외에는 모든 것이 정상입니다.아래 코드를 고려해 주십시오.
class BaseModel {
/*
* Return an instance of a Model from the database.
*/
static public function get (/* varargs */) {
// 1. Notice we want an instance of User
$class = get_class(parent); // value: bool(false)
$class = get_class(self); // value: bool(false)
$class = get_class(); // value: string(9) "BaseModel"
$class = __CLASS__; // value: string(9) "BaseModel"
// 2. Query the database with id
$row = get_row_from_db_as_array(func_get_args());
// 3. Return the filled instance
$obj = new $class();
$obj->data = $row;
return $obj;
}
}
class User extends BaseModel {
protected $table = 'users';
protected $fields = array('id', 'name');
protected $primary_keys = array('id');
}
class Section extends BaseModel {
// [...]
}
$my_user = User::get(3);
$my_user->name = 'Jean';
$other_user = User::get(24);
$other_user->name = 'Paul';
$my_user->save();
$other_user->save();
$my_section = Section::get('apropos');
$my_section->delete();
확실히, 이것은 내가 예상한 행동이 아닙니다(실제 행동도 일리가 있지만).그래서 제 질문은 부모 수업에서 자녀 수업의 이름을 얻는 방법을 알고 계시냐는 것입니다.
정적 컨텍스트 밖에서 이를 수행할 수 있는 방법을 생각해 낼 수 있다면 PHP 5.3을 기다릴 필요가 없습니다.php 5.2.9에서는 부모 클래스의 비정적 메서드에서 다음을 수행할 수 있습니다.
get_class($this);
그러면 자 클래스의 이름이 문자열로 반환됩니다.
예.
class Parent() {
function __construct() {
echo 'Parent class: ' . get_class() . "\n" . 'Child class: ' . get_class($this);
}
}
class Child() {
function __construct() {
parent::construct();
}
}
$x = new Child();
다음과 같이 출력됩니다.
Parent class: Parent
Child class: Child
귀엽지?
한마디로 이건 불가능해요php4에서 당신은 끔찍한 해킹을 구현할 수 있다.debug_backtrace()
PHP5에서는 이 메서드는 동작하지 않습니다.참조:
edit: PHP 5.3의 레이트 스태틱바인딩의 예(댓글에 기재되어 있습니다.현재 구현(src)에 잠재적인 문제가 있음을 유의하십시오.
class Base {
public static function whoAmI() {
return get_called_class();
}
}
class User extends Base {}
print Base::whoAmI(); // prints "Base"
print User::whoAmI(); // prints "User"
이 질문이 매우 오래된 것은 알지만 클래스 이름을 포함하는 모든 클래스에서 속성을 정의하는 것보다 더 실용적인 해결책을 찾고 있는 사용자에게는 다음과 같습니다.
를 사용할 수 있습니다.static
키워드를 지정합니다.
php 문서의 이 기여자 메모에서 설명한 바와 같이
그
static
슈퍼 클래스 내에서 키워드를 사용하면 메서드가 호출되는 서브 클래스에 액세스할 수 있습니다.
예:
class Base
{
public static function init() // Initializes a new instance of the static class
{
return new static();
}
public static function getClass() // Get static class
{
return static::class;
}
public function getStaticClass() // Non-static function to get static class
{
return static::class;
}
}
class Child extends Base
{
}
$child = Child::init(); // Initializes a new instance of the Child class
// Output:
var_dump($child); // object(Child)#1 (0) {}
echo $child->getStaticClass(); // Child
echo Child::getClass(); // Child
오래된 게시물은 알고 있지만 제가 찾은 솔루션을 공유하고 싶습니다.
PHP 7+로 테스트 완료함수 사용get_class()
링크
<?php
abstract class bar {
public function __construct()
{
var_dump(get_class($this));
var_dump(get_class());
}
}
class foo extends bar {
}
new foo;
?>
위의 예는 다음과 같습니다.
string(3) "foo"
string(3) "bar"
get_called_class()를 사용하지 않는 경우 다른 레이트 스태틱바인딩 트릭(PHP 5.3+)을 사용할 수 있습니다.단, 이 경우 모든 모델에 getClass() 메서드가 필요합니다.IMO는 별거 아니야
<?php
class Base
{
public static function find($id)
{
$table = static::$_table;
$class = static::getClass();
// $data = find_row_data_somehow($table, $id);
$data = array('table' => $table, 'id' => $id);
return new $class($data);
}
public function __construct($data)
{
echo get_class($this) . ': ' . print_r($data, true) . PHP_EOL;
}
}
class User extends Base
{
protected static $_table = 'users';
public static function getClass()
{
return __CLASS__;
}
}
class Image extends Base
{
protected static $_table = 'images';
public static function getClass()
{
return __CLASS__;
}
}
$user = User::find(1); // User: Array ([table] => users [id] => 1)
$image = Image::find(5); // Image: Array ([table] => images [id] => 5)
공장 패턴으로 싱글톤 패턴을 사용하려고 하는 것 같습니다.저는 당신의 디자인 결정을 평가하는 것을 추천합니다.싱글톤이 정말 적절하다면 상속이 바람직하지 않은 정적 방법만 사용할 것을 권장합니다.
class BaseModel
{
public function get () {
echo get_class($this);
}
public static function instance () {
static $Instance;
if ($Instance === null) {
$Instance = new self;
}
return $Instance;
}
}
class User
extends BaseModel
{
public static function instance () {
static $Instance;
if ($Instance === null) {
$Instance = new self;
}
return $Instance;
}
}
class SpecialUser
extends User
{
public static function instance () {
static $Instance;
if ($Instance === null) {
$Instance = new self;
}
return $Instance;
}
}
BaseModel::instance()->get(); // value: BaseModel
User::instance()->get(); // value: User
SpecialUser::instance()->get(); // value: SpecialUser
이것이 실제로 질문에 대한 답변은 아닐 수 있지만 유형을 지정하는 get()에 파라미터를 추가할 수 있습니다.그럼 전화하시면 됩니다.
BaseModel::get('User', 1);
User::get()을 호출하지 않습니다.BaseModel::get()에 로직을 추가하여 get 메서드가 서브클래스에 존재하는지 확인하고 서브클래스로 덮어쓰기를 허용할 경우 해당 메서드를 호출할 수 있습니다.
그렇지 않으면 내가 생각할 수 있는 유일한 방법은 각 서브클래스에 내용을 추가하는 것입니다.그것은 어리석은 것입니다.
class BaseModel {
public static function get() {
$args = func_get_args();
$className = array_shift($args);
//do stuff
echo $className;
print_r($args);
}
}
class User extends BaseModel {
public static function get() {
$params = func_get_args();
array_unshift($params, __CLASS__);
return call_user_func_array( array(get_parent_class(__CLASS__), 'get'), $params);
}
}
User::get(1);
하위 수 , 로 대체될 수 있습니다.get_parent_class(__CLASS__)
'BaseModel'
문제는 언어의 제한이 아니라 당신의 디자인입니다.이치노정적 메서드는 객체 지향 설계가 아닌 절차적 설계를 따릅니다.get_row_from_db_as_array()
데이터베이스를 찾을 수 있는 장소를 알고 있습니까?그리고 마지막으로 유닛 테스트가 매우 어려워 보입니다.
이 선에 따라 뭔가를 시도해 보세요.
$db = new DatabaseConnection('dsn to database...');
$userTable = new UserTable($db);
$user = $userTable->get(24);
Preston의 답변에는 두 가지 변형이 있습니다.
1)
class Base
{
public static function find($id)
{
$table = static::$_table;
$class = static::$_class;
$data = array('table' => $table, 'id' => $id);
return new $class($data);
}
}
class User extends Base
{
public static $_class = 'User';
}
2)
class Base
{
public static function _find($class, $id)
{
$table = static::$_table;
$data = array('table' => $table, 'id' => $id);
return new $class($data);
}
}
class User extends Base
{
public static function find($id)
{
return self::_find(get_class($this), $id);
}
}
주의: 자산명을 _로 시작하는 것은 기본적으로 "이것을 공표한 것을 알고 있지만, 실제로 보호되어야 했지만, 그렇게 하지 못하고 목표를 달성할 수 없었다"는 의미입니다.
하면 .class_basename($this)
됩니다.
언급URL : https://stackoverflow.com/questions/283004/getting-the-name-of-a-child-class-in-the-parent-class-static-context
'programing' 카테고리의 다른 글
오류: (23, 17) 해결 실패: junit: junit: 4.12 (0) | 2023.01.25 |
---|---|
빈 어레이를 생성하여 NumPy에 추가하는 방법은 무엇입니까? (0) | 2023.01.25 |
jQuery가 비동기 Ajax 요청이 아닌 동기 Ajax 요청을 수행하도록 하려면 어떻게 해야 합니까? (0) | 2023.01.15 |
두 개체를 자세히 비교할 수 있는 Java 유틸리티가 있습니까? (0) | 2023.01.15 |
변수 이름을 문자열로 가져오기 (0) | 2023.01.15 |