저는 재사용과 단순성을 염두에두고 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();
분명히, 이것은 내가 기대했던 행동이 아닙니다 (실제 행동도 의미가 있지만). 그래서 내 질문은 여러분이 부모 클래스에서 자식 클래스의 이름을 얻는 방법을 알고 있는지 여부입니다.
답변
간단히 말해서. 이건 불가능 해. 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"
답변
정적 컨텍스트 외부에서이 작업을 수행하는 방법을 구상 할 수 있다면 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
달콤한 응?
답변
이 질문이 정말 오래되었다는 것을 알고 있지만 클래스 이름을 포함하는 모든 클래스에서 속성을 정의하는 것보다 더 실용적인 솔루션을 찾는 사람들을 위해 :
이를 위해 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'
그 경우에