Ako Milan strávil týždeň bláznivých nápadov
MySQL QueryBuilder pre Profesiu
Motivácia
public function verziaA()
{
$query = 'select id, title from article where is_published = 1';
if ($this->shouldDisplayDate) {
// potrebujem do zoznamu fieldov pridať stĺpec date_published
}
return $this->databaseManager->fetchAll($query);
}
public function verziaB()
{
$fields = ['id', 'title'];
$query = 'from article where is_published = 1';
if ($this->shouldDisplayDate) {
$fields[] = 'date_published';
}
return $this->databaseManager->fetchAll(
'select '
. implode(', ', $fields) . ' '
. $query
);
}
Motivácia 2
public function heredocSyntax()
{
$query = <<<SQL
select
id, title
from
article
where
is_published = 1
SQL;
return $this->databaseManager->fetchAll($query);
}
Motivácia 3
public function whereIn($ids)
{
$query = 'select * from article where id ' . QueryUtils::in($ids);
return $this->databaseManager->fetchAll($query);
}
Môj cieľ
- vytvoriť query builder pre select, insert, update, delete dotazy
- urobiť nový spôsob escapovania premenných a pritom ponechať možnosť bindovania
- umožniť zadávanie where podmienok pomocou poľa
Výsledok 1. cieľa
Máme QueryBuilder pre SELECT
Máme QueryBuilder pre INSERT
Nestihol som UPDATE a DELETE
SelectQueryBuilder
$query = $this->databaseManager->select('a.id, a.title')
->select('a.date_published')
->from('article')->as('a')
->where('a.is_published = 1')
->where('a.is_approved = 1')
->orderBy('a.date_published desc');
if ($showAuthors) {
$query->select('u.firstname, u.lastname');
$query->join('users')->as('u')->on('u.id = a.user_id');
}
$result = $this->databaseManager->fetchAll($query);
InsertQueryBuilder
$query = $this->databaseManager->insertInto('article', [
'title' => 'Lorem Ipsum',
'user_id' => 7,
]);
$this->databaseManager->query($query);
$query = $this->databaseManager->insertInto('article', [
[
'title' => 'Lorem Ipsum',
'user_id' => 7,
],
[
'title' => 'Star Trek Ipsum',
'user_id' => 42,
],
]);
$this->databaseManager->query($query);
InsertQueryBuilder
$query = $this->databaseManager->insertInto('article')
->set('title', 'Lorem Ipsum');
$query->set('user_id', 7);
$this->databaseManager->query($query);
$query = $this->databaseManager->insertInto('article', [
'title' = 'Lorem Ipsum',
'slug' => 'lorem-ipsum',
]);
$query->onDuplicateKeyUpdate(
"slug = concat(values(slug), '-', values(id))"
);
InsertQueryBuilder
$query = $this->databaseManager->insertInto('article')
->values(['title' => 'Lorem Ipsum']);
if ($insertMore) {
$query->values(['title' => 'Star Trek Ipsum']);
}
if ($insertEvenMore) {
$query->values([
[
'title' => 'Star Wars Ipsum',
],
[
'title' => 'Firefly Ipsum',
],
]);
}
$this->databaseManager->query($query);
Výsledok 2. cieľa
Ostalo zachované doterajšie bindovanie premenných
Pridaný nový spôsob escapovania na spôsob printf
Doterajšie bindovanie premenných
$query = $this->databaseManager->select('id, title')
->from('article')
->where('user_id = :userId')
->where('slug = :slug');
$this->databaseManager->fetchAll($query, [
'userId' => $user->getId(),
'slug' => $request->query->get('slug'),
]);
Escapovanie na spôsob printf
$query = $this->databaseManager->select('id, title')
->from('article')
->where('user_id = %i', $user->getId())
->where('slug = %s', $request->query->get('slug'));
$query->where(
'is_published = %i and published_at >= %dt',
$isPublished,
new \DateTime('2018-09-01 00:00:00')
);
$manager->insertInto('article', [
'title%s' => $title,
'user_id%i' => $userId,
'published_at%dt' => new \DateTime(),
]);
Escapovanie na spôsob printf
Existujúce modifikátory:
%i | integer |
%f | float |
%s | string (berie do úvahy PDO pripojenie, encoding atď) |
%d | dátum (string alebo DateTime) |
%dt | dátum a čas (string alebo DateTime) |
%sql | žiadne escapovanie (vhodné pre neštandardné query) |
%% | percento (napr. pre like dotazy) |
Výsledok 3. cieľa
Prvá skvelá vec:
$query->where([
'is_published' => 1,
'user_id%in' => [4, 5, 6],
]);
// where
// is_published = 1
// and user_id in (4, 5, 6)
Výsledok 3. cieľa
Druhá skvelá vec
$query->where('%or', [
'is_published' => 1,
'user_id%in' => [4, 5, 6],
'%and' => [
'is_published' => 0,
'user_id' => 7,
]
]);
// where
// is_published = 1
// or user_id in (4, 5, 6)
// or (is_published = 0 and user_id = 7)
Ani jedna sa mi nepodarila
Zdrojáky
- samostatná knižnica
- do Profesie sa nainštaluje cez composer (nestihol som)
- git repo: https://git.profesia.sk/library/query-builder
Ďakujem za pozornosť
MySQL QueryBuilder
By Milan Herda
MySQL QueryBuilder
- 607