조금 소개로 시작하겠습니다. PHP에서 OOP를 배우는 중입니다. 필자는 디자인 패턴을 연구했지만 다른 유형의 개념을 아직 완전히 파악하지 못했습니다. 저는 몇 달에 한 번씩 올바른 방식으로 일을하지 않고 제 스타일을 바꾸어야한다는 것을 알게되었습니다. 매우 실망 스럽습니다. 그러므로 나는 한 번에 모든 일을하는 올바른 방법을 찾고 싶습니다. 나는 완전히 다음과 같은 항목에 대한 유래에 읽을 것을 시도했다 :PHP의 OOP 프로그래밍에서 클래스를 설정하는 올바른 방법은 무엇입니까?
ORM
데이터 매퍼
싱글
을 전역는
필자는 복제본으로 닫지 마십시오. 주제에 관한 거의 모든 질문을 솔직히 조사했지만, 아직 명확히 할 수없는 몇 가지 사실을 알고 싶습니다. 미안하지만 너무 길지만 잘 읽을 수 있도록 정리하려고했습니다!
데이터베이스 클래스의 필수 사항을 게시하여 시작하겠습니다.
Database.php
<?php
class DatabaseMySQL{
private static $dbh;
public function __construct(){
$this->open_connection();
}
public function open_connection(){
if(!self::$dbh){
return (self::$dbh = new PDO(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME, DB_USER,DB_PASSWORD)) ? true : false;
}
return true;
}
public function query($sql, $params=array()){
$this->last_query = $sql;
$stmt = self::$dbh->prepare($sql);
$result = $stmt->execute($params);
return $result ? $stmt : $stmt->errorInfo();
}
public function fetch_all($results, $class_name=''){
return $results->fetchAll(PDO::FETCH_CLASS, $class_name);
}
}
?>
이 내 데이터베이스 클래스 파일입니다. 이 클래스를 사용하면이 클래스에서 원하는만큼 인스턴스를 생성 할 수 있으며 클래스의 정적 속성으로 저장된 인스턴스화 된 PDO 객체를 다시 사용합니다. 또한 PDO를 사용하여 결과 세트에서 데이터를 가져 와서 지정된 클래스의 오브젝트로 데이터를 가져옵니다.
내 다음 파일은 내 모든 클래스가 다른 클래스에서 상속 한 클래스입니다. 나는 그것을 MainModel이라고 불렀다. 이것이 관례를 따르는 지 아닌지 나는 모른다. MainModel.php
<?php
abstract class MainModel{
protected static $table;
public function __construct($array=array()){
$this->assign_known_properties($array);
}
public function assign_known_properties($array){
foreach($array as $key=>$value){
$this->$key = $value;
}
}
public static function find_by_id($id){
$db = new DatabaseMySQL();
self::intialise_table_name();
$id = (int) $id;
$sql = "SELECT * FROM ".static::$table." ";
$sql .= "WHERE id = {$id} ";
$result = self::find_by_sql($sql);
return array_shift($result);
}
public static function find_all(){
$db = new DatabaseMySQL();
self::intialise_table_name();
$sql = "SELECT * FROM ".self::$table." ";
return self::find_by_sql($sql);
}
public static function fetch_as_objects($results){
$db = new DatabaseMySQL();
$called_class = get_called_class();
$results = $db->fetch_all($results, $called_class);
return $results;
}
public static function find_by_sql($sql){
$db = new DatabaseMySQL();
$results = $db->query($sql);
return $results ? self::fetch_as_objects($results) : false;
}
public static function intialise_table_name(){
$called_class = get_called_class();
static::$table = strtolower($called_class).'s';
}
public function get_table_fields(){
self::intialise_table_name();
$sql = "SHOW FIELDS FROM ".static::$table." ";
return self::find_by_sql($sql);
}
public function set_table_details(){
$fields = $this->get_table_fields();
$total = count($fields);
$array = array();
foreach($fields as $object){
$array [] = $object->Field;
}
$this->table_details = array('objects'=>$fields,'array'=>$array,'total'=>$total);
$this->set_placeholders_for_new_record();
$this->set_properties_as_array();
$this->set_properties_as_array(true);
}
public function set_properties_as_array($assoc=false){
$array = array();
if (!$assoc){
foreach($this->table_details['array'] as $field){
if(isset($this->$field)){
$array [] = $this->$field;
}else{
$array [] = NULL;
}
}
$this->table_details['values'] = $array;
}else{
foreach($this->table_details['array'] as $field){
if(isset($this->$field)){
$array[$field] = $this->$field;
}else{
$array [$field] = NULL;
}
}
$this->table_details['assoc_values'] = $array;
}
}
public function set_placeholders_for_new_record(){
$string = '';
for($i=0; $i<$this->table_details['total']; $i++){
$string .= '? ';
if(($i+1) != $this->table_details['total']){
$string .= ", ";
}
}
$this->table_details['placeholders'] = $string;
}
public function create(){
$db = new DatabaseMySQL();
$this->set_table_details();
$sql = "INSERT INTO ".static::$table." ";
$sql .= " VALUES({$this->table_details['placeholders']}) ";
$result = $db->query($sql, $this->table_details['values']);
// If array is returned then there was an error.
return is_array($result) ? $result : $db->insert_id();
}
public function update(){
$db = new DatabaseMySQL();
$this->set_table_details();
$sql = "UPDATE ".static::$table." ";
$sql .= " SET ";
$count = 1;
foreach($this->table_details['array'] as $field){
$sql .= "{$field} = :{$field} ";
if($count < $this->table_details['total']){
$sql .= ", ";
}
$count++;
}
$sql .= " WHERE id = {$this->id} ";
$sql .= " LIMIT 1 ";
$result = $db->query($sql, $this->table_details['assoc_values']);
return $result;
}
public function save(){
return isset($this->id) ? $this->update() : $this->create();
}
}
?>
이 파일을 요약합니다. 호출 된 클래스의 객체를 동적으로 생성하는 find_by_id($int)
과 같은 정적 메서드를 사용합니다. Late Static Bindings를 사용하여 호출 된 클래스의 이름에 액세스합니다. $stmt->fetchAll(PDO::FETCH_CLASS, $class_name)
을 사용하여 이러한 객체를 데이터베이스의 데이터로 인스턴스화하고 객체로 자동 변환합니다.
각 정적 메서드에서 DatabaseMySQL 클래스의 인스턴스를 인스턴스화합니다. 각 정적 메서드에서 클래스 이름을 가져 와서 s
을 추가하여 SQL 쿼리에서 꼼꼼하게 $table
이라는 정적 이름을 사용하도록 설정했습니다. 그래서 내 수업이 User
이라면 테이블 이름은 users
이됩니다.
제 생성자에서 객체가 생성 될 때 객체의 속성으로 일부 변수를 삽입하는 데 사용할 수있는 선택적 배열을 배치했습니다. 이렇게하면 모든 것이 동적으로 완료되어 프로젝트의 마지막 단계가됩니다. 내 상속 수업.
User.php
class User extends MainModel{
}
Question.php
class Question extends MainModel{
}
는 내가 지금하는 것은 간단하다. 다음과 같이 말할 수 있습니다.
$user = new User(array('username'=>'John Doe'));
echo $user->username; // prints *John Doe*
$user->save(); // saves (or updates) the user into the database.
정적 호출로 사용자를 검색 할 수 있습니다. 내 질문에 대한 그래서 지금
$user = User::find_by_id(1);
echo $user->username; // prints users name
:
1)도 하나 전혀) .DATA 매퍼 경우 (이 디자인 패턴라고 부르는 이름은? 의존성 주사? 도메인 모델 (그게 뭐든간에)? 데이터 액세스 레이어?
2)이 구현은 현재 잘 구조화 된 것으로 간주됩니까?
3) 좋으면, 내 코드에서 빠뜨린 이름 지정 규칙이 있습니까?
4) 좋은 것으로 생각되면 특히 좋아하는 부분을 지적 해 주시면 분명히 유지할 부분을 알 수 있습니까?
5) 왜 그렇게 생각하는지 모르겠 으면 자세한 설명이 필요하십니까?
6) 해야하는 내
create
,update
, 내find_by_id
, 정적으로 불리는find_all
와 같은 클래스에있을 실제로 개체를 반환 내 개체의 모든 메소드입니다delete
. 그들이 두 개의 다른 클래스에 있어야한다면 어떻게해야합니까?7)
$load->('UserClass')
을 사용하는 다른 모든 사람들이 왜 매퍼와 같은 기능과 멋진 단어를 사용하지만 아직 한 번 필요하지 않은 이유는 무엇입니까?
이것은 더 맞는 여기에 : http://codereview.stackexchange.com/ –
@IliaRostovtsev 내가 그걸 알았지 만 고마워,하지만 난 여전히 전문가의 답변을 원하고 그들이 주로 여기 있다고 생각합니다! –
No.주제를 읽지 마라. (나는 SO를 첫 번째 참조로 사용하는 것을 꺼린다.) 경험을 쌓고 두려워하지 마십시오.이 질문은 좋은 출발입니다. 흑백이 없음을 알아라. 문맥을 알지 못하지만 전역은 반드시 악의가있는 것은 아니며 오용되면 무서운 것입니다. ORM과 Singleton에 대해서도 마찬가지입니다. 그리고 모든 것이 --- 때로는 우수 사례이지만 항상 최고는 아닙니다. – skytreader