Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Query builder w bibliotece do obsługi bazy danych
Forum PHP.pl > Inne > Oceny
czychacz
BoltDB
Pod powyższym linkiem znajduje się kod inicjacyjny dla biblioteki do obsługi bazy danych, którą tworzę. Po co? Żeby poćwiczyć niektóre rzeczy.
Na razie działa tylko budowa prostego SELECTa poprzez klasy Select i SelectAbstract z odpowiednich namespaców.
Chciałbym, żeby ktoś rzucił na to okiem (głównie namespace
Cytat
BoltDb\Engine\Mysql\Query
i
Cytat
BoltDb\Engine\Query
). Od siebie mogę dodać, że prawdopodobnie kiepsko wymyśliłem zależności między interfejsami, traitami i klasami abstrakcyjnymi. Jak Wy byście to widzieli?

//edit: Dodałem prosty tekst Readme

Naprawdę nikt nie ma nic do dodania? Czy może mój kod jest tak sh*towy, że nikt nie chce go przeglądać? brzydal.gif
Pyton_000
Hehe... Dobrze że dałeś tego readma...

Powiem Ci że jakieś to przekombinowane strasznie smile.gif Za chusteczki nie wiedziałbym jak tego używać. Mało intuicyjne.
Zerknij nawet w Laravela jak to mają ogarnięte: https://laravel.com/docs/5.4/queries#selects
czychacz
Widzę tam singletony dla tabel. Zastanawiałem się właśnie nad takim rozwiązaniem, dodając jakąś konfigurację albo automatyczne wykrywanie struktury (kierowałbym się ku konfiguracji, bo automatyka obciążałaby pewnie mocno skrypt). Ale póki co na razie chcę ogarnąć Query Buildera dla co najmniej podstawowych zapytań. Joiny z tego, co widzę, przyjmują mniejszą ilość parametrów, niż u mnie - tu wystarczy nazwa tabeli i warunek, a - jak się domyślam - lista pól uzupełniana jest z automatu lub przez dodanie listy. Ja tego chciałem uniknąć - wymusiłem listę pól (ale można użyć klasy \BoltDb\Query\Expression, by przemycić wildcarda '*'). Zrobiłem tak, ponieważ nie lubię systemów, gdzie jest zbyt dużo automatyki (stąd też podział na fromTable i fromQuery - także join*). Dodatkowo, listy pól przypisane są głównie do tabel lub podzapytań z nimi powiązanych (ale można użyć pól, które nie są z niczym powiązane, po użyciu Select::selectFields()).
Całe skomplikowanie dotyczy chyba właśnie podziału na klasy abstrakcyjne i interfejsy dla obiektów dotyczących pobrania danych - FromTable, FromQuery, JoinTable, JoinQuery - i przyszłych...
markuz
  1. /**
  2.   * @param Connection $connection
  3.   * @dataProvider providerConnection
  4.   */
  5. public function testConnection(Connection $connection)
  6. {
  7. $this->assertInstanceOf(Connection::class, $connection);
  8. }

mellow.gif
viking
Czym to się ma różnic od zend db bo nawet nazwy niektórych klas są identyczne
r4xz
Zdecydowanie popracuj najpierw nad interfejsem, a dopiero potem bierz się za implementację. Dla Ciebie pewnie jest to intuicyjne, ale ja jestem przerażony tym co widzę, a to dopiero zwykły select wink.gif
czychacz
Cytat(viking @ 3.08.2017, 21:24:17 ) *
Czym to się ma różnic od zend db bo nawet nazwy niektórych klas są identyczne

No i chyba na nazwach klas się kończy. Zanim skomentujesz, zajrzyj w kod.
nospor
Jak juz zauwazyl markuz to twoje testy so cudne wink.gif Przekazujesz true i sprawdzasz czy to true. Ciezko o sytuacjie, gdy to nie przejdzie testu wink.gif

Co do klasy: a po co jest to cale Connection? Z przykladu w readme wynika ze do niczego, bo
Najpierw dla connection ustawiam obiekt PDO, ktory sam tworze
$pdo = new PDO('mysql:dbname=my_database;host=127.0.0.1;port=3306', 'username', 'password');
$connection->connect($pdo);

a potem by wykonac query to musze to $pdo, ktore sam ustawilem, pobrac i dopiero moge wykonac query
$result = $connection->getConnection()->query($select->toString());


Czemu poprostu nie moge zrobic
$result = $pdo->query($select->toString());
i ominac to cale $connection?
czychacz
Na chwilę obecną wrzucenie $select->toString() prosto do PDO nie będzie problemem. W sumie jeśli będę kontynuował rozwój tego skryptu to wątpię, żeby w ogóle nim było. Ale obszywanie w klasę Connection miało na celu łatwiejsze zarządzanie później dodanymi klasami (których oczywiście jeszcze nie ma). Na razie mamy tylko BoltDb\Engine\MySql, więc nie ma problemu, ale co, gdy dojdzie np. PostgreSQL? Connection i jego klasy podrzędne miałyby wtedy określić, z jakich zapytań mogę skorzystać, jakich konstrukcji użyć, itp.

Na razie jednak zastanawiam się nad sensem rozwijania tego skryptu - parę osób wspomniało, że jest zbyt skomplikowany.
primosz67
Cześć,

Z góry powiem, że nie patrzyłem w kod i moje rady są na podstawie README.md.

1. Chłopaki mają racje popracuj nad api. Może nawet zacznij od niego.

  1. $connection = new \BoltDb\Connection();
  2. $pdo = new PDO('mysql:dbname=my_database;host=127.0.0.1;port=3306', 'username', 'password');
  3. $connection->connect($pdo);
  4.  
  5.  
  6. $select->fromTable(['alias' => 'name_field', new \BoltDb\Query\Expression('tbl.*')], 'data', 'tbl', 'my_schema');


Staraj się, żeby metoda nie posiadała więcej niż 2 parametry max 3.

  1. $select->joinTable(['other_alias' => 'second_field'], 'sec_table', 'stbl.id = tbl.foreign_id', \BoltDb\Engine\Query\Block\Join\JoinBlock::TYPE_LEFT, 'stbl', 'my_schema');



Zrób fluent

Bolt:ohmy.giff($pdo)
->select(Fields:ohmy.giff())
->from(...)
->joinLeft("")->on("")
->get();

To tylko przykład , ale "you get idea"


  1. $result = $connection->getConnection()->query($select->toString());



Jako uatrakcyjnienie swojej biblioteki mógłbyś zwracać reactive object albo monadę/optional'a.

  1. $result = $select->getResult()
  2.  
  3. $result->cached()
  4.  
  5. ->onSucces(function($rows){
  6.  
  7. })
  8.  
  9. ->onError(function(){
  10. echo "Błąd";
  11. })
  12.  
  13. $resutl->getOrThrowException(new Exception())
czychacz
Metody dot. FROM i JOIN mają obowiązkowo 2 parametry - reszta to opcja.
Fluent wykluczony ze względu na to, że metody dodające bloki FROM i JOIN mają w przyszłości zwracać konfigurowalne bloki.
nospor
Cytat
Metody dot. FROM i JOIN mają obowiązkowo 2 parametry - reszta to opcja.
Acha, czyli jak metoda ma 2 parametry obowiazkowe, a 98 parametrow nieobowiazkowych to wg. ciebie ok? wink.gif
czychacz
A jak inaczej to rozwiązać? Publiczne settery na zwracanych obiektach? Według mnie to jeszcze gorsze niż 6-7 parametrów do fabryki.
primosz67
Cytat(czychacz @ 5.08.2017, 09:32:58 ) *
A jak inaczej to rozwiązać? Publiczne settery na zwracanych obiektach? Według mnie to jeszcze gorsze niż 6-7 parametrów do fabryki.



Według mnie masz parę opcji:

1. Builder

  1. var userTable = Table::of("user")
  2. ->schema("schema")
  3. ->primaryKey("id")
  4.  
  5. $select->jouinTable(Table $userTable, "alias")
  6. ->joinTable($table, "userId")

2.
  1. $select->leftJoinTable("schema.userTable","alias")
  2. ->on("alias.id", "someTable.userId")
  3.  
  4. ->leftJoinTable("schema.games","alias")
  5. >on("alias.id", "someTable.gameId");


Generalnie skłaniam się do builderów i fluentApi bo dużo lepiej się je czyta niż settery. Jak masz więcej 5 - 7 parametrów to lepiej utworzyć 1 albo dwie klasy które przyjmują te parametry zgodnie z ich nazwą. W moim przypadku "Table" - posiada rzeczy dotyczące tabeli (nazwa, schema, klucz główny itd) , parametry dotyczące relacji uzupełniam w metodzie joinTable.
czychacz
Najlepiej byłoby się skłonić ku opcji pierwszej, ale nadal trzeba dodać parametry takie, jak lista pól. W moim założeniu powinno to być pogrupowane, dlatego u mnie jest to parametr metody fromTable/joinTable. W sumie mógłbym operować na obiektach klas zwracanych przez te metody...
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2024 Invision Power Services, Inc.