2010-07-08 4 views
0

__get() 마법 메서드의 기능을 구현할 수있는 방법이 있는지 알아보고 새 클래스를 인스턴스화하려고합니다.클래스를 인스턴스화하는 것과 동일한 __get 마법 메서드가 있습니까?

내 목표는

$foo = new Cat();

은 궁극적으로 일반 객체의 생성을 초래할 것입니다 즉

new Mammal('Cat');$foo 클래스 Mammal의 인스턴스가 될 것 같은 것을

, 호출 된 클래스 이름 ('Cat')은 Mammal의 생성자에 인수로 전달됩니다.


참고 : 는 리튬이나 CakePHP를 잘 알고 사람들을 위해 내가 염두에두고 최종 게임, 각각의 다른 데이터베이스 테이블 클래스의 전체 무리를 정의 할 필요가 없도록하는 것입니다. 만약 내가했다면, 대부분은 비어있을 것이고, 기본적인 CRUD 작업은 모두 필요한 것입니다. 게다가 모든 것을 포함하고 클래스 정의는 오버 헤드에 대해 큰 것이 될 수 없습니다. 내 생각은 단일 "모델"클래스를 사용하여 대부분의 일반 함수를 처리하는 것입니다. 특정 데이터베이스 테이블에 대해 고급 기능이 필요한 경우 항상 하위 클래스를 만들 수 있습니다.

답변

2

클래스 인스턴스화 메커니즘으로 원하는 것을 달성하기 위해 직접적인 비 해킹 방법이 없다고 생각합니다.

나는 공장을 사용하는 것이 좋습니다 것입니다 :

$tableFactory->createTable('Cat'); 

을 한 후 무대 뒤에서 무엇을 수행해야하는지 것이다. Cat이 자체 클래스를 필요로한다고 결정한 경우에도 이점을 얻을 수 있습니다. 단순히 팩토리를 수정할 수 있으며이를 사용하는 코드를 수정할 필요가 없습니다. 존재하지 않는 경우, 다음 실존로 평가 후면,

+0

이것은 분명히 효과가 있으며 내 유일한 해결책 일 수 있습니다. 나는 "new Cat();"이라고 쓸 수 있기를 바랬습니다. 가독성을 위해 필수적이지는 않습니다. 그래도 멋질 것입니다 ... –

+0

'TableFactory :: createTable ('Cat');'. 그렇지 않으면 좋은 대답은 공장 패턴이 여기에 사용할 수 있습니다. – Pete

0

글쎄, 그것은 조금 해키,하지만 당신은, 그래서 class autoloader ...

을 남용 클래스 "고양이"를 확인하는 로더를 가로 챌 수 당신이 ... 게다가이 작업을 수행 할 수있는 클래스, 그것은 장점을 가지고 ...

if (!$foundClass) { 

    $code = 'Class '.$class.' extends Mammal { 
     public function __construct() { parent::__construct("'.$class.'");} 
    }'; 
    eval($code); 
} 

나는 그것을 해키했다 ...하지만 당신은 화이트리스트 항상 수있는 당신은 클래스를 수정하기를 원한다면 , 그것의 확고한 예를 만드십시오.

하지만 다시 한 번 개인적으로 다른 해결책을 발견하게됩니다. 나에게 new Cat()은 전혀 읽을 수 없습니다. 그것은 두 가지 이유 때문입니다. 처음에는 문맥에 대한 단서가없고 두 번째로 클래스 고양이를 찾을 수 없습니다 ... 제가하는 일은 Jani가 제안한 것과 유사합니다 : $table = DatabaseTable::getInstance('cat'); ... 나는 훨씬 더 읽기 쉽습니다. (더 많은 문자 임에도 불구하고) ...

0

내가 Cake에서 기억하는 방법은 컨트롤러 클래스 위에 모델을 정의한 다음 $ this-> Modelname을 사용하는 것입니다. 이것은로 구현하는 간단해야한다 : 속성 이름이 배열 $ 용도에 그렇다면 존재하는 경우, 클래스 확인 할

public function __get($prop) 
{ 
    if(in_array($prop, $this->uses)) { 
     return new $prop; 
    } 
} 

가 아닌 기존 속성을 호출 할 때마다, 가정 $ 소품은 클래스 이름과 그것을 instaniates.인스턴스를 가져올 때마다 다시 인스턴스화하지 않도록 인스턴스를 어딘가에 저장하는 것이 좋습니다.

이것은 다른 곳에서 Klass를 교환하기가 어렵 기 때문에 new Klass을 작성하는 것보다 다소 깨끗합니다. 그것을 컨트롤러에 하드 와이어합니다. 당신이 피하고 싶어하는 의존성입니다. 그렇게 말하면, Symfony Dependency Injection framework을보고 싶을 것입니다.

0

저는 이것이 지금은 오래된 질문이지만 많은 사람들에게 여전히 관련이 있음을 알고 있습니다.

이 정확한 시나리오를 극복하는 나의 방법은 모든 기본 테이블 상호 작용을 유지하는 기본 모델링하는 것입니다

:

<?php 
    class person extends base { 
     public function table_name() { 
      return "person"; 
     } 
    } 

    class car extends base { 
     public function table_name() { 
      return "car"; 
     } 
    } 
?> 

:

<?php 
    class base { 

     /** 
     * @name  $table_values 
     * @description This holds all data about the table including the field names and data for the record loaded. 
     * @example  { 
     *     "primary_keys" : [], 
     *     "table_data" : { 
     *           "name" : "value", 
     *           "name" : "value" 
     *          } 
     *    } 
     */ 
     private $table_values = array(); 

     /** 
     * @name  __get 
     * @param  $name The name of the property to return. 
     * @description The PHP magic getter. 
     */ 
     public function __get($name) { 
      $keys = array_keys($this->table_values['table_data']); 
      if (in_array($name, $keys)) { 
       return $this->table_values['table_data'][$name]; 
      } 
     } 

     /** 
     * @name  __set 
     * @param  $name The name of the property to set. 
     * @param  $value The value to assign to the property. 
     * @description The PHP magic setter. 
     */ 
     public function __set($name, $value) { 
      $this->table_values['table_data'][$name] = $value 
     } 

     /** 
     * @name  table_name 
     * @description Must override in child class. Should return the name of the table to use. 
     */ 
     public function table_name() {} 

     /** 
     * @name  load 
     * @param  $ids int|array Can be a single primary key or an assoc array of primary keys depending on the table with the keys for the array being the field names. 
     * @description This method handles loading a single record from the table and storing it as a PHP object. 
     */ 
     public function load($ids) { 
      // Use the primary key(s) to find and load the record into $table_values from the database. 
     } 

     /** 
     * @name  save 
     * @description Saves the record in the database 
     public function save() { 
      // Use the primary key(s) to find and either insert or update the database table record. 
     } 
    } 
?> 

과 같이 기본 클래스를 사용을 클래스를 자동으로로드하고 테이블에 대한 클래스가없는 경우 처리하기 위해 자동 로더 및 자동 로더 사용 :

<?php 
    spl_autoload_register(function($class_name) { 
     $filename = "/path/to/class/{$class_name}.php"; 
     if (class_exists($class_name)) { 
      // Do nothing. 
     } elesif (file_exists($filename)) { 
      require_once($filename); 
     } else { 
      // Check if the class name exists in the database as a table. 
      if ($database->table_exists($class_name)) { 
       $class_def = " 
class {$class_name} extends base { 
    public function table_name() { 
     return \"{$class_name}\"; 
    } 
}"; 
       eval($class_def); 
      } 
     } 
    }); 
?> 

기본 클래스는 훨씬 더 많은 기능을 가질 수 있습니다. 또한로드 및 저장 전후 작업을 수행하고 예를 들어 동일한 데이터로 중복 레코드를 확인하기 위해 하위에서 재정의 할 수있는 함수가 있습니다.

관련 문제