Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ Frameworki _ [SF][SF2][Symfony2] proste sprawy związane z architekturą

Napisany przez: Foxx 12.10.2013, 13:00:24

Pytanie 1.
Załóżmy, że chciałbym sprawdzić czy produkt jest w schowku, chciałbym użyć funkcji {% if product.inClipboard %} w twigu.
Sprawdzanie polega na zbadaniu tablicy umieszczonej w sesji. Gdzie powinna się znajdować deklaracja tej funkcji? Encja wydaje mi się niewłaściwa bo potrzebuję dostępu do sesji i nie ma to nic wspólnego z bazą danych (o ile to jest kryterium). A więc repozytorium? Ale wtedy trzeba napisać trochę kodu żeby móc użyć tej funkcji w szablonach.

Pytanie 2.
Podobna sytuacja, produkt jest w relacji z encją "galeria", która jest w relacji z encją "zdjęcie".
Potrzebne jest {% product.getMainImage %} w twigu. Gdzie powinna się znajdować deklaracja tej funkcji? Różnica polega na tym, że ustalenie main image polega na pobraniu pierwszego ze zdjęć w przypiętej galerii więc jest to tylko manipulacja bazą danych.


Napisany przez: pedro84 12.10.2013, 13:36:38

1. Jak dla mnie: repozytorium + funkcja Twig. Sorry, głupota wink.gif
2. Chcesz sprawdzić czy kolekcja relacji pomiędzy obiektami jest pusta? Do tego nie potrzebujesz nic specjalnego. Jeśli coś innego, to patrz punkt 1 wink.gif

Napisany przez: Foxx 12.10.2013, 13:43:21

Dzięki:)

Napisany przez: destroyerr 12.10.2013, 18:09:52

Ad. 1
Absolutnie nie repozytorium. Przecież musisz w takim wypadku dodać do repozytorium zależność od sesji. Moim zdaniem jest to zadanie dla obiektu schowek.

Ad. 2
Jeśli do produktu jest przypisana tylko jedna galeria to ja proponowałbym główne zdjęcie pobierać getterem właśnie z galerii.

Napisany przez: Foxx 12.10.2013, 18:25:09

Ad. 1 Rozumiem, ale chyba nie masz na myśli tworzenia encji w Entity/ prawda? To by oznaczało niepotrzebne tworzenie tabeli w bazie no i w sumie wróciłbym do punktu wyjścia i równie dobrze mógłbym tą obsługę wrzucić do encji produkt. Więc podejrzewam, że masz na myśli coś innego. Może to przegapiam, ale w dokumentacji nie znalazłem o tym informacji, ale w różnych zewnętrznych bundlach trafiam na katalog "Model" na równi z "Entity" i może chodzi o to? Jeżeli tak to czy jest gdzieś jakaś dokumentacja na ten temat? Kiedy tych klas używać, gdzie inicjować obiekty?

Napisany przez: pedro84 12.10.2013, 19:25:01

Cytat(destroyerr @ 12.10.2013, 19:09:52 ) *
Ad. 1
Absolutnie nie repozytorium. Przecież musisz w takim wypadku dodać do repozytorium zależność od sesji. Moim zdaniem jest to zadanie dla obiektu schowek.

I co w tym złego? Jeśli potrzebujesz w repozytorium dostęp do jakiegoś serwisu to w jaki sposób go obejdziesz? Z drugiej strony, to nie jest w żaden sposób powiązane z bazą, więc repozytorium lepiej zostawić.

Cytat(Foxx @ 12.10.2013, 19:25:09 ) *
Ad. 1 Rozumiem, ale chyba nie masz na myśli tworzenia encji w Entity/ prawda? To by oznaczało niepotrzebne tworzenie tabeli w bazie no i w sumie wróciłbym do punktu wyjścia i równie dobrze mógłbym tą obsługę wrzucić do encji produkt. Więc podejrzewam, że masz na myśli coś innego. Może to przegapiam, ale w dokumentacji nie znalazłem o tym informacji, ale w różnych zewnętrznych bundlach trafiam na katalog "Model" na równi z "Entity" i może chodzi o to? Jeżeli tak to czy jest gdzieś jakaś dokumentacja na ten temat? Kiedy tych klas używać, gdzie inicjować obiekty?

@destroyerr'owi chodziło zapewne o to, żeby taka funkcjonalność była zawarta w klasie obsługującej schowek, czyli de facto samym obiekcie schowka.

Napisany przez: Foxx 12.10.2013, 19:51:38

Cytat(pedro84 @ 12.10.2013, 20:25:01 ) *
@destroyerr'owi chodziło zapewne o to, żeby taka funkcjonalność była zawarta w klasie obsługującej schowek, czyli de facto samym obiekcie schowka.


Ale rzecz w tym, że właśnie nie mam obiektu schowka, stąd ten przykład - schowek jest niezwiązany z bazą bo polega tylko na obsługiwaniu sesji. W związku z tym tworzenie encji, z której powstanie tabela wydaje się trochę nadmiarowe.

Napisany przez: pedro84 12.10.2013, 19:53:51

Cytat(Foxx @ 12.10.2013, 20:51:38 ) *
Ale rzecz w tym, że właśnie nie mam obiektu schowka, stąd ten przykład - schowek jest niezwiązany z bazą bo polega tylko na obsługiwaniu sesji. W związku z tym tworzenie encji, z której powstanie tabela wydaje się trochę nadmiarowe.

Ale nikt nie mówi o tworzeniu encji. Mówimy o obiekcie schowka, za pomocą którego tymże manipulujesz. W jaki sposób dodajesz elementy do schowka?

Napisany przez: Foxx 12.10.2013, 20:02:35

Trzymam tablicę w sesji i pobieram ją w kontrolerze z sesji, modyfikuję i zapisuję do sesji ponownie czyli operuję na tablicy.

A jak mogę stworzyć obiekt schowka nie w postaci encji?

Napisany przez: pedro84 12.10.2013, 20:06:19

Cytat(Foxx @ 12.10.2013, 21:02:35 ) *
A jak mogę stworzyć obiekt schowka nie w postaci encji?

Po prostu: tworzysz sobie klasę, np. CartManager, w niej definiujesz wszystkie potrzebne Ci składowe. Tworzysz serwis w SF2, wstrzykujesz sobie wszystkie zależności i już. Taka manipulacja jest o wiele lepsza niż to co robisz do tej pory.

Dodatkowo, jak wspomniałem w pierwszym poście, tworzysz sobie funkcję Twiga, do której wstrzykujesz swój serwis schowka i voila wink.gif

Napisany przez: Foxx 12.10.2013, 20:09:35

A gdzie jest odpowiednia lokalizacja dla takiej klasy?

Napisany przez: pedro84 12.10.2013, 20:14:21

Oczywiście w odpowiednim bundlu, np. AppBundle\Cart\CartManager, ale to tylko przykład. SF2 naprawdę daje Ci elastyczność.

BTW. Czytaj dokumentację do poduszki wink.gif

Napisany przez: Foxx 12.10.2013, 20:27:48

Ale ja mam już Bundle i ten koszyk działa tylko wewnątrz niego i jest to malutka funkcja, nie ma chyba sensu tworzyć specjalnie dla niego osobnego Bundla. Obecnie moje pytanie brzmi do jakiego katalogu mam wrzucić klasę Cart.php bo raczej nie jest to Entities/ - czy mam sobie stworzyć dowolnie jakiś katalog? Np. MyClasses?

Napisany przez: pedro84 12.10.2013, 20:53:51

Napisałem Ci już wyżej, AppBundle to nazwa Twojego bundla. Nie mówię, żebyś do samego koszyka tworzył bundle (ale w sumie, czemu nie? wink.gif). Katalog MyClasses jest bez sensu, nazywaj katalogi i klasy rozsądnie i opisowo.

Napisany przez: Foxx 12.10.2013, 21:38:50

Sorry, nie doczytałem nazwy bundla.

Czyli mogę sobie zrobić dowolny katalog wewnątrz bundla na "luźne" klasy i nie ma żadnego wyspecjalizowanego na to tak jak np. Entity/ albo Form/ są wyspecjalizowane? Chcę się upewnić bo to mi się wydaje jakieś takie niepasujące do skonwencjonalizowanej struktury Symfony...

Napisany przez: pedro84 12.10.2013, 21:58:12

Cytat(Foxx @ 12.10.2013, 22:38:50 ) *
Sorry, nie doczytałem nazwy bundla.

Czyli mogę sobie zrobić dowolny katalog wewnątrz bundla na "luźne" klasy i nie ma żadnego wyspecjalizowanego na to tak jak np. Entity/ albo Form/ są wyspecjalizowane? Chcę się upewnić bo to mi się wydaje jakieś takie niepasujące do skonwencjonalizowanej struktury Symfony...

Czy jeden katalog na wiele własnych klas? Z doświadczenia mogę Ci powiedzieć, że lepiej od początku porządkować wszystko, przyjmując sensowną strukturę plików/katalogów. Jeśli zaś chodzi tylko o możliwości, a nie to czy jest to właściwie, to tak, możesz.

Napisany przez: Foxx 12.10.2013, 22:03:32

Okej, dzięki.
A co do pytania to nie jestem pewien, czy dobrze je rozumiem, ale jeden katalog często ma wiele własnych różnych klas, np. Entity zawiera wszystkie obiekty związane z bazą, niekoniecznie związane ze sobą nawzajem. Więc chyba nie będzie niewłaściwe stworzenie katalogu np. "Objects" w którym umieszczę wszystkie klasy, których instancji będę potrzebował i które będą specyficzne tylko dla mojej aplikacji.

Napisany przez: pedro84 12.10.2013, 22:11:32

Zauważ tylko, że zarówno katalog Entity, jak i Form, Model, Controller mają określone i jasne zasady, co do tego jakie pliki powinny być tam przechowywane. Poza tym, już sama nazwa jest skonkretyzowana. Zobacz, że w przypadku katalogu form, struktura jego podkatalogów jest samo-wyjaśniająca, np. Form, Form\Type, Form\Handler.

SF daje Ci elastyczność, jak Ty ją wykorzystasz, zależy już od Ciebie. Zastanawia mnie też ile oraz jakie klasy masz, że chcesz je wszystkie pakować do jednego katalogu.

Napisany przez: Foxx 12.10.2013, 22:38:47

Szczerze to nie mam ich aktualnie wiele, jedynie ten koszyk byłby kandydatem. Ale wyobrażam sobie że w większym projekcie miałbym ich więcej. Pamiętajmy, że pomysł z osobnym katalogiem wyszedł jako odpowiedź na moje pytanie czy jest jakieś konkretne, określone dokumentacją miejsce przeznaczone na takie rzeczy.

Napisany przez: destroyerr 13.10.2013, 15:23:00

Cytat
I co w tym złego? Jeśli potrzebujesz w repozytorium dostęp do jakiegoś serwisu to w jaki sposób go obejdziesz? Z drugiej strony, to nie jest w żaden sposób powiązane z bazą, więc repozytorium lepiej zostawić.

Złe jest dlatego, że nadajesz repozytorium kolejną zależność (musisz tą zależność dostarczać przy pisaniu testów). Dodatkowo obciążając to repozytorium kolejnym zadaniem. Co gorsze zależność ta jest związana z jednym z kontekstów uruchamiania aplikacji (http), jeśli chciałbyś takie repozytorium wykorzystać podczas uruchamiania aplikacji z konsoli to masz problem.

@Foxx uważasz, że dokumentacja Symfony2 powinna przewidywać wszystkie możliwe klasy do obsługi czegokolwiek i podawać programistom w jakich folderach mają być? Musisz mieć obiekt koszyka i koniec. Operowanie na tablicach, wrzucanie jakiś indeksów zwiększanie ilości, gdzieś po kontrolerach jest śmieszne, ciężkie w testowaniu i jest proszeniem się o problemy. Jeśli zastanawiasz się gdzie umieścić taką klasę (a i nie zastanawiaj się w jakim folderze tylko w jakiej przestrzeni nazw) to posłuchaj pedro84 utwórz przestrzeń nazw/folder Cart. Tylko teraz już nie słuchaj pedro84 (to oczywiście tylko moje zdanie) i nie twórz klasy CartManager tylko po prostu Cart.

Napisany przez: pedro84 13.10.2013, 15:29:55

Cytat(destroyerr @ 13.10.2013, 16:23:00 ) *
Złe jest dlatego, że nadajesz repozytorium kolejną zależność (musisz tą zależność dostarczać przy pisaniu testów). Dodatkowo obciążając to repozytorium kolejnym zadaniem. Co gorsze zależność ta jest związana z jednym z kontekstów uruchamiania aplikacji (http), jeśli chciałbyś takie repozytorium wykorzystać podczas uruchamiania aplikacji z konsoli to masz problem.

Z kontekstem zgoda jak najbardziej, z zależnością już nie do końca. Najlepiej tak czy siak, taką funkcjonalność po prostu przenieść do serwisu, a w repozytorium tylko dane wybierać.

Cytat(destroyerr @ 13.10.2013, 16:23:00 ) *
Tylko teraz już nie słuchaj pedro84 (to oczywiście tylko moje zdanie) i nie twórz klasy CartManager tylko po prostu Cart.

W innym wątku (dot. właście czy KlasaManager czy Klasa) dobrą czytankę Ci wkleiłem dlaczego Manager. Ad vocem konwencji, to już dyskusja o wyższości jednych świąt na drugimi wink.gif

Napisany przez: destroyerr 13.10.2013, 17:39:00

Cytat
Z kontekstem zgoda jak najbardziej, z zależnością już nie do końca.

Nie wiem co oznacza, że już nie do końca. Nie do końca się zgadzasz, że kolejna zależność (całkowicie niepotrzebna) jest złą praktyką?

Cytat
Najlepiej tak czy siak, taką funkcjonalność po prostu przenieść do serwisu, a w repozytorium tylko dane wybierać.

Od tego się zaczęła między nami dyskusja i od początku miałem taki punkt widzenia.

Cytat
W innym wątku (dot. właście czy KlasaManager czy Klasa) dobrą czytankę Ci wkleiłem dlaczego Manager.

Też wkleiłem tam czytankę i co z tego? To są tylko czyjeś opinie takie same jak moje. Poza tym można tam znaleźć argumenty za i przeciw. W tamtym wątku menadżer dotyczy zarządzania kolekcją, np. użytkowników, Ty postulujesz użycie menadżera do obsługi jednego koszyka. Jak na warunki SO to słabo punktowany wątek, a w dodatku zamknięty.

Napisany przez: Foxx 16.10.2013, 00:50:45

Dzięki, rozjaśniło mi to trochę spraw. Chyba po prostu dotychczas nie dotarło do mnie, że aż tak elastyczna jest struktura bundla.

Chciałbym się w takim razie upewnić, czy zrobiłem to dobrze: mam teraz obiekt Cart, zarejestrowałem go jako service i mam do niego dostęp w kontrolerze. Tenże Cart ma metodę contains($productId), która sprawdza, czy koszyk zawiera produkt.
W kontrolerze podaję do twiga tablicę produktów oraz Cart (service). W twigu sprawdzam czy dany produkt jest w koszyku poprzez {% if cart.contains(product.id) %}. Działa - czy prawidłowo? Nie jestem pewien tej części, w której przekazuję service do twiga.

I jeszcze pytanie dodatkowe: czy istnieje rozwiązanie, w którym sprawdzałbym w twigu {% if product.inCart %} ?
Czy musiałbym wtedy stworzyć po prostu metodę inCart w repozytorium produktu, a następnie użyć w niej service cart?
Czy to nie byłoby lepsze ze względu na to, że nie musiałbym w kontrolerze przekazywać service cart do twiga?
Czy da się to zrobić bez service?

Napisany przez: destroyerr 16.10.2013, 18:25:11

Rozważ sobie czy nie lepiej do metody Cart::contains() zamiast id produktu nie lepiej byłoby przekazywać cały produkt. To jest luźna propozycja.
Co do samego Twiga. Możesz sobie taki koszyk podpiąć jako http://symfony.com/doc/current/cookbook/templating/global_variables.html. Możesz też podejść do tego jeszcze w ten sposób, że koszyk jest powiązany z obecnie zalogowanym użytkownikiem. Dorzucasz użytkownikowi gettera do koszyka. Sam użytkownik już z marszu jest w Symfony2 globalny więc odpada problem każdorazowego podpinania zmiennej do szablonu.

Cytat
czy istnieje rozwiązanie, w którym sprawdzałbym w twigu {% if product.inCart %} ?

Wtedy do encji musiałbyś podpiąć sesje. Bez sensu totalnie. Możesz napisać jaki jest powód, że chcesz akurat taki zapis?

Napisany przez: Foxx 19.10.2013, 00:33:22

Dzięki, podoba mi się pomysł połączenia usera z koszykiem.

Co do argumentu dla Cart::contains() to zastanawiałem się, czy to powinien być produkt czy tylko jego id skoro korzystam tylko z id, ale nie jestem w stanie określić, które rozwiązanie jest lepsze. Wybrałem id bo wydawało mi się to mniej obciążające pamięć, ale tak naprawdę to nie wiem czym się kierować w takim wypadku.

Pytam o rozwiązanie product.inCart bo taki zapis, a konkretnie taki sposób operowania tymi obiektami wydaje mi się najbardziej sensowny: przetwarzam kolejne produkty i pierwsze co mi przychodzi do głowy to odpytanie właśnie produktów o ich status koszykowy. Odpytywanie koszyka wymaga kolejnego obiektu (koszyka). Albo inaczej mówiąc wydaje mi się sensowne żeby produkt wiedział na swój temat takie rzeczy.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)