このライブラリの代わりに、flightphp/active-record を使用することを強くお勧めします。このライブラリではこれ以上の開発は行われませんが、現時点ではそのまま動作します。
super model非常にシンプルな ORM タイプの PHP クラスで、大量の SQL コードをあちこちに記述することなく、データベース内のテーブルと簡単に対話できます。
それを証明するために、次のコード行を示します。
$ 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]
指定した値から1行戻すメソッドです。メソッドの*
の部分は、データベース内のフィールドを参照します。フィールド名は、データベース テーブル上のフィールド名に関係なく、大文字と小文字が区別されます。
// 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]
これによりテーブルに 1 行が作成されますが、多次元配列を指定すると複数の行が挿入されます。 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)
これによりテーブルに 1 行が作成されますが、多次元配列を指定すると複数の行が挿入されます。 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% である場合がありますが、実際のカバレッジは異なります。目標は、コードに対してさまざまなシナリオをテストして、コードを徹底的に検討し、予期しない結果を予測することです。 「コードが実行されたかどうか」カバレッジではなく、「実際の」カバレッジに対してコーディングを行っています。