Wpis z mikrobloga

Witajcie mirki.

Tworzę w pracy stronkę, gdzie ma być sklep elektroniczny. Napisałem sobie serwis, gdzie tworzę zamówienie, dodaję produkty do zamówienia, pobieram informację o zamówieniu, cenę itd.
Jednak z powodu braku doświadczenia nie robię tego w odpowiedni sposób. W poprzedniej pracy widziałem jak takie coś było zrobione przez doświadczoną osobę i to mniej więcej wyglądało tak:
$this->getOrder()->getPrice() - aby pobrać cenę.
$this->getOrder()->getStatus() - aby pobrać status zamówienia.
U mnie to raczej wygląda tak, że pobieram serwis przy pomocy

$service = $this->get('app.order');
następnie wywołuję metodę:

$service->getPrice();
Nie wiem czy moje rozwiązanie jest w porządku, czy jednak pasowałby ten wariant, który podałem na początku. W pracy nie bardzo mam się kogo poradzić, a samemu brakuje mi doświadczenia z programowaniem obiektowym, więc pytam na mirko. Nie proszę o napisanie za mnie kodu, a tylko wskazanie jak ma wyglądać struktura takiego serwisu. Może to być nawet link do tutoriala.
Załączam swój kod w serwisie: https://gist.github.com/miedzwin/f7dbd4ee0cc4abfd37cb79d23ba4ab8e

#php #webdev #programowanieobiektowe #symfony2
  • 21
  • Odpowiedz
Jeżeli ten $this->getOrder() jest odpalany w kontrolerze, to wg mnie zła logika - kontroler nie powinien szukać zamówienia, to powinno dziać się w serwisie, tak jak Ty to odpalasz.

Z pewnością jednak polecę Ci choć pobieżne przejrzenie kodu "większych" e-commerce pisanych w SF2:
https://github.com/Sylius/Sylius
https://github.com/thelia/thelia
Nie pod kątem użycia ich (bo przy mini stronce to będzie strzelanie z armaty do wróbla) - ale sposobu implementacji, jaki przyjęło większe community.
  • Odpowiedz
@mariecziek: odpuść sobie pisanie sklepu, zakopiesz się w gównie po kolana. Pomijając to, że piszesz aplikację i mieszasz kod infrastruktury (symfony2) i logiki biznesowej (zamówienia, płatności i takie tam).

Poczytaj sobie o zasadach SOLID, może obejrzyj jakąś prezentację z konferencji na yt.

Twój "OrderService" łamie bardzo wiele tych zasad. W programowaniu obiektowym nie powinieneś mieć takiego "serwisu" który robi wszystko związanego z orderami.

Zapewne Twój Order jest złożony z pól i
  • Odpowiedz
@motokate: Szczerze mówiąc to nikt mnie nie kontroluje. 2 tygodnie temu poprosiłem PM'a aby odpowiedziała na kilka pytań (1.5 strony formatu A4) i do dzisiaj nie mam odpowiedzi. Moi koledzy w sumie też klepią gównokod, bo jak sprawdzałem ostatnio kod przy pomocy scrutinizer, to osiągałem lepsze wyniki niż moi bardziej doświadczeni koledzy, więc dałem spokój z zadawaniem im pytań i wolę pytać na wykopie jak mam takie pytania jak w moim
  • Odpowiedz
$service = $this->get('app.order');

następnie wywołuję metodę:

$service->getPrice();


@mariecziek: chyba sobie #!$%@? żartujesz, serwis zwraca ci cenę ordera ? XD to order ma zwracać cenę
  • Odpowiedz
Do tego pisaliśmy w Yii1.13, więc to nie miało za dużo wspólnego z sf2


@mariecziek: właśnie chodzi o to, że nie powinno być różnicy w tym przypadku. Ten kod nie powinien mieć nic wspólnego z frameworkiem którego używasz i tutaj jest największy problem, bo to tak jakbyś przy wbijaniu gwoździa w deskę przybijał też młotek... razem z tym gwoździem... do tej samej deski. To, że masz wątpliwości to normalne, na tym
  • Odpowiedz
@mariecziek: serwis tworzy się wtedy gdy będziesz wykorzystywał ten sam kod w wielu miejscach/będziesz operował na intefejsach, będziesz tworzył order w kilku miejscach, albo posiadał wiele klas które będą implementowały OrderInterface ? raczej na 90% nie, także nie widzę sensu pakowania tego w serwis

tak poza tym mam rozumieć że Orders to kolekcja zamówień ? w bazie jest to przechowywane jak ? każda kolumna to oddzielne zamówienie ?

poza tym tworzysz
  • Odpowiedz
@mariecziek:

public function addItems()
{
$cart = $this->cart->getCart();
foreach ($cart as $id => $amount) {
$variation = $this->em->getRepository(ProductVariation::class)->find($id);
$this->addOrderItem($this->getOrder(), $variation, $amount);
}
}

Naprawdę ? Pobieranie czegoś w foreachu ? Tak ciężko zrobić:

$ids=[];
$amounts=[];
foreach ($cart as $id => $amount) {
$amounts += [$id => $amount];
$ids[]=$id;
}
$criteria = new Criteria();
$criteria->where($criteria->expr()->in('id',$ids));
$variations=$this->em->getRepository->(ProductVariation::class)->matching($criteria);

I zmienić w metodzie addOrderItem aby łykał tablicę variatons i tablicę amounts ?

poza tym ten
  • Odpowiedz
@Jurigag: Model, masz na myśli encję czy mam stworzyć folder Model i tam umieścić klasę Order, gdzie opiszę te wszystkie metody?
Yii był frameworkiem gdzie stosowano wzorzec MVC, więc takie rzeczy jak te, które piszę w serwisie pisane były w modelu. W sf2 w encji trzymam tylko strukturę DB, ewentualnie jakieś metody do sprawdzania statusu itp. no a SQL'e (querybuilder) pisze w repozytoriach. Widziałem, że niektóre bundle mają folder Model i
  • Odpowiedz
@mariecziek: taj w sensie encji, wszystkie te metody tam powinny się znajdować bo operują one na Order, ale przecież ty tu nie operujesz na sqlach, operujesz na orderze xD a to że robisz niepotrzebne zapytania co chwile to już inna kwestia, wiesz o tym że zamiast tego:

public function addOrderItem(Orders $order, ProductVariation $productVariation, $amount)
{
$orderItem = new OrderItem();
$orderItem->setOrder($order);
$orderItem->setPrice($productVariation->getPrice());
$orderItem->setProductVariation($productVariation);
if ($productVariation->getAmount() < $amount) {
$orderItem->setAmount($productVariation->getAmount());
} else {
  • Odpowiedz
@mariecziek: a folder Model w bundlach to zwykle po prostu abstract klasy które rozszerzasz które mają być twoimi encjami, np User w FOSUserBundle
jeszcze zawołam @DanioPL niech zweryfikuje co ja tu gadam żebym też nie gadał bzdur i ci źle mówił
  • Odpowiedz
@Jurigag: @mariecziek:

public function addOrderItem(OrderItem $orderItem)
{
$this->orderItems[] = $orderItem;
}

Jest okej, ale jak ma spieprzony mapping w doctrine to możliwe, że musi zrobić jeszcze $orderItem->setOrder($this); znając życie i robie "pod dokumentację" :D
  • Odpowiedz
@DanioPL: znaczy w sumie i tak potrzebuje jakąś factorie do tych OrderItemów najlepiej, nie iwem jak można skopać mapping w doctrine xD w sumie to jest właśnie fajne dosyć że można dodać w ten sposób i nie trzeba się pieprzyć i potem robimy tylko jeden flush i dziękuje
  • Odpowiedz
@mariecziek: no to coś masz #!$%@? bo powinno wystarczyć stworzyć w faktorii obiekt OrderItem o w taki sposób:
$orderItem = OrderItemFactory::createFrom($productVariation,$amount);
a potem po prostu:
$order->addOrderItem($orderItem);
$em->persist($order); // o ile nie jest on wcześniej pobrany przez em, jeśli jest to ta linijka jest zbędna
$em->flush(); @DanioPL:
  • Odpowiedz
@Jurigag: @mariacziek

$orderItem = OrderItemFactory::createFrom($productVariation,$amount);

spokojnie wystarczy $orderItem = new OrderItem($productVariation, $amount);
taka fabryka to przerost formy nad treścią imo, bo to prosty obiekt, który zupełnie nie potrzebuje czegoś takiego.

Reszta spoko, a jeśli chodzi o to $orderItem->setOrder($this); to musi to robić, żeby mu doctrine wypełnił pole w OneToMany. Da się to "ominąć" przez użycie dodatkowej tabeli. Dopóki getterki i setterki i tak będą to to nie przeszkadza ;)
  • Odpowiedz