Groups | Search | Server Info | Keyboard shortcuts | Login | Register
Groups > pl.comp.lang.php > #16233
| From | Marek S <precz@spamowi.com> |
|---|---|
| Newsgroups | pl.comp.lang.php |
| Subject | Jak korzystać z Doctrine + PostgreSQL? |
| Date | 2019-06-09 21:44 +0200 |
| Organization | ATMAN - ATM S.A. |
| Message-ID | <qdjnif$e2l$1@node2.news.atman.pl> (permalink) |
Witam,
Zabieram się do mojego pierwszego projektu w Symfony 4. Chcę zmienić
swój sposób myślenia i zacząć korzystać z ORM - w tym przypadku
Doctrine. Póki co jestem na etapie postrzegania Doctrine jako rzucanie
kłód pod nogi. To co było banalne w SQL, tu wymaga gimnastyki, a i tak
kwiatki wychodzą. Zapewne czegoś nie wiem. Oto moje problemy:
Założenia.
Jest baza PostgreSQL. Dla testów tworzymy banalną tabelę, którą w SQL
opisałbym jako:
CREATE TABLE public.task
(
task_id BIGSERIAL,
title varchar(255) NOT NULL,
status boolean NOT NULL
)
Czynności
1. Próbowałem podejścia Database First aby nie marnować czasu na
zmaganie się z ORMem. Niestety wszędzie piszą (zawsze nie wprost), że
Doctrine przestaje to wspierać:
https://symfony.com/doc/4.0/doctrine/reverse_engineering.html
https://github.com/symfony/symfony-docs/issues/9172
"Symfony is a different project than Doctrine and we don't have any
control over those decisions."
2. Ok, zatem pozostaje używać durnego narzędzia do kreowania tabel w
postaci console make:entity. Wprowadzenie w ten sposób np. 100 pól
bezbłędnie, graniczy z szaleństwem. A i tak narzędzie nie uwzględnia np.
wartości domyślnych, nazwy klucza głównego i mnóstwa innych rzeczy więc
ręcznie trzeba modyfikować klasę.
Jak sobie radzicie z tworzeniem tabel w bazie, aby było to przynajmniej
tak proste, jak SQL i współgrało z Doctrine?
3. Na początek zbudowałem tabelkę jak w przykładzie powyżej, wpisując
pole po polu w powyższym narzędziu. Oczywiście były potrzebne zmiany w
klasie Task, bo kreator potrafi tylko zarys tabeli zbudować. Encja
wygląda tak:
/**
* @ORM\Entity(repositoryClass="App\Repository\TaskRepository")
*/
class Task {
/**
* @ORM\Id()
* @ORM\GeneratedValue(strategy="IDENTITY")
* @ORM\Column(type="bigint", name="task_id")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $title;
/**
* @ORM\Column(type="boolean", options={"default": false})
*/
private $status=false;
public function getId(): ?int {
return $this->id;
}
public function getTitle(): ?string {
return $this->title;
}
public function setTitle(string $title): self {
$this->title = $title;
return $this;
}
public function getStatus(): ?bool {
return $this->status;
}
public function setStatus(?bool $status): self {
$this->status = $status;
return $this;
}
}
Ręcznie musiałem zmienić:
* @ORM\GeneratedValue(strategy="IDENTITY")
* @ORM\Column(type="bigint", name="task_id")
i dopisać wartości domyślne pól poprzez zainicjowanie zmiennych
prywatnych oraz uczynić to powtórnie zaklęciem
@ORM\Column(type="boolean", options={"default": false})
Niesłychanie łatwo o błędy. Np. zmienię domyślną wartość w klasie, ale
nie powtórzę tego w opcjach "default". Modyfikacji jest mnóstwo przy
realnej wielkości tabeli.
Czy jest jakiś sposób usprawnienia kreowania tabeli?
3. Podczas rozmów tutaj, dowiedziałem się, że ORM zapewnia mi
przenaszalność między bazami danych. Patrzę zatem w migrację i widzę:
$this->abortIf($this->connection->getDatabasePlatform()->getName() !==
'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('CREATE TABLE task (task_id BIGSERIAL NOT NULL,
title VARCHAR(255) NOT NULL, status BOOLEAN DEFAULT \'false\' NOT NULL,
PRIMARY KEY(task_id))');
Mimo iż nie używam żadnych specjalnych typów pól, to powyższy kod nie
wykona się dla baz innych niż PostgreSQL. Zatem jak jest z Doctrine? Da
się przenosić struktury między typami baz, czy nie? Bo ja widzę, że nie.
4. Po wygenerowaniu pierwszej migracji, znalazłem kolejny kwiatek: żadna
metoda "down" nie wykona się. Powstanie błąd SQL i koniec działania. Oto
zawartość metody:
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to
your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !==
'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('CREATE SCHEMA public');
$this->addSql('CREATE SCHEMA exclude');
$this->addSql('CREATE SCHEMA exc');
$this->addSql('DROP TABLE task');
}
Nie wykona się linia:
$this->addSql('CREATE SCHEMA public');
...bo nie można tworzyć przestrzeni nazw, która jest już utworzona. Bez
sensu zapis. Podobnie z kolejnymi przestrzeniami. DROP TABLE nie wykona
się wskutek w/w błędu.
Dosłownie błąd na błędzie jest w Doctrine. Na Stacku ludzie też żalą się
na to już od 2016 roku. Na DBALu iest issue od paru lat na ten temat.
Jak zacząć korzystać z Doctrine skoro już na wejściu katastrofa? Czy
tylko ja tak mam?
--
Pozdrawiam,
Marek
Back to pl.comp.lang.php | Previous | Next — Next in thread | Find similar
Jak korzystać z Doctrine + PostgreSQL? Marek S <precz@spamowi.com> - 2019-06-09 21:44 +0200 Re: Jak korzystać z Doctrine + PostgreSQL? Marek S <precz@spamowi.com> - 2019-06-18 21:18 +0200
csiph-web