2010-03-17 7 views
11

웹 프로젝트를위한 작은 프레임 워크를 PHP로 작성하므로 새로운 웹 사이트마다 기본 작업을 반복 할 필요가 없습니다. 두 번째 CakePHP 또는 Codeigniter를 만드는 것이 내 목표는 아니며 일반적으로 내가 직접 만든 것들을 사용하는 것처럼 사용 가능한 프레임 워크로 내 웹 사이트를 만들 계획도 아닙니다.PHP에서 일반 데이터베이스 인터페이스 설계하기

핵심 구조, 요청 처리 등과 같은 부분에 대해서는 프레임 워크를 설계하고 코딩하는 데 아무런 문제가 없었지만 모듈에 대한 데이터베이스 인터페이스를 설계하는 데 어려움을 겪고 있습니다.

저는 MVC 패턴을 이미 사용하려고 생각했지만 다소 작은 프로젝트에 과도한 부담이 될 것이라는 것을 알았습니다.

내가 직면 한 정확한 문제는 내 프레임 워크 모듈 (예 : viewCustomers이 모듈 일 수 있음)이 데이터베이스와 상호 작용해야하는 방식입니다.

  • SQL을 PHP 코드에 직접 입력하는 것이 좋습니다. ("옛날 방식"이 되겠습니까 : mysql_query('SELECT firstname, lastname(.....))?

  • 어떻게하면 다음과 같은 쿼리를 추상화 할 수 있습니까?

    $this->db->customers->getBy('id', $x);

    같은

    SELECT firstname, lastname FROM customers WHERE id=X 
    

겠습니까 MySQL은 "도우미"기능은 좋은 생각?

위의 꽤 사소한 것과 같은 더 복잡한 쿼리를 다룰 때 쓸모없는 경향이 있기 때문에 잘 모르겠습니다.

  • MVC의 "모델"패턴이이 문제를 해결할 유일한 방법입니까?

  • 현재 위에 나온 문제를 해결하기 위해 현재 무엇을 사용하고 있습니까?

+2

"... 나는 내가 일반적으로 자신을 창조 한 것을 사용하는 것을 선호한다."... 그 다음에 일할 것이있다. 진지하게. 당신은 당신 자신과 동료들 그리고 고객들에게 큰 호의를 베풀 것입니다. – back2dos

+0

back2dos : 저는 약간 작은 웹 프로젝트를위한 프레임 워크를 만들고 재미 있고 교육적인 목적으로 약간의 프레임 워크를 만들고 있습니다. 내가 이미 모든 것을 만들었고 모든 것이 함께 잘 작동한다면, 왜 지금 어떤 ORM을 강제해야합니까? – lamas

+3

운이 좋다면 기능이 부족한 CakePHP 클론으로 끝날 것입니다. 세상에 필요한 것은 또 다른 PHP 래퍼입니다. 권리. –

답변

3

, 다음 원시 쿼리를 사용 (하지만 당신은 정말 prepared queries와 PDO를 사용한다).

더 많은 OOP를 원한다면, 제안 할 수 있습니다. 도우미와 함께 설계하십시오.

일단, 나는 다음과 같은 개념을 가지고 비슷한 설계했습니다 (서로 다른 데이터베이스와 MySQL과 오라클, 등의 다른 서버에 다중 연결을 처리)

  1. DB 연결/핸들러 클래스를;
  2. 조치 당 클래스 (예 : SELECT, DELETE 등).
  3. 필터 클래스 (예 : RangeFilter);

    $select = new Select('field1', 'field2',); 
    $result = $select->from('myTable') 
           ->addFilter(SQLFilter::RangeFilter, 'field2') 
           ->match(array(1, 3, 5)) 
           ->unmatch(array(15, 34)) 
           ->fetchAll(); 
    

    그것은 당신이 그것을 만들 수있는 방법의 간단한 예입니다 :

코드는 다음과 같은 것을 보았다. 오랜 노력으로 보일 수도 등

당신은 더 나아가 자동화 된 테이블 관계의 처리, (당신의 테이블에 반성을 사용) 필드 유형 검사, 테이블 및 필드 별명의 서포트를 구현하고 있습니다, 그러나 실제로, 당신에게이 모든 기능들을 만들기위한 많은 시간 (약 1 개월)이 소요되지는 않을 것입니다.

2

세 가지 팁 :

  • 를 사용하여 저장 프로 시저 (그래서 당신은 DB에서 PHP를 분리 할 수 ​​있습니다) 준비된 문 CALL NEWS_LIST(?, ?)에 대한
  • 를 사용하여 정적 클래스에 대한
  • 사용 PDO/MySQLi 당신의 DB. 모든 모듈 내에서 액세스 할 수 있습니다.
+2

+1 : PDO, PDO, rah rah rah. PDO, PDO, shish-boom-bah! (죄송합니다, 일에 지루함) – Powerlord

+2

DB 용 정적 클래스를 사용하는 것이 mysql_query를 사용하는 것보다 훨씬 낫지는 않습니다. 전역 가변 객체 (정적 DB 클래스)는 일반적으로 매우 높은 결합 원이기 때문에 나쁜 스타일입니다. – back2dos

+1

높은 커플 링? 나는 이것을 심각하게 의심한다. 저장 프로 시저를 사용하는 정적 사용자 정의 DB 클래스를 사용하면 모듈을 수정하지 않고 기본 데이터베이스 서비스 (mysql, postgres)를 변경하거나 캐싱 (memcache)을 추가 할 수있는 기능을 유지하면서 모든 모듈 사이에서 DB를 활용할 수 있습니다. 따라서 커플 링이 더 낮아집니다. –

5

http://www.doctrine-project.org/ 또는 다른 PHP 프레임 워크 (zend_db가 마음에 들었습니까?)를 보았습니까?

+0

그들이 제작/일하는 방법을 보거나 대신 사용해야하는지 의미합니까? – lamas

+0

을 사용하십시오. 그들을 다시 한번 재발견하는 것은 제 의견으로는 시간 낭비입니다. 개인적으로 나는 젠드 프레임 워크 방식을 정말 좋아합니다. 당신은 자신의 app/frameworks를 작성하지만 특정 작업을 위해 모듈 중 일부를 연결합니다. – roman

+1

문제는 이러한 기억이 얼마나 많은 기억인지입니다. PHP는 요청할 때마다 많은 파일과 클래스를로드 할 수 있도록 만들어지지 않았습니다. 따라서 강력한 서버가 필요하거나 코딩이 쉬운 사이를 선택해야합니다. – Xeoncross

1

Raw SQL은 여전히 ​​나를위한 승자입니다. 그래서 나는 일반적으로 헬퍼 함수에서 벗어나기 위해 (인덱스 사용, 복잡한 JOIN 절 등의 경우) 서버에 보내는 것을 제어하고 싶습니다.

이미 많은 기능을 제공하는 PDO를 사용해야하며 충분하지 않은 경우 실제로 데이터베이스에 쿼리하기 전에 Memcached/APC의 히트 확인과 같은 자체 기능으로 확장 할 수 있습니다.모델에서 여전히 보낼 수 있어야합니다, 물론

function getUser($user_id) { 
    return $this->query("SELECT * FROM users WHERE id = " . (int) $user_id); 
} 

: 당신은 또한 같은 자신의 SQL 함수를 구현하는 클래스를 확장 할 수 있습니다

$this->db->query("SELECT * FROM users WHERE id = " . (int) $user_id); 

과 같은 결과를 얻을. 함수는 단지 지름길로 작동해야하며 확장 된 클래스는 사이트에 따라 달라 지므로 프레임 워크에 포함되어서는 안됩니다.

MVC 패턴은 데이터베이스를 드라이버로만 사용할 수 있으므로 모델에서 필요에 맞게 데이터를 변환 할 수 있으므로이 패턴을 적절하게 적용 할 수 있습니다. 단순한 MVC 구조를 만드는 것이 어렵지 않으며 나중에 MVC를 사용하게됩니다.

+0

데이터베이스 추상화는 좋은 생각이지만 PDO는 단 하나입니다 문제에 접근하는 방법. PHP는 dbx_와 함께 제공됩니다. 그렇다면 ADOdb, ORM, 메타베이스가 있습니다 ... 그러나 나는 SQL 구문을 추상화하려고 시도 할 때 얻는 것이 없으며 많은 부분을 잃을 것에 동의합니다. – symcbean

0

이해 : 데이터베이스 상호 작용은 해결 된 문제입니다.

정말로이 아닌 경우 a) 경험이 있거나 b) OCD이기 때문에 사용할 코드의 모든 문자를 알고 싶다면 기존 솔루션을 선택하십시오. .

PEAR :: MDB2, Zend :: Db, Creole, Doctrine, Propel 등 여러 가지가 있습니다.

+1

나는 특히 ORM을 통해 데이터베이스 상호 작용이 해결 된 문제라고 말하지 않을 것입니다. 모든 ORM이 SQL에서 완전한 추상화를 제공하는 대신 데이터베이스를 직접 질의 할 수 있도록하는 이유입니다. – Anurag

6

나는 당신이 당신의 모듈로부터 당신의 DB에 접근하기를 원한다고 생각한다. 나는 코드에서 직접 mysql_query를 사용하지 않을 것이다. 오히려 추상화 된 DB 액세스로 간단한 모델을 작성하는 것은 쉽고 간단합니다.

예를 들어,이 코드와 모델/Customers.php 같은 파일이있을 수 있습니다 내가 DB 도우미 어떤 종류의 가정입니다

<?php 

class Customers { 

    public function getById($id) { 
     $sql = "SELECT first_name, last_name FROM customers WHERE id='$id'"; 
     $res = $DB::getRow($sql); 
     return ($res); 
    } 
} 

이미 인스턴스화 $ DB로 사용할 수 있습니다. Here은 PDO를 사용하는 간단한 프로그램입니다.

지금, 당신은 당신의 모듈이 포함하고 다음과 같은 방법으로 사용해야합니다

<?php 

include_once "models/Customers.php"; 

$customers = new Customers(); 
$theCustomer = $customers->getById(intval($_REQUEST['cust_id'])); 


echo "Hello " . $theCustomer['first_name'] 

건배.

-4

는 데이터베이스 클래스를 만드는 계획 않는 경우는, 당신이 그것을 생성 /를 선언하지 않고 사용할 수 있도록 그것을 싱글을 만들기로 찾고 생각 될 수있다 ...

global $db; 
$db = new db; 
$db->query ('... sql ...'); 

좀입니다 당신이 할 수있는 경우 중복

db::query ('... sql ...'); 

내가 여러 줄 예를 들어, 하나의 호출에 SQL을 많이 이스케이프하는 데 사용되는 것을 줄이기 위해 근처 정기적으로 사용하는 SQL 함수의 집합이 있습니다

get_element ($table, $element, $value, $column='id'); 
get_row ($table, $value, $column='id'); 

그래서 그냥 테이블 '고객'에서 이름을 얻으려면 ID는 4 어디 :

$name = db::get_element ('customers', 'name', 4); 

또한 당신이 단지는 SQL 문자열 통과 기능 query_element 및 query_row을,이 수반된다 단일 요소/행을 반환합니다.

삽입/업데이트 기능과 함께.

$array = array (
    'name' => 'bob jones', 
    'age' => 28 
); 
$insert_id = db::insert_array ('customers', $array); 

$customer_details = db::get_row ('customers', $insert_id); 

$customer_details['age'] = 30; 

db:update_array ('customers, $customer_details); 

새 행을 만들고 세부 사항을 다시 가져 와서 해당 날짜를 업데이트 한 다음 데이터베이스에 다시 작성하십시오.

테이블 단위로 사용자 지정 SQL 액세스 모듈을 만드는 것은 일반적으로 흔히 저지른 실수입니다. 합리적인 기능을 사용하여 데이터베이스에 대해 포괄적으로 쿼리하는 것이 좋습니다.

복잡한 결합이있는 항목을 사용해야하는 경우 getCustomerInfo()와 같은 함수를 작성하는 것이 가장 좋습니다.하지만 일반적인 표 값 조회 만 수행하면 많은 맞춤법을 사용하면 그들 중 하나의 실수. 플러스 이스케이프 데이터는 매우 중요합니다. 가능한 한 비 SQL을 사용하고 몇 가지 핵심 기능을 통해 퍼갈 수 있다면 모든 것이 제대로 쉽게 이스케이프 처리되는지 확인할 수 있습니다.

내 맞춤 데이터베이스 클래스를보고 싶다면 알려주세요.

+1

싱글 톤은 데이터베이스 클래스를 확장하거나 코드 전체에 클래스 이름을 하드 코딩하기 때문에 다른 곳에서 정보를 가져와야하는 경우 특히 좋지 않습니다. 필요한 경우 데이터베이스 객체를 따라 지나가는 추상 클래스 또는 인터페이스 +가 훨씬 더 좋은 해결책이 될 것입니다. – Andre

0

나는 "도우미 기능"경로에서 벗어났다. 그리고 나를 괴롭혔던 한 가지 점은 동일하거나 유사하거나 기능이없는 기능으로 성장하고 성장한 하나의 파일에서 기능을 계속 추가했다는 것이다. 필자는 라인 수가 600에 달했고 그것이 내 생각에 하나의 파일에 많은 도움이되었다고 생각합니다. 이것은 생각에서 벗어나지 못했지만 나는 다음 트레킹을 위해 더 조직 될 것이다. 아마도 DB 작업 (선택, 삽입 등 ...)에 따라 db 함수를 여러 파일로 분할 할 것입니다.

제 조언은 "도우미 기능"을 시도하고 가능한 한 체계적으로 진행하는 것입니다.

또한 PDO를 처음 사용하여 꽤 좋아했습니다. mysql() 함수와 같은 저급 기술이 아니거나 우리가 언급 할 수는 있지만 부 풀릴 수있는 기술은 아닙니다. PDO를 다시 사용하겠습니다.

1

나처럼 들립니다. http://github.com/Xeoncross/micromvc과 ORM 파일 한 개를 http://github.com/Xeoncross/database에 보았습니까? 내 코드를 파헤 치면 찾고있는 것을 찾을 수있을 것입니다.

해결 방법은 다른 검색어에 대해 ORM 및 쿼리 빌더 (codeigniter의 AR과 같은)를 허용하는 동시에 일부 쿼리의 완전한 원시력을 사용하는 것입니다.

둘 다 좋습니다.

0

이 주제에 대한 많은 의견이있는 것처럼 보입니다. 아직 만족스러운 답변을 찾지 못했지만 현상금이 거의 끝나지 않았기 때문에 마지막 날에 내가 작성한 내용을 작성하게 될 것입니다. 몇 가지 시행 착오 :

나는 싱글 톤 MySQL 클래스를 사용하여 연결과 매우 기본적인 쿼리 및 발생할 수있는 오류를 처리하고 있습니다.

$user = $this->db 
      ->users 
      ->getBy('id', $id); 

$this->db가있는 데이터베이스 추상화 클래스의 인스턴스입니다 /users/show/1 (사용 mod_rewrite와) 같은

단일 페이지 원시 SQL하지만 다음 예제와 같이 작동 경량 ORM의 어떤 종류를 사용하지 않는 __get($tableName) 방법. 정의되지 않은 users 속성에 액세스하면 해당 속성이 트리거됩니다. 나머지는 그 자체를 설명합니다. 쿼리는 getBy()에 전달 된 인수로 구성되며 (SQL 이스케이프도 처리됩니다) 결과는 배열로 반환됩니다.

은 아직 전체 아이디어를 완료하지 않은,하지만 데이터베이스에 새 사용자를 추가하면 다음과 같이 수 :

$user = $this->db 
      ->users 
      ->new; 
$user->id = 2; 
$user->name = 'Joe'; 
$user->save(); 

내가 개념이 정말 완료되지이며, 상기있을 수 있습니다으로 (거대한에게) 그것에 결함. 그러나 평범한 MySQL보다 작성하기 쉽고 유지 관리가 쉽습니다. 전체 "물건"의 다른 좋은 측면은 작기 때문에 다소 빠르고 빠르며 간단합니다.

나는 이것이 이미 존재하는 매우 강력한 ORM 및 프레임 워크와 경쟁 할 수 없다는 것을 알고 있지만 위의 제 의견 중 하나에서 언급 한 몇 가지 이유 때문에 여전히 이것을 만들고 있습니다.

+0

micromvc와 같은 MVC를 사용하면'/ user/show/1'이'$ user = new User ($ id);를 넣을 수있는'User :: show ($ id) {}'를 호출 할 수있게됩니다. – Xeoncross

1

나는 확실한 답을 안다. (나는 그것이 존재한다고 생각하지 않는다.) 그러나 나는 내가 가지고있는 것을 나눌 수 있다고 생각했다. 내가 사용하는 자신의 db '프레임 워크', 가벼운 (현재 ~ 1000 라인) 및 사용하기 쉬운. 내 주요 목표는 SQL의 사용을 단순화하는 것이 아니라 프로그래머 (me :)로부터 '숨기기'위해서였다. 몇 가지 예 : 당신이 속도를해야하는 경우

// row() is 'query' + 'fetch' in one 
$user = $db->row("select * from users where id=25"); 

// the same, injection safe 
$user = $db->row("select * from users where id=?", $_GET['id']); 

// ? placeholders are smart 
$someUsers = $db->rows("select * from users where id IN(?)", array(1, 2, 10)); 

// ...and even smarter 
$data = array('name' => 'Joe', 'age' => 50); 
$id = 222; 
$db->exec("update users set ?a where id=?", $data, $id); 

// 'advanced' fetch functions 
$topNames = $db->vlist("select name from users order by name limit 10"); 
$arrayOfIds = $db->nlist("select id from users where age > 90"); 

// table() returns a Table Gateway 
$db->table('users')->delete('where id=?', 25); 

// yes, this is safe 
$db->table('users')->insert($_POST); 

// find() returns a Row Gateway object 
$db->table('users') 
    ->find('where name=?', 'Joe') 
    ->set('status', 'confirmed') 
    ->save(); 
+0

귀하의 사이트에서 _array 및 기타 비트를 보았을 때 코드의 팬이되었습니다.혹시 위의 내용을 게시 할 가능성이 있습니까? – goat

+0

안녕하세요, 감사합니다. 이것은 진행중인 작업이며, 언제든지 곧 사용할 수있는 코드를 출시 할 수 있다고는 생각하지 않습니다. 구식 버전은 http://code.google.com/p/mria/source/browse/trunk/yo/db.inc.php 에 대한 질문이나 제안 사항이 있으면 알려주십시오. – user187291

관련 문제