Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP] Poprawne wczytanie $_POST do klasy
k8dz
post 10.02.2020, 20:24:33
Post #1





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 5.02.2020

Ostrzeżenie: (0%)
-----


Mam formularz i po kliknięciu wyślij potrzebuję przekazać jego wartości do klasy, aby móc na nich wykonać operacje. Zastanawiam się jak to poprawnie powinno być wykonane. Czy takie rozwiązanie jest poprawne, czy powinienem to jakoś inaczej zrobić?

  1. $cena_plyty = 25; //domyślna wartość zmiennej
  2.  
  3. if ( isset($_POST['cena_plyty']) and is_numeric($_POST['cena_plyty']))
  4. {
  5. $cena_plyty = $_POST['cena_plyty'];
  6. }
  7.  
  8. $wycena = new Wycena;
  9. $wycena->ustaw_cene($cena_plyty);
  10. echo $wycena->wyswietl_wycene();
Go to the top of the page
+Quote Post
vokiel
post 10.02.2020, 21:43:44
Post #2





Grupa: Zarejestrowani
Postów: 2 469
Pomógł: 415
Dołączył: 12.03.2007

Ostrzeżenie: (0%)
-----


Tak, generalnie jest OK.

Chociaż często stosuje się też inny sposób działania - wyświetlanie błędów w przypadku nieudanej walidacji danych wejściowych (zamiast przepuszczania na domyślnych wartościach). Tym samym jeśli tylko gdzieś trafisz na nieprawidłowe dane to nie próbujesz ich naprawiać, nie podstawiasz danych domyślnych (bo mogą spowodować anomalie), tylko zwracasz użytkownikowi błąd i pokazujesz gdzie zostały wpisane niepoprawne dane.


--------------------
Go to the top of the page
+Quote Post
k8dz
post 10.02.2020, 22:24:13
Post #3





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 5.02.2020

Ostrzeżenie: (0%)
-----


Rozumiem o co chodzi, chociaż w tym przypadku tworzę prostą aplikację na własne potrzeby, więc nie muszę jej tak zabezpieczać.

Mam jeszcze jedno pytanie. Czy poprawne jest ustawienie za pomocą jednej metody wszystkich zmiennych pobranych z $_POST i później bezpośrednie odwoływanie się do tych zmiennych, czy trzeba do każdej zmiennej pobranej z $_POST tworzyć osobną metodę i potem odwoływać się do metody? Przykład poniżej:

  1.  
  2. $cena_plyty = $_POST['cena_plyty'];
  3. $cena_ciecia = $_POST['cena_ciecia']; //itd, itd...
  4.  
  5. $wycena = new Wycena;
  6. $wycena->ustaw_cene($cena_plyty, $cena_ciecia, $cena_oklejania, $cena_transportu);
  7. echo $wycena->cena_plyty;
  8. echo $wycena->cena_ciecia; //itd...


czy jednak tak:

  1. $wycena = new Wycena;
  2. $wycena->ustaw_cene_plyty($cena_plyty);
  3. echo $wycena->cena_plyty();
  4.  
  5. $wycena->ustaw_cene_ciecia($cena_ciecia);
  6. echo $wycena->cena_ciecia(); //itd...
Go to the top of the page
+Quote Post
viking
post 11.02.2020, 08:48:15
Post #4





Grupa: Zarejestrowani
Postów: 5 483
Pomógł: 932
Dołączył: 30.08.2006

Ostrzeżenie: (0%)
-----


A może tak:
class Cena -> settery , gettery do poszczególnych cen.
class Wycena -> __construct(Cena $cena)


--------------------
Go to the top of the page
+Quote Post
k8dz
post 11.02.2020, 20:54:43
Post #5





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 5.02.2020

Ostrzeżenie: (0%)
-----


ok, czyli w klasie Cena robię settery i gettery dla poszczególnych cen:
  1. public function set_cena_plyty($cena_plyty)
  2. {
  3. $this->cena_plyty = $cena_plyty;
  4. }
  5.  
  6. public function get_cena_plyty()
  7. {
  8. return $this->cena_plyty;
  9. }

ale czy mógłbyś mi wytłumaczyć, do czego potrzebna jest nowa klasa Wycena i dlaczego w konstruktorze jest nazwa klasy Cena i dopiero po niej zmienna $cena?
Rozumiem zasadę działania konstruktora, ale nie rozumiem tego zapisu :/
Go to the top of the page
+Quote Post
vokiel
post 11.02.2020, 23:11:43
Post #6





Grupa: Zarejestrowani
Postów: 2 469
Pomógł: 415
Dołączył: 12.03.2007

Ostrzeżenie: (0%)
-----


Możesz to rozdzielić na początek na dwie klasy, produktu i wyceny.
Zakładam, że produkty masz zdefiniowane gdzieś (np zapisane w bazie, i do formularza przekazujesz ich ID.
Tak, że w $_POST dostajesz tablice produktów z ich ilościami i cenami, np:

Kod
Array
(
    [0] => Array
        (
            [id] => 1
            [count] => 5
            [price] => 2.34
        )

    [1] => Array
        (
            [id] => 2
            [count] => 1
            [price] => 12.09
        )

    [2] => Array
        (
            [id] => 5
            [count] => 1
            [price] => 25.93
        )

    [3] => Array
        (
            [id] => 9
            [count] => 1
            [price] => 52.83
        )
)


  1. $valuation = new Valuation();
  2.  
  3. foreach($_POST['items'] as $item){
  4. $product = new Product($item['id']);
  5. $product->setPrice($item['price']);
  6. $product->setQuantity($item['quantity']);
  7. $product->setCount($item['count']);
  8.  
  9. $valuation->addProduct($product);
  10. }
  11.  
  12. echo "Suma: ".$valuation->getSum().PHP_EOL;
  13. foreach($valuation->getProducts() as $product){
  14. echo 'Produkt '.$product->getId().' | nazwa: '.$product->getName().' | cena: '.$product->getPrice().PHP_EOL;
  15. }


Api klas dopiszesz sobie sam, oczywiście pamiętając o walidacji danych.


--------------------
Go to the top of the page
+Quote Post
k8dz
post 12.02.2020, 21:54:37
Post #7





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 5.02.2020

Ostrzeżenie: (0%)
-----


wielkie dzięki! o to mi właśnie chodziło wink.gif przetestowałem na prostym przykładzie i działa, więc mogę teraz spokojnie działać

ale mam jeszcze pytanie - gdzie i kiedy najlepiej jest robić walidacje danych z $_POST? Czy w pliku, który przetwarza formularz zrobić odpowiednie if...else i jeśli wszystko jest ok, to wtedy utworzyć obiekty i wpuścić $_POST do dalszego przetwarzania; czy tak jak w przykładzie który podałeś, wpuścić $_POST do obiektu i dopiero później za pomocą odpowiedniej metody sprawdzać, czy jest ok; czy może lepiej było by utworzyć osobną klasę zajmującą się tylko walidacją danych i w niej odpowiednie metody sprawdzające czy z $_POST jest wszystko ok??

ps. może zadaję dziwne pytania, ale powiem tak: zajmuję się produkcją mebli na wymiar, chociaż jestem z wykształcenia informatykiem haha.gif Mam sporo prostych zrobionych własnoręcznie skryptów przydatnych w mojej firmie. Wszystkie są napisane w php i totalnie strukturalnie, z całą masą różnych if..else, warunków i itp zbędnego kodu. Po 10 latach przerwy w programowaniu postanowiłem zrobić kilka kolejnych aplikacji, jednak teraz chcę to zrobić w miarę profesjonalnie i obiektowo, a niestety kursy są zbyt ogólnikowe i nie można z nich wszystkiego się dowiedzieć. Dlatego proszę o porady ;
Go to the top of the page
+Quote Post
vokiel
post 13.02.2020, 20:24:52
Post #8





Grupa: Zarejestrowani
Postów: 2 469
Pomógł: 415
Dołączył: 12.03.2007

Ostrzeżenie: (0%)
-----


Co do walidacji to różne są podejścia. Raz jako osobna klasa validatora, raz spięte z generatorem formularza. W sumie osobna klasa i tak się przyda, kwestia gdzie jej użyjesz. Ja wyznaję zasadę "Avoid Else, Return Early" i uważam, że czym wcześniej zastosuje się sprawdzanie, które może przerwać kod tym lepiej. Po pierwsze będzie szybciej, mniej niepotrzebnych obiektów/zmiennych się stworzy, mniej kodu się wykona, mniejsza szansa, że wykona się kod, który nie powinien. No i użytkownik dostanie odpowiedź szybciej.

Także w prostych aplikacjach walidację moim zdaniem lepiej jest robić na samym początku (o ile masz już na tym etapie informacje o poprawnym formacie). Czyli tutaj spokojnie po odebraniu danych z formularza możesz zrobić walidację w pierwszej kolejności, a jeśli ona się powiedzie, to dopiero wtedy tworzyć obiekty produktów i wycenę.


Cytat
Mam sporo prostych zrobionych własnoręcznie skryptów przydatnych w mojej firmie. Wszystkie są napisane w php i totalnie strukturalnie, z całą masą różnych if..else, warunków i itp zbędnego kodu.

Kiedyś poczyniłem aplikację, a ostatnio dowiedziałem się, że po 10 latach nadal z niej korzystają. Voyager 2 leci już 40 lat i nadal się komunikuje z NASA. Stary kod, który działa to niekoniecznie zły kod :-D


--------------------
Go to the top of the page
+Quote Post
k8dz
post 13.02.2020, 21:01:10
Post #9





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 5.02.2020

Ostrzeżenie: (0%)
-----


tak właśnie obstawiałem, że taka podstawowa walidacja powinna się odbywać na samym początku, a dodatkowa klasa validująca może bardziej szczegółowo sprawdzać, co znajduje się w $_POST

a czy taki zapis ma sens?:

  1. $sprawdz = new Validacja();
  2. $sprawdz->validacja_post($_POST['cena1'], $_POST['cena2']);


według mnie jest to bez sensu, jeśli nie sprawdzi się chociażby, czy $_POST w ogóle istnieje, ponieważ jeśli nie ma $_POST to zwróci błąd o braku $_POST

ps. przez 4 lata nauki w technikum uczyliśmy się głównie programowania strukturalnego, a tak na prawdę tylko jakieś podstawy javy były obiektowe, ale to była dla mnie wtedy czarna magia haha.gif
nie twierdzę, że stary kod jest zły, bo faktycznie takie aplikacje działają, ale tak dla własnej satysfakcji chcę chociaż w miarę opanować tą obiektowość
Go to the top of the page
+Quote Post
vokiel
post 14.02.2020, 15:12:29
Post #10





Grupa: Zarejestrowani
Postów: 2 469
Pomógł: 415
Dołączył: 12.03.2007

Ostrzeżenie: (0%)
-----


Językowo bym się trzymał angielskich nazw, jeśli już chcesz PL to Walidacja nie Validacja. Ale nadal, Validator brzmi lepiej ;-)

Najczęściej walidatory przyjmują reguły, na podstawie których sprawdzają czy pole ma poprawą wartość.

Możesz np zrobić tak, że przekazujesz całą tablicę $_POST i dla nazw pól ustawiasz warunki, np not_empty, int, string, max_lengt: 16, min_length: 8, unique, match_regex itd.
Następnie w walidatorze bierzesz pole, sprawdzasz czy istnieje w $_POST, czy jest wymagane, czy jego format jest zgodny ze wzorcem. Jeśli nie to zbierasz błędy i na koniec zwracasz true/false plus tablica błędów.

Same sprawdzanie formatu możesz zrobić w jakiejś osobnej klasie, w której zdefiniujesz sobie metody na każde porównanie, w stylu:
  1. class Rule {
  2. public function notEmpty($item)
  3. {
  4. return !empty($item);
  5. }
  6.  
  7. public function matchRegex($item, string $regex)
  8. {
  9. return preg_match($item, $regex);
  10. }
  11. }


A do walidatora dodajesz przez:
  1. $validator = new Validator();
  2. $validator->addRule('price', new Rule('not_empty'));
  3. $validator->addRule('price', new Rule('decimal'));
  4.  
  5. $validator->addRule('quantity', new Rule('not_empty'));
  6. $validator->addRule('quantity', new Rule('greater_than', 0));
  7.  
  8. if (!$validator->valid()){
  9. // Wróć do formularza, podświetl błędne pola.
  10. }


--------------------
Go to the top of the page
+Quote Post
k8dz
post 14.02.2020, 20:08:25
Post #11





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 5.02.2020

Ostrzeżenie: (0%)
-----


ten sposób mi się podoba, ale kurde nie do końca wszystko rozumiem.. Klasa Rule jest dla mnie jasna, ale metoda addRule() już nie za bardzo. Rozumiem, że metoda addRule() przyjmuje 2 parametry. Pierwszy parametr, to ten który ma być sprawdzony, ale ten drugi parametr z klasą Rule nie rozumiem.. jakbyś mi to jeszcze wytłumaczył i już nie zawracam więcej gitary
Go to the top of the page
+Quote Post
viking
post 14.02.2020, 20:45:55
Post #12





Grupa: Zarejestrowani
Postów: 5 483
Pomógł: 932
Dołączył: 30.08.2006

Ostrzeżenie: (0%)
-----


Poczytaj po prostu jak robią to inni https://docs.laminas.dev/laminas-validator/ POdstawowa zasada obecnie. Nie wymyślaj swoich rozwiązań na siłę. Po to są gotowe komponenty żeby z nich korzystać.
Dodatkowo stosuj się do PSR-2.

Ten post edytował viking 14.02.2020, 20:51:43


--------------------
Go to the top of the page
+Quote Post
vokiel
post 15.02.2020, 13:24:58
Post #13





Grupa: Zarejestrowani
Postów: 2 469
Pomógł: 415
Dołączył: 12.03.2007

Ostrzeżenie: (0%)
-----


Cytat(k8dz @ 14.02.2020, 20:08:25 ) *
ten sposób mi się podoba, ale kurde nie do końca wszystko rozumiem.. Klasa Rule jest dla mnie jasna, ale metoda addRule() już nie za bardzo. Rozumiem, że metoda addRule() przyjmuje 2 parametry. Pierwszy parametr, to ten który ma być sprawdzony, ale ten drugi parametr z klasą Rule nie rozumiem.. jakbyś mi to jeszcze wytłumaczył i już nie zawracam więcej gitary


Tak, addRule() dodaje kolejne elementy do sprawdzenia w walidatorze. Bo domyślnie (bez ich podania) on nie wie co ma sprawdzać i na jakich polach. W samym walidatorze możesz po prostu zrobić sobie tablicę pól z przypisanymi do nich regułami do uruchomienia. Na koniec, przy valid() iterujesz po każdym polu, pobierasz jego wartość z $_POST i odpalasz na nim każdą regułę. Szybki przykład:

  1. class Validator
  2. {
  3. protected $items = [];
  4. protected $invalid = [];
  5.  
  6. public function addRule(string $field, Rule $rule)
  7. {
  8. if (!isset($this->items[$field]) {
  9. $this->items[$field] = [];
  10. }
  11. array_push($this->items[$field], $rule);
  12. }
  13.  
  14. public function valid(array $values)
  15. {
  16. foreach($this->items as $item => $rules) {
  17. $value = $values[$item] ?? null;
  18. forach ($rules as $rule) {
  19. if (!$rule->check($item)) {
  20. array_push($this->invalid, [
  21. $item => [
  22. 'value' => $value,
  23. 'rule' => $rule
  24. ]
  25. ] );
  26. }
  27. }
  28. }
  29.  
  30. return empty($this->invalid);
  31. }
  32.  
  33. public function getInvalid()
  34. {
  35. return $this->invalid;
  36. }
  37. }
  38.  
  39. $validator = new Validator();
  40. $validator->addRule('price', new Rule('not_empty'));
  41. $validator->addRule('price', new Rule('decimal'));
  42.  
  43. $isValid = $validator->valid($_POST);
  44. if (!$isValid){
  45. $validationErrors = $validator->getInvalid();
  46. }


Oczywiście, jeśli nie chcesz sobie ćwiczyć programowania to możesz wziąć dowolnego gotowca i go użyć tak jak pisał @viking.


--------------------
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 17.02.2020 - 02:58