이 라이브러리 대신 flightphp/active-record를 사용하는 것이 좋습니다. 이 라이브러리에 대한 추가 개발은 수행되지 않지만 현재로서는 작동합니다.
super model 은 여기저기에 수많은 SQL 코드를 작성하지 않고도 데이터베이스의 테이블과 쉽게 상호 작용할 수 있는 매우 간단한 ORM 유형 PHP 클래스입니다.
이를 증명하기 위해 다음 코드 줄이 있습니다.
$ cloc src/
1 text file.
1 unique file.
0 files ignored.
github.com/AlDanial/cloc v 1.74 T=0.01 s (71.8 files/s, 48768.5 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
PHP 1 86 246 347
-------------------------------------------------------------------------------
이는 성능을 염두에 두고 작성되었습니다. 따라서 지금까지 구축된 모든 프로젝트의 모든 단일 요구 사항을 충족할 수는 없지만 대부분의 경우 작동하며 그에 대한 작업도 수행합니다!
super model 시작하는 것은 쉽습니다. 간단히 super model 클래스를 확장하고 테이블 이름을 정의하면 됩니다. 그게 다야.
<?php
use n0nag0n Super_Model ;
class User extends Super_Model {
protected $ table = ' users ' ;
}
이제 그녀가 일하는 방식에 대한 몇 가지 간단한 예를 들어볼까요?
먼저 다음 표를 가정해 보겠습니다.
Table: users
---------------------------------------------------------
| id | email | company_id |
| 1 | [email protected] | 50 |
| 2 | [email protected] | 61 |
| 3 | [email protected] | 61 |
---------------------------------------------------------
<?php
// somefile.php
$ pdo = new PDO ( ' sqlite::memory: ' , '' , '' , [ PDO :: ATTR_DEFAULT_FETCH_MODE => PDO :: FETCH_ASSOC ]);
$ User = new User ( $ pdo );
// WHERE company_id = 50
$ users = $ User -> getAllBycompany_id ( 50 );
// same as above
$ users = $ User -> getAll ([ ' company_id ' => 50 ]);
쉬운 피지, 레몬 스퀴지 맞죠?
getBy*(mixed $value): array [result]
지정한 값에서 한 행을 다시 반환하는 메서드입니다. 메소드의 *
부분은 데이터베이스의 필드를 나타냅니다. 필드 이름은 데이터베이스 테이블에 있는 필드 이름에 따라 대소문자를 구분합니다.
// get by the id field on the users table
$ User -> getByid ( 3 );
/*
[
'id' => 3,
'email' => '[email protected]',
'company_id' => 61
]
*/
$ User -> getBycompany_id ( 61 );
/*
// it only will pull the first row, not all rows
[
'id' => 2,
'email' => '[email protected]',
'company_id' => 61
]
*/
getAllBy*(mixed $value): array [ [result], [result] ]
주어진 값으로 모든 행을 반환하는 단축 필터입니다. 메소드의 *
부분은 데이터베이스의 필드를 나타냅니다. 필드 이름은 데이터베이스 테이블에 있는 필드 이름에 따라 대소문자를 구분합니다.
// this is pointless, but will still work
$ User -> getAllByid ( 3 );
/*
[
[
'id' => 3,
'email' => '[email protected]',
'company_id' => 61
]
]
*/
$ User -> getAllBycompany_id ( 61 );
/*
[
[
'id' => 2,
'email' => '[email protected]',
'company_id' => 61
],
[
'id' => 3,
'email' => '[email protected]',
'company_id' => 61
]
]
*/
getAll(array $filters, bool $return_one_row = false): array [ [result], [result] ] or [result]
이는 테이블의 데이터를 필터링하기 위해 다양한 사용자 정의를 추가할 수 있는 필터입니다. 알아야 할 몇 가지 고유 키와 특정 데이터를 가져오는 데 도움이 되는 일부 연산자가 있습니다.
// Full example
$ filters = [
//
// arguments in the WHERE statement
//
' some_field ' => 5 , // some_field = ?
' some_field-= ' => 5 , // some_field = ?
' another_field ' => ' IS NULL ' , // some_field IS NULL
' another_field ' => ' IS NOT NULL ' , // some_field IS NOT NULL
' another_field-> ' => ' Apple ' , // another_field > ?
' another_field->= ' => ' Apple ' , // another_field >= ?
' another_field-< ' => ' Apple ' , // another_field < ?
' another_field-<= ' => ' Apple ' , // another_field <= ?
' another_field-!= ' => ' Apple ' , // another_field != ?
' another_field-<> ' => ' Apple ' , // another_field <> ?
' another_field-LIKE ' => ' Ap%ple ' , // another_field LIKE ?
' another_field-NOT LIKE ' => ' Apple% ' , // another_field NOT LIKE ?
' another_field-IN ' => [ ' Apple ' , ' Banana ' , ' Peach ' ], // another_field IN(??) double question mark gets parsed as array
' another_field-NOT IN ' => [ ' Apple ' , ' Banana ' , ' Peach ' ], // another_field NOT IN(??) double question mark gets parsed as array
// If you need some custom action
' another_field-RAW-> DATE_SUB(?, INTERVAL 1 DAY) ' => ' 1980-01-01 ' , // another_field > DATE_SUB(?, INTERVAL 1 DAY)
//
// Other parts of the query
//
// choose what columns you want to select
' select_fields ' => ' id, first_name ' ,
// Get any joins
' joins ' => [ ' LEFT JOIN companies ON companies.id = users.company_id ' ],
// Group by
' group_by ' => ' company_id ' ,
// having
' having ' => ' count > 5 ' ,
// order by
' order_by ' => ' id DESC ' ,
// limit
' limit ' => 15 ,
// offset
' offset ' => 10000 ,
];
$ users = $ User -> getAll ( $ filters );
모델 속성에는 몇 가지 기본 구성 옵션도 있습니다.
항상 작은 결과 집합을 반환하는 모델이 있고 전체 테이블을 쿼리할 수 있기를 원하는 경우 이 속성을 설정하세요. 그렇지 않으면 SQL 매개변수가 제공되지 않은 경우 전체 결과 세트를 다시 검색하지 않도록 보호하는 것입니다(이로 인해 많은 항목이 충돌하고 화상을 입을 수 있음).
use n0nag0n Super_Model ;
class User extends Super_Model {
protected $ table = ' users ' ;
protected $ disallow_wide_open_queries = false ;
}
create(array $data): int [insert id]
이렇게 하면 테이블에 단일 행이 생성되지만 다차원 배열을 제공하면 여러 행이 삽입됩니다. id
의 기본 키가 가정됩니다.
$ User -> create ([ ' email ' => ' [email protected] ' , ' company_id ' => 55 ]);
// returns 4
$ User -> create ([ [ ' email ' => ' [email protected] ' , ' company_id ' => 55 ], [ ' email ' => ' [email protected] ' , ' company_id ' => 56 ] ]);
// returns 6, only the last id will be returned
update(array $data, string $update_field = 'id'): int (number of rows updated)
이렇게 하면 테이블에 단일 행이 생성되지만 다차원 배열을 제공하면 여러 행이 삽입됩니다. id
의 기본 키가 가정됩니다.
$ User -> update ([ ' id ' => 1 , ' email ' => ' [email protected] ' ]);
// returns 1 and will only update the email field
$ User -> update ([ ' email ' => ' [email protected] ' , ' company_id ' => 61 ], ' email ' );
// returns 1
$ User -> update ([ ' company_id ' => 61 , ' email ' => ' [email protected] ' ], ' company_id ' );
// returns 3, not really logical, but it would update all the emails
특정 플래그가 실행될 경우 결과를 자동으로 변경하려면 어떻게 해야 합니까? 쉬워요. 가져오는 모든 결과를 실행하는 processResult()
라는 메서드가 있습니다. $filters['processResults']
키에 이 메서드에 대한 특수 필터를 삽입합니다.
<?php
use n0nag0n Super_Model ;
class User extends Super_Model {
protected $ table = ' users ' ;
public processResult (array $ process_filters , array $ result ): array {
// add some trigger here and do whatever checks you need
if( isset ( $ process_filters ['set_full_name']) && $ process_filters ['set_full_name'] === true && !empty( $ result ['first_name']) && !empty( $ result ['last_name'])) {
$ result ['full_name'] = $ result [ ' first_name ' ]. ' ' . $ result [ ' last_name ' ];
}
return $ result ;
}
}
// later on in some other file.
$ User = new User ( $ pdo );
// setting the processResults filter here is the key to connecting the getAll statement with your processResult method
$ users = $ User -> getAll ([ ' company_id ' => 51 , ' processResults ' => [ ' set_full_name ' => true ] ]);
echo $ users [ 0 ][ ' full_name ' ]; // Bob Smith
이 클래스나 getAll()
필터의 영역에 속하지 않는 매우 복잡한 SQL 쿼리를 수행해야 하는 경우 어떻게 해야 합니까?
이 수업의 요점은 지금까지 존재했거나 앞으로 존재할 모든 프로젝트의 모든 요구 사항을 충족하는 것이 아니라 90% 목표를 달성할 수 있다는 점을 기억하세요. 이를 고려하여 위의 질문을 실행하는 간단한 방법이 있습니다. 일회용으로 RAW SQL을 사용하세요.
<?php
use n0nag0n Super_Model ;
class User extends Super_Model {
protected $ table = ' users ' ;
public function processCrazyKukooQuery ( /* add whatever required fields you need */ ): array {
$ db = $ this -> getDbConnection ();
// shamelessly ripped from StackOverflow
$ statement = $ db -> prepare ( " SELECT
DISTINCT
t.id,
t.tag,
c.title AS Category
FROM
tags2Articles t2a
INNER JOIN tags t ON t.id = t2a.idTag
INNER JOIN categories c ON t.tagCategory = c.id
INNER JOIN (
SELECT
a.id
FROM
articles AS a
JOIN tags2articles AS ta ON a.id=ta.idArticle
JOIN tags AS tsub ON ta.idTag=tsub.id
WHERE
tsub.id IN (12,13,16)
GROUP BY a.id
HAVING COUNT(DISTINCT tsub.id)=3
) asub ON t2a.idArticle = asub.id " );
$ statement -> execute ();
return $ statement -> fetchAll ();
}
}
phpunit
과 phpstan
실행하려면 composer test
실행하기만 하면 됩니다. 현재 100% 적용 범위이며 이를 유지하고 싶습니다.
100% 적용 범위에 대한 참고 사항: 코드의 적용 범위는 100%일 수 있지만 실제 적용 범위는 다릅니다. 목표는 코드에 대해 다양한 시나리오를 테스트하여 코드를 통해 생각하고 예상치 못한 결과를 예상하는 것입니다. 나는 "코드가 실행되었는지" 적용 범위가 아니라 "실제" 적용 범위에 따라 코딩합니다.