======Baza danych======
===== Wyświetlenie powiązań relacyjnych =====
use information_schema;
SELECT `REFERENCED_TABLE_NAME`,`TABLE_NAME`,`DELETE_RULE` FROM `REFERENTIAL_CONSTRAINTS` WHERE `CONSTRAINT_SCHEMA`='nazwa_bazy_danych' ORDER BY `REFERENCED_TABLE_NAME`
===== Sprawdzenie powiązań relacyjnych =====
Jak sprawdzić czy rekord z danej tabeli o identyfikatorze id jest używany w innych tabelach powiązanych relacyjne.\\
Mechanizm przydatny w celu ukrycia np. przycisku usuń jeżeli rekord i tak nie będzie mógł być usunięty.\\
Utworzyłem w **common\models** klasę o nazwie **Pomocnik**
db->dsn, $matches);
$dbname = $matches[1];
$sql = "
SELECT TABLE_NAME, COLUMN_NAME
FROM
information_schema.KEY_COLUMN_USAGE
WHERE
REFERENCED_TABLE_NAME = '{$table_name}'
AND REFERENCED_COLUMN_NAME = 'id'
AND CONSTRAINT_SCHEMA = '{$dbname}';
";
$connection = \Yii::$app->db;
$model = $connection->createCommand($sql);
$lista = $model->queryAll();
foreach ($lista as $element) {
$tabela = $element['TABLE_NAME'];
$col = $element['COLUMN_NAME'];
$sql1 = "SELECT count(*) as `liczba` FROM {$tabela} WHERE `{$col}` = {$id} ";
$model1 = $connection->createCommand($sql1);
$tab = $model1->queryOne();
if ($tab['liczba'] > 0) {
return false;
}
}
return true;
}
}
CheckRelation zwraca wartość true jeśli rekord o identyfikatorze id = $model->id
nie występuje w tabelach powiązanych z tabelą users
W widoku
if(Pomocnik::checkRelation('users',$model->id)){
...
}
===== Sprawdzenie czy rekord można usunąć =====
Funkcja sprawdzająca czy istnieją tabele relacyjne używające id usuwanego rekordu i czy reguła klucza obcego jest ustawiona na RESTRICT. Jeśli jest taki przypadek zwraca false w przeciwnym przypadku true.
Przydatne do wyświetlania lub nie przycisku DELETE.
public function checkDelete($table_name, $id) {
preg_match("/dbname=([^;]*)/", \Yii::$app->db->dsn, $matches);
$dbname = $matches[1];
$sql = "
SELECT TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME
FROM
information_schema.KEY_COLUMN_USAGE
WHERE
REFERENCED_TABLE_NAME = '{$table_name}'
AND REFERENCED_COLUMN_NAME = 'id'
AND CONSTRAINT_SCHEMA = '{$dbname}';
";
$connection = \Yii::$app->db;
$model = $connection->createCommand($sql);
$lista = $model->queryAll();
foreach ($lista as $element) {
$tabela = $element['TABLE_NAME'];
$tabela_ref = $element['REFERENCED_TABLE_NAME'];
$col = $element['COLUMN_NAME'];
$sql1 = "SELECT count(*) as `liczba` FROM {$tabela} WHERE `{$col}` = {$id} ";
$model1 = $connection->createCommand($sql1);
$tab = $model1->queryOne();
if ($tab['liczba'] > 0) {
$sql2 = "
SELECT count(*) as `liczba`
FROM
information_schema.REFERENTIAL_CONSTRAINTS
WHERE
TABLE_NAME = '{$tabela}'
AND REFERENCED_TABLE_NAME = '{$tabela_ref}'
AND DELETE_RULE = 'RESTRICT'
AND CONSTRAINT_SCHEMA = '{$dbname}';
";
$model2 = $connection->createCommand($sql2);
$tab2 = $model2->queryOne();
if ($tab2['liczba'] > 0) {
return false;
}
}
}
return true;
}
W widoku
if(Pomocnik::checkDelete('users',$model->id)){
przycisk USUŃ
}
===== Transakcje =====
Podczas zapisywania danych w kilku modelach jednocześnie zależy nam aby zostały zapisane dane we wszystkich modelach albo wcale.
Służą do tego transakcje.
W kontrolerze:
use yii\db\Transaction;
...
public function actionZapisz(){
...
$transaction = \Yii::$app->db->beginTransaction(
Transaction::SERIALIZABLE
);
try {
...
$model1->save();
...
$model2->save();
$transaction->commit();
} catch (Exception $e) {
$transaction->rollBack();
throw new BadRequestHttpException($e->getMessage(), 0, $e);
}
}
* try - spróbuj wstępnie zapisać
* commit() - próba się udała, zapisz wszystkie modele (zapisz do bazy).
* catch - próba się nie udała. Któregoś z modeli nie można zapisać
* rollBack() - Wycofaj wszystko co zapisano. Przywróć stan bazy danych jaki był przed próbą
----
===== Duplikowanie rekordu =====
Jak zduplikować rekord zmieniając wartości wybranych atrybutów.
W akcji kontrolera:
Tworzymy model istniejącego rekordu
$model = $this->findModel($id);
Modyfikujemy wybrane atrybuty
$model->id = null; // !!! Ważne jeśli id jest PRIMARY i autoincrement
$model->data_zakonczenia = null;
$model->rozpoczecie = date('Y-m-d');
$model->zakonczony = 0;
$model->widoczny = 0;
Ustawiamy parametr informujący, że należy stworzyć nowy rekord
$model->isNewRecord = true;
Zapisujemy model do rekordu
$model->save();