Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Stworzenie sklepu
Forum PHP.pl > Forum > Bazy danych
mimol
Witam, zastanawia mnie jak powinna wyglądać struktura tabel do sklepu.
Proszę o info czy mój pomysł jest OK

Product
*ID
*name
*desc
*category
Category
*ID
*name
Order
*User_id
*adress
*starus
Order_has_product
*order_id
*product_id
*amount
mmmmmmm
jeszcze jakies 300 tabel ci brakuje. (no moze z 300 przesadziłęm, ale ze sto to na pewno)
thek
Do pewnego momentu Ci wystarczy. Jaki to moment? Gdy nadejdzie zmiana ceny produktu. Skąd wtedy będziesz wiedział jaki produkt kiedy miał jaką cenę, skoro cena zapewne będzie przypisana do produktu lub po prostu jego atrybutem, tak jak desc lub name? Poza tym... Każdy produkt, choćby jeden, to osobne zamówienie? A co jeśli ktoś do "koszyka" wrzucił kilka rzeczy? Policzysz kilka razy koszt wysyłki? Pomyśl nad tym i co konkretnie ten system ma oferować i jak działać. Nie zaczynaj od struktury tabel, tylko od funkcjonalności i niejako tego, co widzi użytkownik. To przełóż na obiekty i dopiero wtedy myśl o przełożeniu na tabele.
mimol
Cytat
Skąd wtedy będziesz wiedział jaki produkt kiedy miał jaką cenę, skoro cena zapewne będzie przypisana do produktu

Hmm no jak dam edycje produktu to będę wdział ostatnią cenę. Tabeli mam oczywiście więcej, bardziej chodziło mi w temacie jak rozwiązać problem z koszykiem produktów.
Cytat
Każdy produkt, choćby jeden, to osobne zamówienie?

No tak myślałem.
Np w Order będzie zapisany adres do wysyłki.
W Order_has_product np
1 2 1
1 3 2
Czyli nr zamówienia w którym jest produkt nr 2 i dwa produkty nr 3.

Nie wiem czy to dobry pomysł więc pytam się na forum... Nie potrafię nic bardziej sensownego wymyślić, więc proszę o jakieś podpowiedzi
thek
A będziesz wiedział jaka była cena produktu 2 miesiące temu? Może już zdążyła nastąpić jej edycja 5 razy? wink.gif Liczysz na niezmienność i modlisz się, albo wprowadzasz tabele historyczne lub też kombinujesz wink.gif

Masz do zapamiętania kilka rzeczy dla każdego produktu w koszyku: produkt, cenę (brutto lub netto do wyboru), vat, ilość produktów. Czemu? Jeśli ktoś będzie kupował, może chcieć się rozliczyć na innych warunkach, jak choćby faktura VAT dla firm. Stąd cena i podatek powinny być osobno. Dane te mogą być inne nawet każdego dnia, jeśli pozwolisz klientom edytować ceny produktów/usług w systemie. Będziesz pamiętał jaka cena była tego a tego dnia, lub jaki rabat danej osobie konkretnego dnia przysługiwał? Po kilku godzinach byś się pogubił wink.gif Dlatego tego typu dane powinny być niezależne od aktualnych w danej chwili i po transakcji także przechowane. Najczęściej takie coś rozwiązuje się poprzez jakąś formę przechowania aktualnych w danej chwili parametrów. Jednak często nie do końca wiemy jaką ostateczną formę (ilość kolumn) to przyjmie. Albo więc tworzymy tabelę z kolumnami, które przewidujemy jako puste z góry, albo zaczyna się zabawa w serializowanie części danych (i tak są w zasadzie tylko do sporadycznego odczytu) lub bazy nosql, które można przy odrobinie pomyślunku zgrać z bazami relacyjnymi w samej aplikacji jako formę archiwum transakcji przykładowo.

Najczęściej w chwili obecnej chyba spotykanym rozwiązaniem jest zapis zserializowanej zawartości koszyka, gdzie poszczególne elementy to produkty z niezbędnymi parametrami, które po deserializacji można wykorzystać do pobrania z bazy brakujących, ale niezmiennych rzeczy, jak choćby identyfikator oferty/przedmiotu. Oczywiście jak podejdziesz do aplikacji sklepu nie wiem osobiście. Dałem Ci jedynie do przemyślenia fakt, że czasem nie zauważa się rzeczy i należy spojrzeć na problem bardziej ogólnie niż tylko z poziomu struktury tabel. Nie za bardzo przyjrzałeś się problematyce i samemu zagadnieniu. Gdybym ja miał iść po najmniejszej linii oporu, tabela miała by postać mniej więcej w stylu: id_zamówienia, id_usera, data_transakcji, zawartość_koszyka. Czym jest ta zawartość? To zserializowana tablica, przechowująca jako elementy tablice atrybutów pokroju: id_produktu, cena, podatek, ilość, ewentualny rabat. Dodatkowo w przypadkach niektórych, sama tablica może mieć osobno jeszcze wydzielone rabaty na elementy powiązane, bo i takie rabaty się zdarzają. Masz naprawdę trochę do przemyślenia struktury i powiązań smile.gif
mimol
dzięki za odpowiedź.
Hmm chciałem aby to było w miarę proste, ponieważ chcę sobie napisać coś co wygląda jak sklep (taki projekt sam dla siebie / być może coś czy mógłbym się pochwalić)... więc nie zależy mi na tym, aby były zapamiętane ceny itd.... Tylko na razie żeby działało.... Potem będę zastanawiał się nad szczegółami
Nigdy nie bawiłem się jeszcze w serializacje... więc szczerze nie wiem jak się za to zabrać... (Słyszałem, że jest to zapisywanie obiektu... Jak sobie z tym radzić w SF2)?

Też chciałbym się dowiedzieć co zrobić z anonimowymi użytkownikami (takimi którzy nie posiadają konta), co mam zapisywać w bazie??
Czy może wszystko zapisywać w sesji?... a może zawsze mieć wszytko w sesji a dopiero na sam koniec podczas składania zamówienia (ostatni krok) zapisać to w bazie?
thek
Serializacja to konwersja obiektów do stringa w taki sposób, by była mozliwe jego ponowne odtworzenie. Tu nie ma wiele zabawy, gdyż są do tego gotowe metody w php. Co do symfony2 to ona też ma do tego wbudowane mechanizmy poprzez adnotacje choćby czy serializery. Tu raczej więc nie ma większych problemów. Co do anonimowych uzytkowników, można zrobić to choćby tak, ze po wejściu do sklepu nie robisz nic, ale każdy użytkownik ma sesję i dostęp do koszyka. Może w każdej chwili zalogować, ale nie jest to konieczne dla procesu wybierania. Gdy dochodzi do procesu zakupu możesz rozwiązać to na kilka sposobów. Możesz zaproponować jedno z kilku rozwiązań, ale sprowadzają się one do tak naprawdę 4 przypadków:
- prosisz użytkonika o zalogowanie jeśli ma konto,
- proponujesz założenie konta,
- zakładasz konto niejawnie lub o krótkim czasie ważności,
- pozwalasz na podanie danych do wysyłki.
Gdy tworzysz jakiekolwiek konto - nie ma problemu. Możesz przykładowo ograniczyć liczbę pól wymaganych by po prostu walidacja takiego konta przeszła (validation groups się kłaniają). Gdy pozwalasz na wysyłke bez tworzenia konta, musisz mieć możliwość zachowania danych do wysyłki w innej postaci. Własnie tutaj można zrobić sobie zadanie "od końca". Transakcje moga być zrobione na różne sposoby. Możesz przechowywać dane na sposoby podręcznikowe, czyli optymalizując tabele by pozbyć redundantnych danych. Możesz też spreparowac dane by wykorzystać je od razu przy wysyłce. Ale tutaj niemal na pewno wystąpi powtórzenie danych. Kwestia więc estetyki i miejsca na dysku czy w bazie wink.gif Jako że osobiście nie ufam w niezmienność danych typu cena czy podatek VAT na produkty, wolę dane takie zapisywać w momencie transakcji, by mieć punkt odniesienia. W takiej sytuacji mogę sobie tabelę transakcji zapisać jako:
id_transakcji, id_usera, transkcja. Czemu tak? Pierwsze pole nie wymaga wyjaśnień. Drugie przechowuje id_usera w systemie. Jeśli jest tam liczba, wiem że muszę podstawowych danych adresowych szukać w profilu usera o danym id. jeśli brak, user jest anonimowy i danych wysyłki szukam w polu transakcji. A co jeśli user ma inne dane w profilu, a na inne chce wysłać? Formularz transakcji i jedna z opcji to zmiana adresu wysyłki. Można dodatkowo dodać checkboxy, czy dane te mają stać się profilowymi, a może także domyślnymi dla dalszych wysyłek. Jak widzisz, jest dużo możliwości. Oczywiście wygodnie jest wtedy zapisac ów adres wysyłki także do transakcji. Sama transakcja to dla mnie właśnie zserializowane dane o całości zamówienia.
mimol
Czyli czy moja struktura tabel moze wygladac nastepująco?
User
*ID
*name
*address
Product
*ID
*name
*desc
*category
*price
Category
*ID
*name
Order
*ID
*User_id
*order
*address
*status


Jeśli kupujący jest (zalogowany/ nie zalogowany), to wszystkie akcje związane z produktem zapisuję w sesji (Product_id, amount) (czy to bezpieczne??)
Jeśli kupujący chce kupić produkt:
*jest zalogowany, to wyświetlam podsumowanie, i w formularz wysyłki wstawiam jego adres z profilu (jeśli chce może go zmienić)
*jeśli jest niezalogowany wyświetlam pusty formularz

Jeśli zdecyduje się kupić do tabeli Order wrzucał userID/NULL, adres na który chce wysłać, wszystkie zserializowane obiekty, które kupił (gdzie umieścić informacje o ich liczebności), status (domyślnie rozpoczęta)

Co jeśli będę chciał wyszukać jakie produkty kupili userzy?? Pobieranie całej zawartości Order->status, zamienianie na obiekt nie wydaje mi się najlepszą opcją...

=======================
User
*ID
*name
*address
Product
*ID
*name
*desc
*category
*price
Category
*ID
*name
Order
*ID
*User_id
*item_ID
*address
Item
*ID
*product (serializowany)
*amount

Jaka opcja lepsza. Mnie wydaje się, że nr2....
Wyszukiwanie jacy userzy kupili dany produkt też w tym przypadku nie powinno być takie trudne (Wydaje mi się że jeśli produkt jest zserializowany, to można odczytać jego ID). Jedyna wada/zaleta każdy produkt można wysłać na inny adres
thek
Mi akurat odczytywanie co user dodał do koszyka nie było potrzebne. Jeśli Cię interesuje na zasadzie zrobienia opcji w stylu "Inni kupujący ten produkt kupili także...", to możesz po prostu "wypchnąć" określony i potrzebny parametr poza serializowane dane. W Twoim wypadku nieco inaczej bym podszedł do koszyka. Masz userów, produkty i kategorie w sumie bez zmian. Zastanawiałbym się jednak nad wywaleniem category z Product i połączeniem go relacją Many-to-Many go z Category.
Order może zawierać id, usera, adres, ale zawiera nie połączenie do produktu, ale utwórz tu kolekcję serializowanych danych, czyli relacja One-To-Many z Item. Z kolei Item to nie jest cały serializowany Product, ale jedynie wybrane jego składowe. Po co trzymać tam desc, który będzie niezwykle długi zapewne? wink.gif Wystarczy, że zserializujesz name i price lub inne niezbędne z Product atrybuty (te, które mogą się zmienić, a są konieczne do transakcji) by wygenerowac fakturkę ewentualną czy jakieś zestawienie. Dla wyszukiwania dobre by też mogło być utworzenie Item jako tabeli połączeniowej między Order a Product, która miała by jako pola dodatkowe owe amount i serializowane dane. Rozwiązało by Ci to problem wyszukiwania między innymi. tak więc na chwilę obecną miałbyś cos w stylu:
User
*ID
*name
*address
Product
*ID
*name
*desc
*price
Category
*ID
*name
ProductCategory
*productId
*categoryId
(klucz typu unique na oba razem)
Order
*ID
*User_id
*address
OrderProduct
*orderId (przynajmniej na tym index)
*productId
*product (serializowany)
*amount

Myslę, że najpierw musisz przemysleć cele i zachowanie użytkownika w systemie. Jak od jego strony powinien proces kupna przebiegać od początku do końca. Co w przypadku cofania się lub innych wariacji w systemie? Jak rozbic proces na składowe? Naprawdę... Zobacz, że gdyby nie Twoje wspomnienie o przeglądaniu produktów usera, to bym nigdy nie wpadł, ze struktura może być inna. Dostosuj bazę do funkcjonalnosci... Nie na odwrót. Inaczej zostaniesz z protezami, które nie wiadomo potem jak poprawiać.
mimol
Hmm z category nie chce kombinować (Jako przykład podałem uproszczony model), bo obecnie mam Kategorie, i Podkategorie i relacje między nimi.
Dzięki za pomoc.
Pozostaje jeszcze jedna kwestia, o której wspomniałem.
Zapomniałeś mi wyjaśnić czy od razu ładować wszystko do bazy (klient doda pierwszy produkt -> w bazie generuje się nowy Order i reszta tabel, przy dodawaniu następnych sprawdzane jest czy to jest pierwszy czy kolejny produkt), czy (chyba lepszy pomysł) dopiero na końcu składania zamówienia (po uzupełnieniu adresu, metody płatności) wrzucić to do bazy, a przed tym trzymać wszystko w Sesji...
I tutaj jest problem bo wydaje mi się, że SF2 nie ma swojej obsługi sesji więc można ją łatwo odczytać/zatruć. Jak sobie poradzić z tym problemem?
skowron-line
Ja bym dodał jeszcze
Product
*ID
*name
*desc

Product_Price
*product_id
*price
*change_date

wtedy na dany dzien będzie mozna cene wyciągnąć

Cytat
Zapomniałeś mi wyjaśnić czy od razu ładować wszystko do bazy (klient doda pierwszy produkt -> w bazie generuje się nowy Order i reszta tabel, przy dodawaniu następnych sprawdzane jest czy to jest pierwszy czy kolejny produkt), czy (chyba lepszy pomysł) dopiero na końcu składania zamówienia (po uzupełnieniu adresu, metody płatności) wrzucić to do bazy, a przed tym trzymać wszystko w Sesji...

wkładaj odrazu do bazy a w sessji numer zamówienia trzymaj żebys kolejne produkty pod to samo zamówienie podpinał a status zamówienia zmieniaj (na potwierdzone) jak już Ci klient wpisze wszystkie dane i kliknie "Zamawiam|Potwierdzam"
mimol
jak sobie poradzić z czyszczeniem wpisów które nie są dokończone? Używając CronJoba? czy jest jakiś sposób aby tworzyć 'tymczasowe' tabele?
thek
Bezpieczniej jest trzymać gdzieś w bazie taki tymczasowy koszyk, który potem będziesz tylko uzupełniał o kolejne produkty. Jeśli masz to zrobić jednak jak najprościej, to i sama sesja na koszyk starczy. Co do czyszczenia to najprościej użyć cronjobs lub eventów.
mimol
Mógłbyś rozwinąć ideę eventów.
Znalazłem
http://www.alexatnet.com/articles/programming-events-php
Ale nie mam pojęcia jak teko używać/ kiedy wywołać jakiś event?
skowron-line
Jeżeli chodzi o czyszczenie to dasz jakis czas na zatwierdzenie zamówienia a po tym czasie będziesz usuwał wpisy.
http://dev.mysql.com/doc/refman/5.1/en/events.html tu masz eventy w mysql.
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-2025 Invision Power Services, Inc.