É altamente recomendado que você use flightphp/active-record em vez desta biblioteca. Nenhum desenvolvimento adicional será feito com esta biblioteca, mas ela funciona como está agora.
super model é uma classe php do tipo ORM muito simples para interagir facilmente com tabelas em um banco de dados sem escrever uma tonelada de código SQL em todo o lugar.
Para provar isso, aqui estão as linhas de código...
$ 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
-------------------------------------------------------------------------------
Isso foi escrito com o desempenho em mente. Portanto, embora não satisfaça todos os requisitos de todos os projetos já construídos, ele funcionará na maioria dos casos e também fará um excelente trabalho!
Começar com super model é fácil, basta estender a classe super model e definir um nome de tabela. É isso.
<?php
use n0nag0n Super_Model ;
class User extends Super_Model {
protected $ table = ' users ' ;
}
Agora, que tal alguns exemplos simples de como ela funciona?
Primeiro, vamos supor a seguinte tabela:
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 ]);
Fácil, espremedor de limão, certo?
getBy*(mixed $value): array [result]
Este é um método que retorna uma linha do valor especificado. A parte *
do método refere-se a um campo no banco de dados. O nome do campo diferencia maiúsculas de minúsculas de qualquer nome de campo na tabela do banco de dados.
// 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] ]
Este é um filtro de atalho para retornar todas as linhas por um determinado valor. A parte *
do método refere-se a um campo no banco de dados. O nome do campo diferencia maiúsculas de minúsculas de qualquer nome de campo na tabela do banco de dados.
// 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]
Este é o filtro onde você pode adicionar várias personalizações para filtrar os dados da sua tabela. Existem algumas chaves exclusivas que você deve conhecer e alguns operadores para ajudá-lo a extrair seus dados específicos.
// 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 );
Existem também algumas opções básicas de configuração com as propriedades do modelo.
Se você tiver um modelo que sempre retornará um pequeno conjunto de resultados e quiser poder consultar a tabela inteira, defina esta propriedade. Caso contrário, é uma proteção para que, se nenhum parâmetro sql fosse fornecido, você não recuperasse todo o conjunto de resultados (o que poderia travar e queimar muitas coisas).
use n0nag0n Super_Model ;
class User extends Super_Model {
protected $ table = ' users ' ;
protected $ disallow_wide_open_queries = false ;
}
create(array $data): int [insert id]
Isso criará uma única linha na tabela, mas se você fornecer uma matriz multidimensional, várias linhas serão inseridas. Uma chave primária de id
é assumida.
$ 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)
Isso criará uma única linha na tabela, mas se você fornecer uma matriz multidimensional, várias linhas serão inseridas. Uma chave primária de id
é assumida.
$ 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
E se você quiser uma maneira automatizada de alterar seu resultado se um sinalizador específico for acionado? Fácil. Existe um método chamado processResult()
que executará cada resultado obtido. Você injeta filtros especiais para este método na chave $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
E se você precisar fazer uma consulta SQL complexa e maluca que não se enquadra no domínio desta classe ou nos filtros getAll()
?
Lembre-se de que o objetivo desta aula NÃO é satisfazer todos os requisitos de todos os projetos que já existiram ou existirão, mas você alcançará 90% do caminho até lá. Diante disso, existe uma maneira simples de executar a questão acima. Basta usar RAW SQL para você.
<?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 ();
}
}
Basta executar composer test
para executar phpunit
e phpstan
. Atualmente com 100% de cobertura e é onde gostaria de mantê-la.
Uma observação sobre cobertura de 100%: embora o código possa ter cobertura de 100%, a cobertura real é diferente. O objetivo é testar muitos cenários diferentes em relação ao código para pensar no código e antecipar resultados inesperados. Eu codifico para cobertura "real", não para cobertura "o código foi executado".