Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]MySQL setters i getters
Forum PHP.pl > Forum > Przedszkole
Stron: 1, 2
sadistic_son
Czyli bezczelnie przerabiamy string z PDO na int. Czaję. Dzięki.
nospor
lastInsertId z PDO to metoda uniwersalna. Rozne silniki jako ID maja albo teksty, albo inty itp
Ty uzywasz mysql i jako ID masz inty, wiec mozna spokojnie to co zwraca lastInsertId rzutowac na INT
sadistic_son
Rozumiem. Dzięki.



A wracając do setter/getter....
Oto kawałek klasy ProductList
  1. class ProductList
  2. {
  3. private DB $db;
  4.  
  5. public function __construct(DB $db){
  6. $this->db = $db;
  7. }
  8. public function listProducts()
  9. {
  10. $products = $this->getProducts();
  11. return $products;
  12. }
  13.  
  14. private function getProducts(): array
  15. {
  16. $this->db->query("SELECT zapytanie dluuugie");
  17. $results = $this->db->resultSet();
  18. return $results;
  19. }
  20.  
  21. public function listGroupedProducts(): array
  22. {
  23. $products = array();
  24. foreach ($this->listProducts() as $row) {
  25. //sortowanie w tablicy, w tym temacie niewazne
  26. }
  27. return $products;
  28. }


Metody getProducts oraz listProducts wziąłem właściwie z książki, modyfikując jedynie zapytanie SELECT. Czemu tutaj jest to tak zrobione? Po co w ogóle jest listProducts ? Nie lepiej zostawić tylko getProducts i mieć już stworzony przy okazji getter dla wylistowanych produktów? Nastepnie zmieniając nazwę z listGroupedProducts na getGroupedProducts otrzymuję getter dla pogrupowanych produktów, czy tak?

Czy getter/setter to właściwie tylko nazewnictwo i mozna przyjąć że jak coś zwraca np pogrupowane rekordy z bazy to będzie to getter?

Czy może istnieć getter bez settera i odwrotnie? Tzn istnieć może i kod będzie działał, ale czy tak się robi?

Męcze te gettery i settery pamiętając o wymaganiu projektu:
"Logika MySQL powinna być obsługiwana przez obiekty z właściwościami, zamiast bezpośrednich wartości kolumn. Proszę użyć setters i getters aby to osiągnąć oraz nie zapomnieć użyć ich do zapisu i wyświetlania logiki."
nospor
listProducts wydaje sie zbedne, tak.

Zas z ta logika co pisali to chyba im chodzi, ze zamiast zwracac tablice z rekordami w postaci tablicy, masz zwraca tablice obiektow, wtym wypadku obiektow Product
viking
W sumie zwracał CI już na to uwagę ale po co wprowadzasz zmienne które nie mają żadnego celu?
  1. $products = $this->getProducts();
  2. return $products;
  3.  
  4. // powinno być
  5. return $this->getProducts();
sadistic_son
Cytat(viking @ 13.01.2023, 13:52:53 ) *
W sumie zwracał CI już na to uwagę ale po co wprowadzasz zmienne które nie mają żadnego celu?
  1. $products = $this->getProducts();
  2. return $products;
  3.  
  4. // powinno być
  5. return $this->getProducts();
Ok, rzeczywiście. Wiesz... tak jak powyżej ponoć robią początkujący programiści, bo tak jest niby czytelniej. Moje przyzwyczajenie. Ale wiem że nie powinno się tak robić, bo tym sposobem alokuję podwójnie pamięć, zupełnie zbędnie.



Cytat(nospor @ 13.01.2023, 13:35:46 ) *
Zas z ta logika co pisali to chyba im chodzi, ze zamiast zwracac tablice z rekordami w postaci tablicy, masz zwraca tablice obiektow, wtym wypadku obiektow Product
Czekaj bo lekko się teraz pogubiłem. Masz na myśli w tym wypadku tak jak już mam via getProducts(); czy masz na myśli że w klasie ProductList mam jakoś wrzucać to co zwraca mi np getProducts do Product poprzez settery klasy Product?
nospor
No pewnie listGroupedProducts powinna juz zwracac tablice oboektow (producktow)
Ale twoje produkty maja jeszcze wlasciwosci wiec pewnie musisz rozszerzyc klase Product o te wlasciwosci/properties
sadistic_son
No dobra, to rozszerzyłem klasę Product o $properties:
  1. class Product
  2. {
  3. private int $productId;
  4. /*
  5. inne zmienned
  6. */
  7. private array $properties;
  8.  
  9. /*
  10. inne settery i gettery
  11. */
  12.  
  13. public function setProperties(array $properties): void
  14. {
  15. $this->properties = $properties;
  16. }
  17.  
  18. public function getProperties(): array
  19. {
  20. return $this->properties;
  21. }
  22.  
  23. }

Następnie zmodyfikowałem listGroupedProducts tak aby zwracała tablicę obiektów:
  1. public function listGroupedProducts(): array
  2. {
  3. $products = array();
  4. $productObject = new Product();
  5. foreach ($this->getProducts() as $row) {
  6. // foreach ($this->listProducts() as $row) {
  7.  
  8. $pid = $row['sku'];
  9. if (!isset($products[$pid])) {
  10. // $products[$pid] = array('name' => $row['name'], 'price' => $row['price'], 'id' => $row['prodId'], 'properties' => array());
  11. $products[$pid] = array('name' => $productObject->setproductName($row['name']), 'price' => $productObject->setproductPrice($row['price']), 'id' => $productObject->setproductId($row['prodId']), 'properties' => array());
  12. }
  13. if (!empty($row['value'])) {
  14. $products[$pid]['properties'][] = $productObject->setProperties(['value' => $row['value'], 'label' => $row['label']]);
  15. }
  16. }
  17. return $products;
  18. }
Lecz edytor podpowiada mi tutaj w przedostatniej linijce (nie licząc domknięć nawiasów), że "assigning void from a function setProperties". No jest void bo każdy setter ma ustawione void, więc czemu tylko p[rzy tym jednym się czepia?
W ogóle dobrze tutaj rozumuję? To miałeś na mysli mówiąc że ta metoda powinna zwracać tablicę obiektów?
nospor
array('name' => $productObject->setproductName($row['name']), 'price' => $productObject->setproductPrice($row['price']),
No ale co to jest?
Raz ze tak jak mowi edytor, przypisujesz dla 'name' wartosc funkcji setProductName ktora nic nie zwraca. No gdzie sens i logika?
A po drugie czemu znowu tworzysz tablice tablic? Masz tworzyc tablice obiektow

  1. public function listGroupedProducts(): array
  2. {
  3. $products = array();
  4.  
  5. foreach ($this->getProducts() as $row) {
  6. $product = new Product();
  7. $product->setName($row['name']);
  8. //... reszta pol
  9.  
  10. $products[] = $product;  
  11. }
  12. return $products;
  13. }
sadistic_son
No ok, ale w takim razie co ma być w ttych warunkach, bo już zgłupiałem:
  1. public function listGroupedProducts(): array
  2. {
  3. $products = array();
  4. foreach ($this->getProducts() as $row) {
  5. $product = new Product();
  6. $product->setProductName($row['name']);
  7. $product->setSku($row['sku']);
  8. $product->setPrice($row['price']);
  9. $product->setProductId($row['sku']);
  10. $product->setProductId($row['prodId']);
  11.  
  12.  
  13. // $pid = $row['sku'];
  14. if (!isset($products[$row['sku']])) {
  15. // $products[$pid] = array('name' => $row['name'], 'price' => $row['price'], 'id' => $row['prodId'], 'properties' => array());
  16.  
  17. }
  18. if (!empty($row['value'])) {
  19. // $products[$row['sku']]['properties'][] = $product->setProperties(['value' => $row['value'], 'label' => $row['label']]);
  20. }
  21. $products[] = $product;
  22. }
  23. return $products;
  24. }


EDIT:
nie no zaraz, nowy obiekt mam tworzyć wewnątrz pierwszego warunku, aco w takim razie w drugim?
  1. public function listGroupedProducts(): array
  2. {
  3. $products = array();
  4. foreach ($this->getProducts() as $row) {
  5.  
  6.  
  7. if (!isset($products[$row['sku']])) {
  8. $product = new Product();
  9. $product->setProductName($row['name']);
  10. $product->setSku($row['sku']);
  11. $product->setPrice($row['price']);
  12. $product->setProductId($row['sku']);
  13. $product->setProductId($row['prodId']);
  14. // $products[$pid] = array('name' => $row['name'], 'price' => $row['price'], 'id' => $row['prodId'], 'properties' => array());
  15.  
  16. }
  17. if (!empty($row['value'])) {
  18. $product->setProperties(['value' => $row['value'], 'label' => $row['label']]);
  19. // $products[$row['sku']]['properties'][] = $product->setProperties(['value' => $row['value'], 'label' => $row['label']]);
  20. }
  21. $products[] = $product;
  22. }
  23. return $products;
  24. }
Tak?
Nie no to też bez sensu bo przecież pierwszy warunek nigdy nie będzie spełniony. Tzn zawsze będzie empty.
Na końcu musi być tak:
$products[$row['sku']] = $product;


EDIT2:
Na takim czymś stanąłem:
  1. public function listGroupedProducts(): array
  2. {
  3. $products = array();
  4. foreach ($this->getProducts() as $row) {
  5.  
  6.  
  7. if (!isset($products[$row['sku']])) {
  8. $product = new Product();
  9. $product->setProductName($row['name']);
  10. $product->setSku($row['sku']);
  11. $product->setPrice($row['price']);
  12. $product->setProductId($row['prodId']);
  13. // $products[$pid] = array('name' => $row['name'], 'price' => $row['price'], 'id' => $row['prodId'], 'properties' => array());
  14. $properties = array();
  15.  
  16. }
  17. if (!empty($row['value'])) {
  18. $properties[] = ['value' => $row['value'], 'label' => $row['label']];
  19. $product->setProperties($properties);
  20. // $products[$row['sku']]['properties'][] = $product->setProperties(['value' => $row['value'], 'label' => $row['label']]);
  21. }
  22. $products[$row['sku']] = $product;
  23. }
  24. return $products;
  25. }
I chyba to jest to co ma być bo tablica przypomina ta co była wcześniej, zanim tworzyliśmy tablicę obiektów:
Kod
Array
(
    [MBL-0005] => Product Object
        (
            [productId:Product:private] => 399
            [productName:Product:private] => Mebel 5
            [sku:Product:private] => MBL-0005
            [price:Product:private] => 105
            [properties:Product:private] => Array
                (
                    [0] => Array
                        (
                            [value] => 95
                            [label] => Width (cm)
                        )

                    [1] => Array
                        (
                            [value] => 125
                            [label] => Length (cm)
                        )

                    [2] => Array
                        (
                            [value] => 65
                            [label] => Height (cm)
                        )

                )

        )

    [FLM-0004] => Product Object
        (
            [productId:Product:private] => 398
            [productName:Product:private] => Film 4
            [sku:Product:private] => FLM-0004
            [price:Product:private] => 14
            [properties:Product:private] => Array
                (
                    [0] => Array
                        (
                            [value] => 654
                            [label] => Size (MB)
                        )

                )

        )

    [KSK-0004] => Product Object
        (
            [productId:Product:private] => 397
            [productName:Product:private] => Ksiazka 4
            [sku:Product:private] => KSK-0004
            [price:Product:private] => 14
            [properties:Product:private] => Array
                (
                    [0] => Array
                        (
                            [value] => 0.4
                            [label] => Weight (kg)
                        )

                )

        )
nospor
  1.  
  2. public function listGroupedProducts(): array
  3. {
  4. $products = array();
  5. foreach ($this->getProducts() as $row) {
  6.  
  7.  
  8. if (!isset($products[$row['prodId']])) {
  9. $product = new Product();
  10. $product->setProductName($row['name']);
  11. $product->setSku($row['sku']);
  12. $product->setPrice($row['price']);
  13. $product->setProductId($row['sku']);
  14. $product->setProductId($row['prodId']);
  15.  
  16. $products[$row['prodId']] = $product;
  17.  
  18. }
  19. if (!empty($row['value'])) {
  20. $products[$row['prodId']]->addProperty($row['value'], $row['label']);
  21. }
  22.  
  23. }
  24. return $products;
  25. }


I w klasie Product dopisz metode
addProperty(string $value, string $label)

ktora bedzie dodawala kolekne property do tablicy properties produktu
sadistic_son
Cytat(nospor @ 13.01.2023, 15:42:28 ) *
ktora bedzie dodawala kolekne property do tablicy properties produktu
Wybacz, ale nie rozumiem jak ta metoda ma wyglądać. O tej godzinie to w ogóle już mało rozumiem sad.gif

To masz na myśli?
  1. public function addProperty(string $value, string $label)
  2. {
  3. $this->setProperties(['value' => $value, 'label' => $label]);
  4. }
nospor
masz ddoac a nie nadpisac.


....
private array $properties = [];

...


public function addProperty(string $value, string $label): void {
$this->properties[] = [
'value' => $value,
'label' => $label
];
}
sadistic_son
No tak. Oczywiste... sad.gif
Ech, czas na dłuższą przerwę bo już nie myslę...
Dzięki za pomoc nospor. Liczę, że dziś wieczorem wyślę projekt (lub jutro rano, bo cała noc przede mnąwink.gif).


Hej, pytanie stricte z typu "co autor miał na myśli" smile.gif I tutaj chciałbym się dowiedzieć jak ty nospor uważasz - czy biorąc pod uwagę poniższe:
""Logika MySQL powinna być obsługiwana przez obiekty z właściwościami, zamiast bezpośrednich wartości kolumn. Proszę użyć setters i getters aby to osiągnąć oraz nie zapomnieć użyć ich do zapisu i wyświetlania logiki."
to można uznać, że spełniam warunek (poniżej) posługiwania sie getter/setter przy zapisie?
  1. if (isset($_POST['save']) && isset($_POST['sku']) && isset($_POST['name']) && isset($_POST['price']) && isset($_POST['productType'])) {
  2. $product = new Product();
  3. $product->setProductName($_POST['name']);
  4. $product->setSku($_POST['sku']);
  5. $product->setPrice($_POST['price']);
  6. $product->setProductType($_POST['productType']);
  7.  
  8. $productObject = new ProductAdd($this->db);
  9. if (!$productObject->checkExistingSKU($product->getSku())) {
  10. $productObject->insertNewProduct($product);
  11. }
  12.  
  13. /*
  14. oraz w innym pliku metoda insertNewProduct, a przynajmniej jej kawałek, bez większości bebechów
  15. */
  16.  
  17. public function insertNewProduct(Product $product)
  18. {
  19. if ($this->ensureNoEmpytValues($product) === false)
  20. return false;
  21.  
  22. $sku = $product->getSku();
  23. $productName = $product->getProductName();
  24. $price = $product->getPrice();
  25. $selectedType = $product->getProductType();
  26.  
  27. // tutaj pętal forach - nie ważne
  28.  
  29. $queryInsertProduct = "INSERT INTO `product` (`id`, `sku`, `name`, `price`, `type`) VALUES (null, :sku, :productName , :price, :selectedType)";
  30. $this->db->query($queryInsertProduct);
  31. $this->db->bind(':sku', $sku);
  32. $this->db->bind(':productName', $productName);
  33. $this->db->bind(':price', $price);
  34. $this->db->bind(':selectedType', $selectedType);
  35. $this->db->execute();
  36.  
  37. $lastProductId = $this->db->lastInsertId();


Przed wywołaniem metody do zapisu są settery. W ciele metody do zapisu są gettery. No to chyba spełniam to wymaganie przy zapisie, co? Jeśli też tak to rozumiesz to (chyba) skończyłem... smile.gif
nospor
no chyba tak

Tylko ne tworz takich cudow
$sku = $product->getSku();

przeciez mozsesz od razu:
$this->db->bind(':sku', $product->getSku());
sadistic_son
Cytat(nospor @ 13.01.2023, 18:26:36 ) *
Tylko ne tworz takich cudow
$sku = $product->getSku();

przeciez mozsesz od razu:
$this->db->bind(':sku', $product->getSku());
Tak, teraz będe się właśnie takich rzeczy pozbywać, wywalać moje komentarze, wszelkie echo 'dupa' i var dumpy wywalać, itp, itd. Ale to już można po kolacji przy piwku wink.gif I wysyłam. Dzięki wielkie za nieoceniona pomoc!


Hej, tak jeszcze jedna rzecz mi nie daje spokoju w moim kodzie. Metoda powinna dostać dane z POST w parametrze, a u mnie w jednym przypadku tak nie jest i metoda dostaje $_POST w ciele funkcji. Dzieje się to tutaj: if (empty($_POST[$propertyData['property']])) oraz tutaj: $this->db->bind(':productValue', $_POST[(string) $propertyData['property']]);
Nie wiem jak przekazać do parametru tą wartość POST, bo nie znam jej indeksu - jest pobierany z bazy na podstawie wypełnionych pól i wybranej wartości z SELECT. Czy powienienm poniższy fragmencik wkomponować w wywołanie metody?
  1. $properties = $this->groupFullProperties();
  2. foreach ($properties[$product->getProductType()] as $propertyData) {
  3. if (empty($_POST[$propertyData['property']]))
  4. return false;
  5. }



Metodę wywołuję tak:
  1. if (isset($_POST['save']) && isset($_POST['sku']) && isset($_POST['name']) && isset($_POST['price']) && isset($_POST['productType'])) {
  2. $product = new Product();
  3. $product->setProductName($_POST['name']);
  4. $product->setSku($_POST['sku']);
  5. $product->setPrice($_POST['price']);
  6. $product->setProductType($_POST['productType']);
  7. $productObject = new ProductAdd($this->db);
  8. if (!$productObject->checkExistingSKU($product->getSku())) {
  9. $productObject->insertNewProduct($product);
  10. }
  11. header("Location:http://" . PRODUCT_LIST_LANDING);
  12. }



Tutaj kawałek klasy z omawianą metodą:
  1. public function insertNewProduct(Product $product)
  2. {
  3. if ($this->ensureNoEmpytValues($product) === false)
  4. return false;
  5. $properties = $this->groupFullProperties();
  6. foreach ($properties[$product->getProductType()] as $propertyData) {
  7. if (empty($_POST[$propertyData['property']]))
  8. return false;
  9. }
  10. $this->db->query("INSERT INTO `product` (`id`, `sku`, `name`, `price`, `type`) VALUES (null, :sku, :productName, :price, :selectedType)");
  11. $this->db->bind(':sku', $product->getSku());
  12. $this->db->bind(':productName', $product->getProductName());
  13. $this->db->bind(':price', $product->getPrice());
  14. $this->db->bind(':selectedType', $product->getProductType());
  15. $this->db->execute();
  16. $lastProductId = (int) $this->db->lastInsertId();
  17. foreach ($properties[$product->getProductType()] as $propertyData) {
  18. $propertyId = $propertyData['id'];
  19. $this->db->query("INSERT INTO `product_property` (`id`, `product_id`, `property_id`, `value`) VALUES (null, $lastProductId, $propertyId, :productValue )");
  20. $this->db->bind(':productValue', $_POST[(string) $propertyData['property']]);
  21. $this->db->execute();
  22. }
  23.  
nospor
Oj chyba sie zgubilem. O co dokladnie pytasz?
sadistic_son
Chodzi mi o to, że:

W formularzu mam pole select z którego wybieram rodzaj produktu. Jak jest to np mebel to pojawiają się inputy dla wysokości, szerokości i długości. Dla dvd pojawia się rozmiar (MB), itd. Teraz wywołując metodę $productObject->insertNewProduct($product); podaję jej jako parametr obiekt $product w którym to za pomocą getterów mam ustawione wartości pozostałych inputów, ale bez tych dodawanych dynamicznie (szerokośc, wysokość, rozmiar itd - $_POST['width'] itd) bo w momencie wywoływania tej metody nie wiem jeszcze które z inputów zostały poprzez select dodane do formularza. Dowiaduję się tego dopiero wewnątrz metody, poprzez odwołanie bezpośrednio do $_POST[$propertyData['property']] tworzonego w forach (spójrz na kod powyżej). I traz moje pytanie to - jak mam przekazać w parametrze to $_POST['width'] (albo $_POST['size'] albo dowolne inne wysłane) przy wywołaniu insertNewProduct($product) zamiast wrzucać je w ciele metody?

Czy powinienem poniższy kawałek (który obecnie jest tylko w ciele medoty insertNewProduct) równierz wykonywać przy sprawdzeniu czy w ogóle wywowłać insertNewProduct?

  1. $properties = $this->groupFullProperties();
  2. foreach ($properties[$product->getProductType()] as $propertyData) {
  3. if (!empty($_POST[$propertyData['property']])) //wywołaj insertNewProduct
Oczywiście trzeba ten kawałek zmodyfikować by dodawał do obiektu $product też tablicę zawierającą $_POST[$propertyData['property']].
nospor
Poprostu do metody przekaz caly $_POST i po sprawie.
Normalnie bys przekazal obiekt Request jak cie prosilem tyle razy, ale ze nie napisales to przekazuj caly $_POST
sadistic_son
No ok, ale co w tej klasie Request miałoby być? Nie napisałem jej, bo kiedy dopytywałem o czyszczenie POST to mi doradziłeś, że wystarczy bindowanie do bazy oraz htmlspecialchars do wyświetlania POST wystarczy. Oraz pisałeś też że czyszczeni POST powinno być w oddzielnej klasie właściwie. Więc nie mam pomysłu jak ta klasa w ogóle ma wyglądać i po co być.

Coś w TYM stylu? Wiem, że to sprzed 11 lat...
viking
Dawałem ci wcześniej linki do klas na github. Nie możesz zajrzeć i zobaczyć co w nich jest? Na tym też polega programowanie. Patrzeć jak piszą lepsi.
nospor
Cytat
Nie napisałem jej, bo kiedy dopytywałem o czyszczenie POST to mi doradziłeś, że wystarczy bindowanie do bazy oraz htmlspecialchars do wyświetlania POST wystarczy. Oraz pisałeś też że czyszczeni POST powinno być w oddzielnej klasie właściwie.

No ale to nie moja wina ze sie zafiksowales na tym czyszczeniu i nie czytales co sie do ciebie innego pisze.

Pisalem ci wyraznie, ze w Request na poczatek masz mie getPost() getGet() getByKey() getUri
takie podstawowe metody ktore zwracaja rzeczy ktorych uzywasz z request.

Inni, jak juz viking wspomnial, tez podawali ci linki do przykladowych klas. Takze nie, nikt ci tutaj nie doradzal bys rezygnowal z klasy Request.
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.