Skip to content

Commit 0d83042

Browse files
author
Karel Wintersky
committed
2.2.0
- added Tables repository (implements ArrayAccess)
1 parent 5f0829c commit 0d83042

File tree

3 files changed

+253
-0
lines changed

3 files changed

+253
-0
lines changed

README.TABLES.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
```php
2+
// Скалярный массив - ключи совпадают со значениями
3+
$t1 = new \Arris\Database\Tables(tables: ['a', 'b']);
4+
echo $t1['a']; // выводит: 'a'
5+
echo $t1['b']; // выводит: 'b'
6+
7+
// Ассоциативный массив
8+
$t2 = new TableRepository(tables: ['users' => 'users_table', 'orders' => 'orders_table']);
9+
echo $t2['users']; // выводит: 'users_table'
10+
echo $t2['orders']; // выводит: 'orders_table'
11+
12+
// Добавление таблицы без указания имени - имя равно ключу
13+
$t3 = new TableRepository(prefix: 'prefix_');
14+
$t3->addTable('users'); // tableName = 'users' (автоматически)
15+
$t3->addTable('orders', withPrefix: true); // tableName = 'orders', с префиксом
16+
echo $t3['users']; // выводит: 'users'
17+
echo $t3['orders']; // выводит: 'prefix_orders'
18+
19+
// Добавление таблицы с явным указанием имени
20+
$t4 = new TableRepository();
21+
$t4->addTable('users', 'user_table_name');
22+
echo $t4['users']; // выводит: 'user_table_name'
23+
```
24+
25+
Или, более жизненный пример:
26+
27+
```php
28+
$this->tables = new \Arris\Database\Tables(tables: ['taverns', 'dishes']);
29+
$this->tables
30+
->addTable('users', 'auth_users')
31+
->addTable('auth.confirm', 'auth_users_confirmations')
32+
->addTable('auth.remember','auth_users_remembered')
33+
->addTable( 'auth.resents','auth_users_resets')
34+
->addTable('auth.throttling', 'auth_users_throttling')
35+
->addTable('taverns')
36+
;
37+
38+
// позже, где-то в коде:
39+
40+
$sth = $this->pdo->prepare("SELECT * FROM {$this->tables['users']} WHERE id = ?"); // auth_users (объявлено в addTable)
41+
42+
$sth = $this->pdo->prepare("SELECT * FROM {$this->tables['taverns']} WHERE id = ?"); // taverns (объявлено в конструкторе)
43+
44+
// и так тоже работает:
45+
$sql = "
46+
SELECT d.*, u.email, u.username, t.title AS tavern_title
47+
FROM {$this->tables['dishes']} AS d
48+
LEFT JOIN {$this->tables['taverns']} AS t ON d.tavern_id = t.id
49+
LEFT JOIN {$this->tables['users']} AS u ON d.owner_id = u.id
50+
ORDER BY t.id
51+
";
52+
// хотя можно было бы указать
53+
54+
$this->tables->addTable("taverns", alias: 't'); // и получить при вызове
55+
56+
$sql = "SELECT * FROM {$this->tables['taverns']} WHERE id = ?";
57+
58+
// SELECT * FROM taverns AS t WHERE id = ?
59+
60+
61+
62+
```
63+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Arris\Database;
4+
5+
interface TablesInterface
6+
{
7+
public function __construct(
8+
string $prefix = '',
9+
array $tables = [],
10+
array $havePrefix = [],
11+
array $haveAlias = []
12+
);
13+
14+
public function addTable(
15+
string $key,
16+
?string $tableName = null,
17+
?string $replacement = null,
18+
bool $withPrefix = false,
19+
?string $alias = null
20+
): Tables;
21+
22+
}

sources/Database/Tables.php

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
<?php
2+
3+
namespace Arris\Database;
4+
5+
use InvalidArgumentException;
6+
7+
class Tables implements \ArrayAccess, TablesInterface
8+
{
9+
private string $prefix;
10+
private array $tables;
11+
private array $havePrefix;
12+
private array $haveAlias;
13+
14+
/**
15+
* Инициализируется репозиторий таблиц
16+
*
17+
* @param string $prefix
18+
* @param array $tables
19+
* @param array $havePrefix
20+
* @param array $haveAlias
21+
*/
22+
public function __construct(
23+
string $prefix = '',
24+
array $tables = [],
25+
array $havePrefix = [],
26+
array $haveAlias = []
27+
) {
28+
$this->prefix = $prefix;
29+
$this->tables = $tables;
30+
$this->havePrefix = $havePrefix;
31+
$this->haveAlias = $haveAlias;
32+
33+
// Если в конструктор переданы строки (не ассоциативный массив),
34+
// то каждая строка становится и ключом, и значением
35+
foreach ($tables as $key => $value) {
36+
if (is_int($key)) {
37+
// Это скалярный массив типа ['a', 'b']
38+
$this->addTable($value, $value);
39+
} else {
40+
// Это ассоциативный массив типа ['users' => 'users_table']
41+
$this->addTable($key, $value);
42+
}
43+
}
44+
}
45+
46+
/**
47+
* Добавляет таблицу в репозиторий
48+
*
49+
* @param string $key Ключ для обращения к таблице
50+
* @param string|null $tableName Имя таблицы в БД
51+
* @param string|null $replacement Если задан, будет использовано вместо tableName
52+
* @param bool $withPrefix Добавлять ли префикс (игнорируется если задан replacement)
53+
* @param string|null $alias Алиас для таблицы
54+
* @return Tables
55+
*/
56+
public function addTable(
57+
string $key,
58+
?string $tableName = null,
59+
?string $replacement = null,
60+
bool $withPrefix = false,
61+
?string $alias = null
62+
): self {
63+
if (empty($tableName)) {
64+
$tableName = $key;
65+
}
66+
67+
$this->tables[$key] = $tableName;
68+
69+
if ($replacement !== null) {
70+
$this->havePrefix[$key] = $replacement;
71+
} elseif ($withPrefix) {
72+
$this->havePrefix[] = $key;
73+
}
74+
75+
if ($alias !== null) {
76+
$this->haveAlias[$key] = $alias;
77+
}
78+
79+
return $this; // Для цепочечных вызовов
80+
}
81+
82+
//
83+
84+
/**
85+
* Проверяет, существует ли ключ
86+
* (таблица в репозитории) *
87+
*
88+
* @param mixed $offset
89+
* @return bool
90+
*/
91+
public function offsetExists(mixed $offset): bool
92+
{
93+
return isset($this->tables[$offset]);
94+
}
95+
96+
/**
97+
* Возвращает значение по ключу с учетом логики префиксов и алиасов
98+
*
99+
* @param mixed $offset
100+
* @return string
101+
*/
102+
public function offsetGet(mixed $offset): string
103+
{
104+
if (!$this->offsetExists($offset)) {
105+
throw new InvalidArgumentException("Table '$offset' not found.");
106+
}
107+
108+
$tableName = $this->tables[$offset];
109+
$result = $tableName;
110+
111+
// Если аргумент есть в таблице замен - подставляем значение из have_prefix
112+
if (isset($this->havePrefix[$offset])) {
113+
$result = $this->havePrefix[$offset];
114+
}
115+
// Иначе если есть в таблице have_prefix - ставим префикс
116+
elseif (in_array($offset, $this->havePrefix, true)) {
117+
$result = $this->prefix . $tableName;
118+
}
119+
// Иначе ставим значение ключа (уже в $tableName)
120+
121+
// Если аргумент есть в таблице have_alias - добавляем AS alias
122+
if (isset($this->haveAlias[$offset])) {
123+
$alias = $this->haveAlias[$offset];
124+
$result .= ' AS ' . $alias;
125+
}
126+
127+
return $result;
128+
}
129+
130+
/**
131+
* Устанавливает значение
132+
*
133+
* @param mixed $offset
134+
* @param mixed $value
135+
* @return void
136+
*/
137+
public function offsetSet(mixed $offset, mixed $value): void
138+
{
139+
if (is_null($offset)) {
140+
$this->tables[] = $value;
141+
} else {
142+
$this->tables[$offset] = $value;
143+
}
144+
}
145+
146+
/**
147+
* Удаляет значение по ключу
148+
*
149+
* @param mixed $offset
150+
* @return void
151+
*/
152+
public function offsetUnset(mixed $offset): void
153+
{
154+
unset($this->tables[$offset]);
155+
unset($this->havePrefix[$offset]);
156+
unset($this->haveAlias[$offset]);
157+
158+
// Удаляем из массива скалярных значений, если есть
159+
$key = array_search($offset, $this->havePrefix, true);
160+
if ($key !== false) {
161+
unset($this->havePrefix[$key]);
162+
}
163+
}
164+
165+
166+
}
167+
168+
# -eof- #

0 commit comments

Comments
 (0)