Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]MySQL setters i getters
Forum PHP.pl > Forum > Przedszkole
Stron: 1, 2
sadistic_son
Cześć.
Walczę z kolejnym wymogiem projektu nad którym siedzę.
"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."
Póki co to nie użyłem setter/getter. Pokażcie proszę na przykładzie mojego poniższego kodu jak to powinno być zastosowane.

Klasa Produkt
  1. class Product
  2. {
  3.  
  4. public $productName;
  5. public $sku;
  6. public $price;
  7. public $productType;
  8. public function __construct()
  9. {
  10. $this->productName = isset($_POST['name']) ? (string) $_POST['name'] : null;
  11. $this->sku = isset($_POST['sku']) ? (string) $_POST['sku'] : null;
  12. $this->price = isset($_POST['price']) ? (float) $_POST['price'] : null;
  13. $this->productType = isset($_POST['productType']) ? (string) $_POST['productType'] : null;
  14. }
  15.  
  16. function ensureNoEmpytValues()
  17. {
  18. if (empty($this->productName) || empty($this->sku) || empty($this->price) || empty($this->productType))
  19. return false;
  20. return true;
  21. }
  22. }


Kawałek klasy ProductAdd z metodą wrzucającą do bazy:
  1. <?php
  2. class ProductAdd extends Product
  3. {
  4. public function insertNewProduct()
  5. {
  6.  
  7. if ($this->ensureNoEmpytValues() === false)
  8. return false;
  9.  
  10. $db = new DB();
  11.  
  12. $sku = $this->sku;
  13. $productName = $this->productName;
  14. $price = $this->price;
  15. $selectedType = $this->productType;
  16.  
  17.  
  18. $properties = $this->groupFullProperties();
  19.  
  20. foreach ($properties[$selectedType] as $propertyData) {
  21. $postIndex = $propertyData['property'];
  22. if (empty($_POST[$postIndex]))
  23. return false;
  24. }
  25. $queryInsertProduct = "INSERT INTO `product` (`id`, `sku`, `name`, `price`, `type`) VALUES (null, :sku, :productName , :price, :selectedType)";
  26. $db->query($queryInsertProduct);
  27. $db->bind(':sku', $sku);
  28. $db->bind(':productName', $productName);
  29. $db->bind(':price', $price);
  30. $db->bind(':selectedType', $selectedType);
  31.  
  32. $db->execute();
  33.  
  34. $lastProductId = $db->lastInsertId();
  35.  
  36. foreach ($properties[$selectedType] as $propertyData) {
  37. $propertyId = (int) $propertyData['id'];
  38. $productValue = $_POST[(string) $propertyData['property']];
  39.  
  40. $queryInsertProductProperty = "INSERT INTO `product_property` (`id`, `product_id`, `property_id`, `value`) VALUES (null, $lastProductId , $propertyId, :productValue )";
  41. $db->query($queryInsertProductProperty);
  42. $db->bind(':productValue', $productValue);
  43.  
  44. $db->execute();
  45. }
  46. }
  47. }


nospor
Ja nie wiem na kiedy masz to zrobic, ale warto by bylo bys jednak odszedl na razie od tego projektu i poprostu przelecial glowne rzeczy z OOP, poprawcowal na przykladach tam podanych i dopiero potem majac juz jakas tam wiedze z oop bral sie za ten projekt.
Bo teraz im wiecej do niego dodajesz tym coraz bledow robisz. Z tego co ci mowimy to zapamietujesz w najlepszym wypadku moze polowe, a i to nie zawsze, wiec z kazdym koljneym tematem trzeba ci na nowo mowic to co sie juz mowilo milion razy i troche to powoduje drganie zylki na czole wink.gif


Ale dobra, wypunktuje pare rzeczy, i wracam do pracy
1) klasa masie nie dobierac do zadnego POST. Klasy nie interesuje czy dane pochodza z POST czy marsa. klasa ma dostac dane jako parametr. W twoim przypadku przekaz tablice w konstruktorze Produkt i sobie ustaw co masz ustawic
Choc wg wymagan co tu napisales to w konstruktorze nic nie przekazujesz tylko uzywasz masz setter/getter
2)
public $productName;
public $sku;
public $price;
public $productType;
Naprawde nie wiesz ze productName to string a price to float i nie mozesz tego ustawic?

3)
ensureNoEmpytValues()
Nie, klasa produkt ma nie robic za walidator. Masz miec validator ktory przyjmie obiekt klasy Product i on stwierdzi czy jest wypelniony czy nie

4) juz ci mowilem, klasa nie wie o zadnych STALYCH w programie. Klasa ma dostac niezbedne dane np. w konstuktorze. Mowie tu o klasie DB ktore magicznie wie ze w programie sa stale z HOSTEM, PASSWORD itp.

5) Nie, klasa insert product pod zadnym pozorem nie dziedziczy po Produkt. Metoda tej klasy dostaje obiekt Produkt i na nim pracuje a nie dziedziczy

6) $db = new DB();
No nie. Obiekt klasy DB masz stworzyc tylko raz, gdzies np w index.php i ten obiekt masz przekazywac do klas, ktore beda go wymagaly. Poczytaj o DI (dependency injection)

7) W ostatnich tematach bylo jeszcze wiecej bledow ale juz nie pamietam


zas to o co pytasz to banalne settery, w kazdym lepszy arcie o tym masz, czyli nie

  1. public $productName;
  2. public $sku;
  3. public $price;
  4. public $productType;

a
  1. private string $name;
  2. public $sku;// co to za typ?
  3. private float $price;
  4. private string $type;

i metody

  1. public function setName(string $name): void
  2. {
  3. $this->name = $name;
  4. }
  5.  
  6. public function getName(): string
  7. {
  8. return $this->name;
  9. }
  10.  
  11. // itd


a potem w kodzie

  1. $product = new Product();
  2. $product->setName(....);


i pobranie
  1. echo $product->getName();
sadistic_son
Cytat(nospor @ 10.01.2023, 15:29:26 ) *
Ja nie wiem na kiedy masz to zrobic
Na piątek.


Cytat(nospor @ 10.01.2023, 15:29:26 ) *
warto by bylo bys jednak odszedl na razie od tego projektu i poprostu przelecial glowne rzeczy z OOP, poprawcowal na przykladach tam podanych i dopiero potem majac juz jakas tam wiedze z oop bral sie za ten projekt.
Bo teraz im wiecej do niego dodajesz tym coraz bledow robisz.
Jeśli odejdę od tego projektu, to obecnej pracy nie zmienię przynajmniej do maja, a jak zostanę w niej na dłużej to... Nie chcę myśleć.
Przerobiłem książkę i wydawało mi się to wszystko jasne. Kod z niej rozumiałem, tłumaczenia też. Ogólne zasady OOP też, a przynajmniej tak mi się wydawało. Więc stwierdziłem, że najlepszym trenerem jest praktyka i zacząłem pisać projekt. No i tutaj się okazało, że jednak wydawało mi się, że coś było jasne (póki to czytałem), a w międzyczasie również, że ta książka to szajs - że jest w niej pełno literówek, różnych błędów logicznych, że uczy złych praktyk. Więc nie chcę do niej wracać. Okazało się tez po drodze, że php zmienia się z wersji na wersję bardziej niż sądziłem, a co za tym idzie ciężej zaraz ufać różnym artykułom i samouczkom znalezionym w google, bo rzadko udaje się coś z 2022 dorwać. Stąd moje ciągłe pytania tutaj - odpowiedzi są zawsze aktualne wink.gif

Cytat(nospor @ 10.01.2023, 15:29:26 ) *
Ale dobra, wypunktuje pare rzeczy, i wracam do pracy.

Dzięki, opisałeś to jasno. Przynajmniej tak mi się wydaje, a głowę mam już napuchniętą o tej godzinie.
Mój projekt już funkcjonalnie działa. Teraz czas na poprawianie błędów w OOP - przebudowywanie klas wedle tego co napisałeś powyżej. Mam nadzieję, że jutro się z tym wyrobię, bo na czwartek zostawiam sobie javascript i wieczorem wysyłam.
nospor
No dobra, nie pozostalo w takim razie nic innego jak zyczyc powodzenia smile.gif
No to mecz nas do tego czwartku, ale nie zapominaj polowy w miedzyczasie wink.gif
sadistic_son
Cytat(nospor @ 10.01.2023, 16:55:20 ) *
No dobra, nie pozostalo w takim razie nic innego jak zyczyc powodzenia smile.gif
No to mecz nas do tego czwartku, ale nie zapominaj polowy w miedzyczasie wink.gif
Dzięki.
Uff, no to zabieram się.
JS jednak już dziś męczyłem.


Cytat(nospor @ 10.01.2023, 15:29:26 ) *
6) $db = new DB();
No nie. Obiekt klasy DB masz stworzyc tylko raz, gdzies np w index.php i ten obiekt masz przekazywac do klas, ktore beda go wymagaly. Poczytaj o DI (dependency injection)
Przeczytałem TO. Obawiam się, że nie zdążę tego opanować tak żeby jeszcze przerobić właściwie cały mój kod do (końca) jutra. Bez DI $db = new DB(); w index.php i po wywaleniu z reszty kodu (wszystkich metod z różnych klas) oczywiście nie działa.
nospor - czy pozostawienie tego tak jak jest, tj. tworzenie nowego obiektu DB(string $db_name_itd) w różnych metodach, gdzie tego potrzebuję to jest taki fatalny błąd i skreśla całą aplikację? Czy jednak da się na to przymknąć oko u kogoś kto na juniora aspiruje?
Czy wystarczy zrobić $db = new DB(); w index.php i potem do każdej metody wymagającej bazy tylko przekazywać $db jako parametr? Tak cię zrozumiałem powyżej.
insertNewUser($db, $userName);
nospor
Cytat
Czy jednak da się na to przymknąć oko u kogoś kto na juniora aspiruje?

Jesli na juniora to powinno ujsc. Nie mnie jednak nie moge powiedziec jak oni beda na to patrzec.

A dlaczago to jest blad? Bo ile tazy robisz
$db = new DB();
to tyle razy tworzysz nowe polaczenie do bazy danych. Raz pracowalem nad projektem gdzie ludzei tak robili 27 razy w jednym request i tworzylo sie 27 nowych polaczen do bazy danych, tylko dla jednego requst. A szefostwo ciagle narzekalo ze zasoby im zzera i aplikacja wolno dziala....

jesli nie chcesz tego robic jako DI, zrob z tego singleton. 10minut roboty

Przypomnij mi twoja klase DB

Zreszta tu masz szybkie wyjasnienie
https://designpatternsphp.readthedocs.io/pl...ton/README.html
sadistic_son
W chwili obecnej moja klasa DB wygląda tak:
  1. namespace nameOne;
  2.  
  3. class DB
  4. {
  5. private $dbh;
  6. private $stmt;
  7. private string $host;
  8. private string $name;
  9. private string $user;
  10. private string $pass;
  11.  
  12. public function __construct(string $host, string $name, string $user, string $pass)
  13. {
  14. $this->host = $host;
  15. $this->name = $name;
  16. $this->user = $user;
  17. $this->pass = $pass;
  18. $this->dbh = new \PDO("mysql:host=" . $this->host . ";dbname=" . $this->name, $this->user, $this->pass);
  19. }
  20.  
  21. public function query(string $query)
  22. {
  23. $this->stmt = $this->dbh->prepare($query);
  24. }
  25.  
  26. public function bind($param, $value, $type = null)
  27. {
  28. if (is_null($type)) {
  29. switch (true) {
  30. case is_int($value):
  31. $type = \PDO::PARAM_INT;
  32. break;
  33. case is_bool($value):
  34. $type = \PDO::PARAM_BOOL;
  35. break;
  36. case is_null($value):
  37. $type = \PDO::PARAM_NULL;
  38. break;
  39. default:
  40. $type = \PDO::PARAM_STR;
  41. }
  42. }
  43. $this->stmt->bindValue($param, $value, $type);
  44. }
  45.  
  46. public function execute()
  47. {
  48. $this->stmt->execute();
  49. }
  50.  
  51. public function resultSet()
  52. {
  53. $this->execute();
  54. return $this->stmt->fetchAll(\PDO::FETCH_ASSOC);
  55. }
  56.  
  57. public function lastInsertId()
  58. {
  59. return $this->dbh->lastInsertId();
  60. }
  61.  
  62. public function single()
  63. {
  64. $this->execute();
  65. return $this->stmt->fetch(\PDO::FETCH_ASSOC);
  66. }
  67.  
  68. public function rowsAffected()
  69. {
  70. return $this->stmt->rowCount();
  71. }
  72. }


Nowy obiekt w index.php:
  1. $db = new DB(DB_HOST, DB_NAME, DB_USER, DB_PASS);

Generalnie to w index zaciąga config.php przez require. W config natomiast nie mam żadnej klasy, tylko mam podefiniowane stałe do DB oraz include DB.php, Product.php oraz PageDisplay.php (która to dalej zaciąga więcej klas). Teraz na początku ProductList.view.php tworze obiekt $products = new ProductList($db); i tutaj zmienna $db jest nieznana. Coś mi świta sprzed lat, że to przez to że raz używam require a raz include. Jedno z nich chyba do zaciągniętego pliku nie przekazuje zmiennych z zaciągającego pliku. dobrze kombinuję?


Cytat(nospor @ 12.01.2023, 12:27:05 ) *
jesli nie chcesz tego robic jako DI, zrob z tego singleton. 10minut roboty
Może dla ciebie tongue.gif Dla mnie to będzie 60-90 minut czytania po 3 razy, nastepnie analiza tego kodu przez godzinę, potem wklepywanie do mnie i analizowanie przez kolejne pół dnia co zrobiłem źle, że nie działa. Potem pisanie na forum o pomoc. Łącznie - 2dni...
nospor
Cytat
Teraz na początku ProductList.view.php tworze obiekt $products = new ProductList($db)

$products powinno byc przekazane do ProductList.view.php a nie tworzone w ProductList.view.php

A jak tworzysz/owierasz ProductList.view.php ?

Cytat
W config natomiast nie mam żadnej klasy, tylko mam podefiniowane stałe do DB oraz include DB.php, Product.php oraz PageDisplay.php

Czemu w config tworzysz/zaciagasz DB i Product i PageDisplay?

No i skoro PageDisplay zarzadza caloscia, to $db masz przekazac do PageDisplay, to wtedy rzeczy w PageDisplay beda widziec $db. No to sa podstawy z Zasiegu Zmiennych
https://www.php.net/manual/en/language.variables.scope.php
sadistic_son
Cytat(nospor @ 12.01.2023, 12:50:37 ) *
Czemu w config tworzysz/zaciagasz DB i Product i PageDisplay?
Tak mi się wydawało rozsądnie na bazie tego co przerobiłem ze wspomnianej nie raz książki, której przerobienia teraz żałuję. A gdzie mam wtedy zaciągać DB i PageDisplay (Product na razie powstało ale nic jeszcze nie robi sad.gif)? W index.php ?

Cytat(nospor @ 12.01.2023, 12:50:37 ) *
No i skoro PageDisplay zarzadza caloscia, to $db masz przekazac do PageDisplay, to wtedy rzeczy w PageDisplay beda widziec $db. No to sa podstawy z Zasiegu Zmiennych
https://www.php.net/manual/en/language.variables.scope.php
Zasięg zmiennych to jeszcze ogarniam. Chyba... :| Ale zaraz to się wyjaśnie jak opiszę moją strukturę.

Tak więc w index.php mam niewiele:
  1. use nameOne\PageDisplay;
  2. use nameOne\DB;
  3.  
  4.  
  5. require('pagefiles/config.php');
  6. $displayPage = new PageDisplay($_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], $db);
  7. $displayPage->decideOnContent();

w configu definuję stałe do DB (to dobre miejsce na to , tak?) oraz zaciągam DB.php oraz PageDisplay.php.


Teraz PageDisplay wg mojego założenia miała sprawdzać którą z dwóch podstron wybrano (liste produktów lub dodawanie produktu). W index.php ją wywołuję i przekazuję w parametrach $request oraz $db. Jeszcze nie zabrałem się za jej porządkowanie, więc wiem że idzie zwymiotować jak się na nią patrzy. Tak - zaciąga stałe a nie powinna, ma w sobie $_POST a powinna go dostać w parametrze. Wiem to wszystko już, i zamierzam ją oczyścić. A zacząłem od $db.
Wygląda ona tak:
  1. namespace nameOne;
  2.  
  3. class PageDisplay
  4. {
  5. private $request;
  6. private array $recordsIds;
  7. private $db;
  8.  
  9. public function __construct($request, $db)
  10. {
  11. $this->db = $db;
  12. $requestString = explode("?", $request);
  13. $this->request = $requestString[0];
  14. }
  15. public function decideOnContent()
  16. {
  17.  
  18. if (!$this->request) {
  19. return;
  20. }
  21.  
  22. switch ($this->request) {
  23. case PRODUCT_LIST_LANDING . '/':
  24. $title = 'Product List';
  25. $pageContent = "ProductList";
  26. include("ProductList.php");
  27. if (isset($_POST['mass_delete']) && isset($_POST['product_check'])) {
  28. $this->massDelete($_POST['product_check']);
  29. }
  30. break;
  31. case PRODUCT_ADD_LANDING:
  32. $title = 'Product Add';
  33. $pageContent = "ProductAdd";
  34. include("ProductAdd.php");
  35. if (isset($_POST['save']) && isset($_POST['sku'])) {
  36. $productObject = new ProductAdd($db);
  37. if (!$productObject->checkExistingSKU($_POST['sku'])) {
  38. $productObject->insertNewProduct();
  39. }
  40. header("Location:http://" . PRODUCT_LIST_LANDING);
  41. }
  42. break;
  43. default:
  44. $title = 'Product List';
  45. $pageContent = "ProductList";
  46. include("ProductList.php");
  47. break;
  48.  
  49. }
  50. $this->displayHeader($title);
  51. require('views/' . $pageContent . '.view.php');
  52. $this->displayFooter();
  53. }
  54.  
  55. public static function displayHeader($title)
  56. {
  57. require_once("views/html/header.html");
  58. }
  59.  
  60. public static function displayFooter()
  61. {
  62. require_once("views/html/footer.html");
  63.  
  64. }
  65.  
  66. //nie miałem pomysłu gdzie ta metoda ma być, czy jako oddzielna klasa, czy jak...
  67. private function massDelete(array $recordsIds)
  68. {
  69. $idsToDel = implode(", ", array_map('intval', $recordsIds));
  70.  
  71. $this->db->query("DELETE FROM `product_property` WHERE `product_property`.`product_id` IN ($idsToDel)");
  72. $this->db->execute();
  73.  
  74. $this->db->query("DELETE FROM `product` WHERE `product`.`id` IN ($idsToDel)");
  75. $this->db->execute();
  76.  
  77. }
  78.  
  79. }


Teraz jak widać switch decyduje o tym (poprzez include) która strona ma się wyświetlić. Nie wiem czy chcę się tutaj dzielić ProductAdd.php i ProductList.php bo tam to już jest kompletny p1erdolnik i mi wstyd :|


EDIT:
to moje ProductList.php
Chyba nie wygląda jeszcze, aż tak źle, żeby mnie postawić przed ścianą egzekucyjną.
  1. namespace nameOne;
  2.  
  3. class ProductList
  4. {
  5. private $db;
  6.  
  7. public function __construct($db){
  8. $this->db = $db;
  9. }
  10. public function listProducts()
  11. {
  12. $products = $this->getProducts();
  13.  
  14. return $products;
  15. }
  16.  
  17. private function getProducts(): array
  18. {
  19. // $db = new DB();
  20. $this->db->query("SELECT product.id prodId, product.sku, product.name, product.price, property.id, property.type, property.property, property.label, product_property.id, product_property.value FROM product_property INNER JOIN property ON product_property.property_id = property.id INNER JOIN product ON product_property.product_id = product.id ORDER BY product.id DESC
  21. ");
  22. $results = $this->db->resultSet();
  23. return $results;
  24. }
  25.  
  26. public function listGroupedProducts(): array
  27. {
  28. $products = array();
  29. foreach ($this->listProducts() as $row) {
  30.  
  31. $pid = $row['sku'];
  32. if (!isset($products[$pid])) {
  33. $products[$pid] = array('name' => $row['name'], 'price' => $row['price'], 'id' => $row['prodId'], 'properties' => array());
  34. }
  35. if (!empty($row['value'])) {
  36. $products[$pid]['properties'][] = array('value' => $row['value'], 'label' => $row['label']);
  37. }
  38. }
  39. return $products;
  40. }
nospor
Cytat
Nie wiem czy chcę się tutaj dzielić ProductAdd.php i ProductList.php bo tam to już jest kompletny p1erdolnik i mi wstyd :|

Gorzej juz nie bedzie pokazuj, a potrzebuje tego by widziec co z tym $db dalej robic

No dobra, tu masz blad
$productObject = new ProductAdd($db);

przeciez nie $db a $this->db

$productObject = new ProductAdd($this->db);

zakladam ze z produktList jest podobnie
sadistic_son
Ok, to ProductList wkleiłem wyżej a tutaj największy burdel - ProductAdd. Zaznaczam, że jeszcze tutaj jest zupełnie przed czyszczeniem tych klas - używają $_POST wewnątrz, nie ma konstruktorów, setter/getter itd. Nie ma wszędzie typowania zmiennych czy tego co ma zwracać metoda. To wszystko do poprawienia jeszcze.
  1. namespace nameOne;
  2. use Product;
  3.  
  4. class ProductAdd extends Product
  5. {
  6. private $db;
  7.  
  8. public function __construct($db){
  9. $this->$db = $db;
  10. }
  11.  
  12. public function listProperties()
  13. {
  14. $properties = $this->getDistinctProperties();
  15. return $properties;
  16. }
  17.  
  18. private function getDistinctProperties()
  19. {
  20. // $db = new DB();
  21. $this->db->query("SELECT DISTINCT type FROM property ORDER BY type ASC");
  22. $results = $this->db->resultSet();
  23. return $results;
  24. }
  25.  
  26. public function listFullProperties()
  27. {
  28. $properties = $this->getFullProperties();
  29. return $properties;
  30. }
  31. private function getFullProperties()
  32. {
  33. // $db = new DB();
  34. $this->db->query("SELECT * FROM property ORDER BY type ASC");
  35. $results = $this->db->resultSet();
  36. return $results;
  37. }
  38.  
  39. public function groupFullProperties(): array
  40. {
  41. $properties = array();
  42. foreach ($this->getFullProperties() as $row) {
  43. $property = $row['property'];
  44.  
  45. $newProperty = $row['type'];
  46. if (!isset($properties[$newProperty])) {
  47. $properties[$newProperty] = array();
  48. }
  49. $properties[$newProperty][] = [
  50. 'id' => $row['id'],
  51. 'property' => $property,
  52. 'label' => $row['label'],
  53. 'description' => $row['description']
  54.  
  55. ];
  56.  
  57. }
  58. return $properties;
  59. }
  60.  
  61. public function checkExistingSKU(string $skuToCheck)
  62. {
  63. // $db = new DB();
  64. $this->db->query("SELECT sku FROM product WHERE sku = :sku");
  65. $this->db->bind(':sku', $skuToCheck);
  66.  
  67. if ($this->db->single()) {
  68. return true;
  69. }
  70. return false;
  71. }
  72.  
  73.  
  74. public function insertNewProduct()
  75. {
  76.  
  77. if ($this->ensureNoEmpytValues() === false)
  78. return false;
  79.  
  80. // $db = new DB();
  81.  
  82. $sku = $this->sku;
  83. $productName = $this->productName;
  84. $price = $this->price;
  85. $selectedType = $this->productType;
  86.  
  87.  
  88.  
  89. $properties = $this->groupFullProperties();
  90.  
  91.  
  92. foreach ($properties[$selectedType] as $propertyData) {
  93. $postIndex = $propertyData['property'];
  94. if (empty($_POST[$postIndex]))
  95. return false;
  96. }
  97. $queryInsertProduct = "INSERT INTO `product` (`id`, `sku`, `name`, `price`, `type`) VALUES (null, :sku, :productName , :price, :selectedType)";
  98. $this->db->query($queryInsertProduct);
  99. $this->db->bind(':sku', $sku);
  100. $this->db->bind(':productName', $productName);
  101. $this->db->bind(':price', $price);
  102. $this->db->bind(':selectedType', $selectedType);
  103.  
  104. $this->db->execute();
  105.  
  106. $lastProductId = $this->db->lastInsertId();
  107.  
  108. foreach ($properties[$selectedType] as $propertyData) {
  109.  
  110. $propertyId = (int) $propertyData['id'];
  111. $productValue = $_POST[(string) $propertyData['property']];
  112.  
  113. $queryInsertProductProperty = "INSERT INTO `product_property` (`id`, `product_id`, `property_id`, `value`) VALUES (null, $lastProductId , $propertyId, :productValue )";
  114. $this->db->query($queryInsertProductProperty);
  115. $this->db->bind(':productValue', $productValue);
  116.  
  117. $this->db->execute();
  118. }
  119.  
  120.  
  121. }
  122.  
  123. }


No i Product.php. Jednak coś tam robi. Nawet zapomniałem, że to napisałem.
  1. class Product
  2. {
  3.  
  4. public $productName;
  5. public $sku;
  6. public $price;
  7. public $productType;
  8. public function __construct()
  9. {
  10. $this->productName = isset($_POST['name']) ? (string) $_POST['name'] : null;
  11. $this->sku = isset($_POST['sku']) ? (string) $_POST['sku'] : null;
  12. $this->price = isset($_POST['price']) ? (float) $_POST['price'] : null;
  13. $this->productType = isset($_POST['productType']) ? (string) $_POST['productType'] : null;
  14. }
  15.  
  16. function ensureNoEmpytValues()
  17. {
  18. if (empty($this->productName) || empty($this->sku) || empty($this->price) || empty($this->productType))
  19. return false;
  20. return true;
  21. }
  22. }




EDIT:

Cytat(nospor @ 12.01.2023, 13:14:44 ) *
Gorzej juz nie bedzie pokazuj, a potrzebuje tego by widziec co z tym $db dalej robic

No dobra, tu masz blad
$productObject = new ProductAdd($db);

przeciez nie $db a $this->db

$productObject = new ProductAdd($this->db);

zakladam ze z produktList jest podobnie

A no tak, przecież $db to ona jest w index, a wewnątrz klasy to już jest $this->db smile.gif
Lecę na zakupy na obiad i za 45 minut zabieram się za porządkowanie tego bałaganu. Czy w międzyczasie byłbyś uprzejmy mi z grubsza opisać jak naprawić konstrukcję tej strony, żeby choć przypominała jakiś wzorzec projektowy? W którym miejscu najlepiej porobić setter/getter żeby wykazać że wiem o co w nich chodzi (wymóg projektu)? Jest tu jakaś klasa z której można zrobić abstrakcyjną i byloby to uzasadnione?
nospor
Jak pisalem wczesniej:
nie
$productObject = new ProductAdd($db);

a
$productObject = new ProductAdd($this->db);


No i skoro $db to obiekt klasy DB
to nie

private $db;
 
public function __construct($db){
$this->$db = $db;
}

a
private DB $db;
 
public function __construct(DB $db){
$this->$db = $db;
}

Cytat
W którym miejscu najlepiej porobić setter/getter żeby wykazać że wiem o co w nich chodzi (wymóg projektu)?

No jak zrobic setter/getter przeciez ci podalem w pierwszym poscie tego wlasnie tematu.

Cytat
Jest tu jakaś klasa z której można zrobić abstrakcyjną i byloby to uzasadnione?

Tan caly balagan to jedna wielka abstrakcja wiec juz masz wink.gif
A na powaznie, nachwile obecna nie widze gdzie to by mozna bylo dac, za duzy balagan i za malo czasu by poprawiac

class ProductAdd extends Product

Pisalem, ze ProductAdd nie moze dziedziczyc po Produkt, tylko ma dostac Produkt gdzie trzeba.

public function insertNewProduct(Product $product)
sadistic_son
Cytat(nospor @ 12.01.2023, 13:27:24 ) *
No jak zrobic setter/getter przeciez ci podalem w pierwszym poscie tego wlasnie tematu.
Tak tak, jak zrobić i w którym miejscu danej klasy to rozumiem - pisałeś. Ale moje pytanie było bardziej typu - czy dla każdej klasy to robić? Czy są jakieś uzasadnienia kiedy getter/setter nie robić? Czy w moim powyższym kodzie jest jakaś klasa w której szczególnie aż rzuca się w oczy że powinny byś gettery i settery?


Cytat(nospor @ 12.01.2023, 13:27:24 ) *
Tan caly balagan to jedna wielka abstrakcja wiec juz masz wink.gif
Serio jest aż tak źle, że nawet kandydat na juniora powinien się wstydzić?


Cytat(nospor @ 12.01.2023, 13:27:24 ) *
class ProductAdd extends Product

Pisalem, ze ProductAdd nie moze dziedziczyc po Produkt, tylko ma dostac Produkt gdzie trzeba.

public function insertNewProduct(Product $product)

Ok, clear. Nie zdążyłem tego jeszcze poprawić. I tak dziś to wygląda to wszystko już dużo lepiej niż jeszcze choćby 24h temu.


A czy sama klasa Product jest zrobiona należycie?
nospor
napisz te setter dla Product tylko.

Cytat
Serio jest aż tak źle, że nawet kandydat na juniora powinien się wstydzić?

Ja tylko mowie ze jest balagan a nie ze maszs sie wstydzic. Wybacz, nie jestem za dobry w social talks wink.gif

Cytat
A czy sama klasa Product jest zrobiona należycie?

NO teraz nie. NIe masz setterow/getterow tylko w construktorze pobierasz z POST
Dodatkowo masz tam validacje napisana a mowilem ci tez juzze walidacja ma byc gdzie indziej.
Klasa Product wg rozumienia DTO, a w tym kontekscie to bylo pisane, ma miec tyko pola, ktore chcesz wypelnic no i te settery/gettery i to wszystko
sadistic_son
Cytat(nospor @ 12.01.2023, 14:19:11 ) *
napisz te setter dla Product tylko.


Ja tylko mowie ze jest balagan a nie ze maszs sie wstydzic. Wybacz, nie jestem za dobry w social talks wink.gif


NO teraz nie. NIe masz setterow/getterow tylko w construktorze pobierasz z POST
Dodatkowo masz tam validacje napisana a mowilem ci tez juzze walidacja ma byc gdzie indziej.
Klasa Product wg rozumienia DTO, a w tym kontekscie to bylo pisane, ma miec tyko pola, ktore chcesz wypelnic no i te settery/gettery i to wszystko

Ok, rozumiem. Zabrałem się za to, ale najpierw zrobiłem sobie backup plików. A następnie sprawdziłem czy wszystkie funkcjonalności działają. I kurde nie dodaje mi nowego produktu okazało się. Doszedłem do tego że właśnie ta metoda ensureNoEmpytValues z Product zwraca false. Natomiast var dump z POST wygląda ok:
Kod
Array
(
    [save] => save
    [sku] => NoweSKU
    [name] => photos
    [price] => 120
    [productType] => Book
    [weight] => 1
}
Coś gdzieś po drodze spieprzyłem i nie potrafię znaleźć co. Wygląda na to, że metoda z klasy ProductAdd, która w chwili obecnej nadal dziedziczy po Product, nie widzi tych miennych:
$sku = $this->sku;
$productName = $this->productName;
$price = $this->price;
$selectedType = $this->productType;
Dlaczego?

W Product jest konstruktor do sku, price itd. Następnie dziedzicząca klasa nie wie co to jest $this->sku ...
nospor
Cytat
Coś gdzieś po drodze spieprzyłem i nie potrafię znaleźć co. Wygląda na to, że metoda z klasy ProductAdd, która w chwili obecnej nadal dziedziczy po Product, nie widzi tych miennych:
$sku = $this->sku;
$productName = $this->productName;
$price = $this->price;
$selectedType = $this->productType;


No logicznie przeciez.

Jesli zrobiles jak mowilem czyli
public function insertNewProduct(Product $product)

to te zmienne masz w $product->productName itd itd. No chyba ze juz gettery masz to wtedy uzyj getterow
sadistic_son
Nic jeszcze nie zrobiłem, bo od godziny (odkąd poprawiłem wszędzie wszystko odnosnie $db) to się głowię czemu nie dodaje nowego produktu.
Tak więc w chwili obecnej mam tak:
  1. <?php
  2.  
  3. class Product
  4. {
  5.  
  6. private string $productName;
  7. private string $sku;
  8. private float $price;
  9. private string $productType;
  10. public function __construct()
  11. {
  12. $this->productName = isset($_POST['name']) ? (string) $_POST['name'] : null;
  13. $this->sku = isset($_POST['sku']) ? (string) $_POST['sku'] : null;
  14. $this->price = isset($_POST['price']) ? (float) $_POST['price'] : null;
  15. $this->productType = isset($_POST['productType']) ? (string) $_POST['productType'] : null;
  16. }
  17.  
  18. function ensureNoEmpytValues()
  19. {
  20. if (empty($this->productName) || empty($this->sku) || empty($this->price) || empty($this->productType))
  21. return false;
  22. return true;
  23. }
  24. }
  25.  
  26.  
  27. /*
  28. inny plik
  29. */
  30.  
  31.  
  32. class ProductAdd extends Product
  33. {
  34. public function insertNewProduct()
  35. {
  36.  
  37. if ($this->ensureNoEmpytValues() === false)
  38. return false;
  39.  
  40. // $db = new DB();
  41.  
  42. $sku = $this->sku;
  43. $productName = $this->productName;
  44. $price = $this->price;
  45. $selectedType = $this->productType;
  46.  

Tak więc na razie metoda klasy ProductAdd dziedziczącej po Product powinna znać $this->productName prawda? A generalnie wynika z tego że ensureNoEmpytValues zwraca false, czyli nawet sama klasa Product nie wie co to za zmienne. A POST przechodzi.

Natomiast kiedy zrobię tak public function insertNewProduct(Product $product) to mam za mało argumentów.
Kod
Fatal error: Uncaught ArgumentCountError: Too few arguments to function nameOne\ProductAdd::insertNewProduct(), 0 passed in pagefiles/PageDisplay.php on line 41 and exactly 1 expected in pagefiles/ProductAdd.php:76 Stack trace: #0 pagefiles/PageDisplay.php(41): nameOne\ProductAdd->insertNewProduct() #1 /public_html/index.php(36): nameOne\PageDisplay->decideOnContent() #2 {main} thrown in pagefiles/ProductAdd.php on line 76
nospor
Kurcze, ale ty nadal dziedziczysz po Produkt.

A pewnie masz jeszcze konstruktor w ProductAdd ktory nadpisuje ci konstruktor z Produkt, temu twoje rzeczy nie sa ustawione bo konstruktor z Product sie nie odpala...
Jesli nadal chcesz miec to swoje bezsensoswne dziedziecznie to w konstuktorze ProductAdd masz wywolac konstuktor z Product


class ProductAdd extends Product
{
private $db;
public function __construct($db){
$this->$db = $db;

parent::__construct();
}
sadistic_son
Cytat(nospor @ 12.01.2023, 15:08:48 ) *
Jesli nadal chcesz miec to swoje bezsensoswne dziedziecznie to w konstuktorze ProductAdd masz wywolac konstuktor z Product
Zamierzam się go pozbyć, ale na razie chcę mieć działającą stronę (mimo chaosu w kodzie), a po uprzednich poprawkach z dziś już ona nie działa sad.gif

Dodałem konstruktor rodzica, to mnie uderzyło tym...
Kod
Fatal error
: Uncaught TypeError: Cannot assign null to property Product::$productName of type string in /home/xxx/domains/xxx/public_html/pagefiles/Product.php:12 Stack trace: #0 /home/xxx/domains/xxx/public_html/pagefiles/ProductAdd.php(12): Product->__construct() #1 /home/xxx/domains/xxx/public_html/pagefiles/views/ProductAdd.view.php(4): nameOne\ProductAdd->__construct(Object(nameOne\DB)) #2 /home/xxx/domains/xxx/public_html/pagefiles/PageDisplay.php(55): require('/home/xxx/do...') #3 /home/xxx/domains/xxx/public_html/index.php(36): nameOne\PageDisplay->decideOnContent() #4 {main} thrown in
/home/xxx/domains/xxx/public_html/pagefiles/Product.php
on line
12
Kurde, opadam z sił. Jest uczucie rezygnacji sad.gif Sprzątanie takiego bałaganu to dramat sad.gif

EDIT:
Tak, bo teraz jak tylko wejdę na stronę to konstruktor działa i sprawdza czy $_POST są podane. A że nie ma to próbuje dac im null. Ale czemu nie może przypisać?
nospor
Pokaz jak wyglada teraz ProductAdd i Product
sadistic_son
Product:
  1. <?php
  2.  
  3. class Product
  4. {
  5.  
  6. private string $productName;
  7. private string $sku;
  8. private float $price;
  9. private string $productType;
  10. public function __construct()
  11. {
  12. $this->productName = isset($_POST['name']) ? (string) $_POST['name'] : null;
  13. $this->sku = isset($_POST['sku']) ? (string) $_POST['sku'] : null;
  14. $this->price = isset($_POST['price']) ? (float) $_POST['price'] : null;
  15. $this->productType = isset($_POST['productType']) ? (string) $_POST['productType'] : null;
  16. }
  17.  
  18. function ensureNoEmpytValues()
  19. {
  20. if (empty($this->productName) || empty($this->sku) || empty($this->price) || empty($this->productType))
  21. return false;
  22. return true;
  23. }
  24. }


Oraz ProductAdd:
  1. <?php
  2.  
  3. namespace nameOne;
  4. use Product;
  5.  
  6. class ProductAdd extends Product
  7. {
  8. private DB $db;
  9.  
  10. public function __construct(DB $db){
  11. $this->db = $db;
  12. // parent::__construct();
  13. }
  14.  
  15. public function listProperties()
  16. {
  17. $properties = $this->getDistinctProperties();
  18. return $properties;
  19. }
  20.  
  21. private function getDistinctProperties()
  22. {
  23. // $db = new DB();
  24. $this->db->query("SELECT DISTINCT type FROM property ORDER BY type ASC");
  25. $results = $this->db->resultSet();
  26. return $results;
  27. }
  28.  
  29. public function listFullProperties()
  30. {
  31. $properties = $this->getFullProperties();
  32. return $properties;
  33. }
  34. private function getFullProperties()
  35. {
  36. // $db = new DB();
  37. $this->db->query("SELECT * FROM property ORDER BY type ASC");
  38. $results = $this->db->resultSet();
  39. return $results;
  40. }
  41.  
  42. public function groupFullProperties(): array
  43. {
  44. $properties = array();
  45. foreach ($this->getFullProperties() as $row) {
  46. $property = $row['property'];
  47.  
  48. $newProperty = $row['type'];
  49. if (!isset($properties[$newProperty])) {
  50. $properties[$newProperty] = array();
  51. }
  52. $properties[$newProperty][] = [
  53. 'id' => $row['id'],
  54. 'property' => $property,
  55. 'label' => $row['label'],
  56. 'description' => $row['description']
  57.  
  58. ];
  59.  
  60. }
  61. return $properties;
  62. }
  63.  
  64. public function checkExistingSKU(string $skuToCheck)
  65. {
  66. // $db = new DB();
  67. $this->db->query("SELECT sku FROM product WHERE sku = :sku");
  68. $this->db->bind(':sku', $skuToCheck);
  69.  
  70. if ($this->db->single()) {
  71. return true;
  72. }
  73. return false;
  74. }
  75.  
  76.  
  77. public function insertNewProduct()
  78. {
  79.  
  80. /* to na razie jest zakomentowane żebym w ogóle widział jakie są błędy*/
  81. // if ($this->ensureNoEmpytValues() === false)
  82. // return false;
  83.  
  84.  
  85.  
  86.  
  87. $sku = $this->sku;
  88. $productName = $this->productName;
  89. $price = $this->price;
  90. $selectedType = $this->productType;
  91.  
  92.  
  93.  
  94. $properties = $this->groupFullProperties();
  95.  
  96.  
  97. foreach ($properties[$selectedType] as $propertyData) {
  98. $postIndex = $propertyData['property'];
  99. if (empty($_POST[$postIndex]))
  100. return false;
  101. }
  102. $queryInsertProduct = "INSERT INTO `product` (`id`, `sku`, `name`, `price`, `type`) VALUES (null, :sku, :productName , :price, :selectedType)";
  103. $this->db->query($queryInsertProduct);
  104. $this->db->bind(':sku', $sku);
  105. $this->db->bind(':productName', $productName);
  106. $this->db->bind(':price', $price);
  107. $this->db->bind(':selectedType', $selectedType);
  108.  
  109. $this->db->execute();
  110.  
  111. $lastProductId = $this->db->lastInsertId();
  112.  
  113. foreach ($properties[$selectedType] as $propertyData) {
  114.  
  115. $propertyId = (int) $propertyData['id'];
  116. $productValue = $_POST[(string) $propertyData['property']];
  117.  
  118. $queryInsertProductProperty = "INSERT INTO `product_property` (`id`, `product_id`, `property_id`, `value`) VALUES (null, $lastProductId , $propertyId, :productValue )";
  119. $this->db->query($queryInsertProductProperty);
  120. $this->db->bind(':productValue', $productValue);
  121.  
  122. $this->db->execute();
  123. }
  124.  
  125.  
  126. }
  127.  
  128. }
  129.  
  130. ?>

Przyczepia się że nie wie co to jest:
$sku = $this->sku;
$productName = $this->productName;
$price = $this->price;
$selectedType = $this->productType;

Jak w product zmienię na public to za to przyczepia się że Product::$sku must not be accessed before initialization
nospor
zmien
private string $productName;

na
protected string $productName;
poniewaz dziedziczysz

analogicnzie reszta pol



No i odkomentuj ten parent::
public function __construct(DB $db){
$this->db = $db;
parent::__construct();
}
sadistic_son
Niestety to samo co wczesniej -Fatal error: Uncaught TypeError: Cannot assign null to property Product::$productName of type string in
Jak tylko wejdę na stronę to konstruktor ProductAdd próbuje przypisać $_POST które nie zostało wysłane sad.gif
  1. namespace nameOne;
  2. use Product;
  3.  
  4. class ProductAdd extends Product
  5. {
  6. private DB $db;
  7.  
  8. public function __construct(DB $db){
  9. $this->db = $db;
  10. parent::__construct();
  11. }
  12.  
  13.  
  14. //Product
  15. class Product
  16. {
  17.  
  18. protected string $productName;
  19. protected string $sku;
  20. protected float $price;
  21. protected string $productType;
  22. public function __construct()
  23. {
  24. $this->productName = isset($_POST['name']) ? (string) $_POST['name'] : null;
  25. $this->sku = isset($_POST['sku']) ? (string) $_POST['sku'] : null;
  26. $this->price = isset($_POST['price']) ? (float) $_POST['price'] : null;
  27. $this->productType = isset($_POST['productType']) ? (string) $_POST['productType'] : null;
  28. }

nospor
Cannot assign null to property Product::$productName of type string in

No bo pola sa ustawione jako teksty czy liczby a ty przypisujesz null. No komunikat mowi to wyraznie.
Nie bardzo ogarniam czemu tworzysz produkt jesli POST nie byl wyslany.Znaczy wiem czemu, wszystko przez ten balagan. No ale dobra, nie ustawiaj nullow tylko to co ma byc

czyli

$this->productName = isset($_POST['name']) ? (string) $_POST['name'] : '';
$this->sku = isset($_POST['sku']) ? (string) $_POST['sku'] : '';
$this->price = isset($_POST['price']) ? (float) $_POST['price'] : 0;
$this->productType = isset($_POST['productType']) ? (string) $_POST['productType'] : '';
sadistic_son
No tak, przypisywałem null do stringa, to jasne że się nie da.
Uff, dobra, to chociaż jestem na etapie, że funkcjonalności działają. Dziękuję.

No to dalsze poprawianie przede mną, żeby z tego chaosu wyłoniła się jakaś struktura.

Powiedz mi prosze do czego właściwie klasa Product ma służyć? Ja mam nią tylko i wyłacznie (po zrobieniu setter/getter) pobierać i wyświetlać właściwości produktu tam gdzie jest to potrzbne?

Np na szybko (bo robię obiad jedną ręką):
  1. class Product{
  2. public function setName(string $name): void
  3. {
  4. $this->name = $name;
  5. }
  6.  
  7. public function getName(): string
  8. {
  9. return $this->name;
  10. }
  11. }
i potem jak chcę spradzić np czy jest wysłane formularzem $_POST['name'] to:
  1. $product = new Product();
  2. if(isset$_POST['save']) && isset($_POST['name'])){
  3. $product->setName($_POST['name']);
  4. }
no własnie i co teraz? Brakuje mi tego logicznego zastosowania dla tej klasy. Właściwie to przyznać można że cała ta moja aplikacja to nie zupełnie OOP, tylko po prostu uzycie metod klas jak w programowaniu proceduralnym, tak sądzę.
nospor
Klase Produkt zostala ci zaproponowana wczesniej jako DTO.

Wiec klasa Produkt jest po to, bys mial ladno klase do przechowywania nazwy produkt, ceny itp.

Juz ci pisalem wczesniej wiele razy. ProduktAdd nie moze dziedziczyc po Produkt, tylko ma otrzymac produkt tam gdzie trzeba czyli np


public function insertNewProduct(Product $product)

A gdzie tam w odmentach swojego kodu, gdize wywolujesz insertNewProduct, masz ten product stworzyc czyli




$product = new Product();
if(isset$_POST['save']) && isset($_POST['name'])){
$product->setName($_POST['name']);
}
.....
.....->nsertNewProduct($product);
sadistic_son
Ok, zaczynam chwytać. Nigdzie w żadnych artykułach nie natrafiłem na takie proste pokazanie jak łaczyć znane mi proceduralne programowanie z OOP.
Dobra, a czy klasa nadrzędna w moim wypadku PageDisplay może mieć switch który centralnie robi
  1. case 'add-product': //w pasku adresu jest add-product
  2. $product = new Product();
  3. if(isset$_POST['save']) && isset($_POST['name'])){
  4. $product->setName($_POST['name']);
  5. }
  6. .....
  7. .....->nsertNewProduct($product);
Czy to jest po bożemu, albo chociaż akceptowalne (skoro to przyszły junior pisze)?
nospor
Na te chwile moze.
sadistic_son
ok.
To klasa Product nie ma mieć właściwie żadnych iinych metod oprócz setterów i getterów, tak? Skoro np walidacja czy dane $_POST są wypełnione ma być gdzie indziej.
nospor
tak

I jesli to juz bedzie oddzielna klasa i ProductAdd po nei nie bedzie dziedziczyl, to zamien spowrotem protected na private
sadistic_son
Ok, to to mi sporo wyjaśnia. Tego elementu mi chyba brakowało, żeby moc w ogóle zacząć porządkowanie tego chaosu. Dziękuję.

Hej, jakiego typu będa zmienne $dbh, $smt, $param i $value?
  1. class DB
  2. {
  3. private $dbh;
  4. private $stmt;
  5. private string $host;
  6. private string $name;
  7. private string $user;
  8. private string $pass;
  9.  
  10. public function __construct(string $host, string $name, string $user, string $pass)
  11. {
  12. $this->host = $host;
  13. $this->name = $name;
  14. $this->user = $user;
  15. $this->pass = $pass;
  16. $this->dbh = new \PDO("mysql:host=" . $this->host . ";dbname=" . $this->name, $this->user, $this->pass);
  17. }
  18.  
  19. public function query(string $query)
  20. {
  21. $this->stmt = $this->dbh->prepare($query);
  22. }
  23.  
  24. public function bind($param, $value, $type = null)
  25. {
  26. if (is_null($type)) {
  27. switch (true) {
  28. case is_int($value):
  29. $type = \PDO::PARAM_INT;
  30. break;
  31. case is_bool($value):
  32. $type = \PDO::PARAM_BOOL;
  33. break;
  34. case is_null($value):
  35. $type = \PDO::PARAM_NULL;
  36. break;
  37. default:
  38. $type = \PDO::PARAM_STR;
  39. }
  40. }
  41. $this->stmt->bindValue($param, $value, $type);
  42. }

dbh to object, tak? A co z $value która raz może być int, raz string itd? Jak mam ją typować w deklaracji metody bind ? Oraz jaki typ danych zwrócą mi tutaj poszczególne metody?
nospor
No obiekt, ale konkretnie obiekt PDO wiec

private \PDO $dbh;

Na takiej samej zasadzie jak ci typowalem wczoraj DB ale znowy nie laczysz kropek tongue.gif

Co do value to albo mixed albo union
https://www.php.net/manual/en/language.types.mixed.php

No a $param to przeciez string
sadistic_son
Cytat(nospor @ 13.01.2023, 10:04:00 ) *
Na takiej samej zasadzie jak ci typowalem wczoraj DB ale znowy nie laczysz kropek tongue.gif
Ja już nie jestem młodym 30 parolatkiem, więc mam nieco utrudniony kontakt z bazą wink.gif Zwłaszcza to zauważyłem po covidzie rok temu (serio) i nie chce minąć. chyba już tak zostanie na stałe sad.gif

a $type to też będzie string?
a $stmt ?


A taka funkcja jak poniżej, która nic nie zwraca, to powinna być :void ?
  1. public function execute()
  2. //czy tak? public function execute(): void
  3. {
  4. $this->stmt->execute();
  5. }



Albo tutaj:
  1. public function resultSet()
  2. {
  3. $this->execute();
  4. return $this->stmt->fetchAll(\PDO::FETCH_ASSOC);
  5. }
Co to mi zwraca? Object? Czyli jak powinna wyglądać pierwsza linijka?
  1. //tak?
  2. public function resultSet(): object
nospor
Starasz sie o te nowa robote, ona wymaga samodzielnosci. Ok, na poczatku mozna o cos pytac, ale latanie z pierdulami to naprawde za dlugo miejsca tam nie zagrzejesz nawet jako junior

Jkaim cudem $type to jest string?
przeciez do $type przypisujesz
$type = \PDO::PARAM_INT;

Wiec idziesz do manuala PHP i patrzysz czym jest \PDO::PARAM_INT i juz wiesz jakiego typu bedzie $type


Tak, jak funkcja nic nie zwraca to void


return $this->stmt->fetchAll(\PDO::FETCH_ASSOC);
No to samo tutaj. Co ci zwraca fetchAll() ? Obiekt? Naprawde? Bo ja wchodze do manuala i widze ze wraca jednak co innego
viking
Poczytaj sobie https://prophp.pl/advice/show/14/jak_czytac...mentacje_php%3F
Masz np https://www.php.net/manual/en/pdostatement.fetchall.php
Więc co zwraca public PDOStatement::fetchAll(int $mode = PDO::FETCH_DEFAULT): array ?
sadistic_son
Cytat(nospor @ 13.01.2023, 10:20:17 ) *
Jkaim cudem $type to jest string?
przeciez do $type przypisujesz
$type = \PDO::PARAM_INT;
Tak, wewnątrz metody przypisuję rózne wartości. Ale przecież wywołując metodę bind podaję parametry w formie $this->db->bind(':sku', $sku); więc w tym przypadku $type na wejściu będzie null. Innym razem mogę go podać i wtedy będzie stringiem, tak? Czyli powinno być public function bind(string $param, mixed $value, mixed $type = null) . Czy jednak błądzę?

Widzę w manualu że w takim przypadku $type = \PDO::PARAM_INT; to type to "PDO::PARAM_INT (int) Represents the SQL INTEGER data type.". Jednak moje pytanie dotyczyło typu wejściowego, byłem nieprecyzyjny.


Cytat(nospor @ 13.01.2023, 10:20:17 ) *
return $this->stmt->fetchAll(\PDO::FETCH_ASSOC);
No to samo tutaj. Co ci zwraca fetchAll() ? Obiekt? Naprawde? Bo ja wchodze do manuala i widze ze wraca jednak co innego
Cytat(viking @ 13.01.2023, 10:20:55 ) *
Masz np https://www.php.net/manual/en/pdostatement.fetchall.php
Więc co zwraca public PDOStatement::fetchAll(int $mode = PDO::FETCH_DEFAULT): array ?
No ok, ok, to będzie array.
nospor
$this->db->bind(':sku', $sku);
Troche sie zgubilem. Co ma sku do $type danych ktore bindujesz?
sadistic_son
To z sku to tylko przykład wywołania metody bind.
W definicji mam:
  1. public function bind(string $param, mixed $value, $type = null): void

A wywołuje ją np w taki sposób (tutaj nie podając $type w parametrze):
  1. $queryInsertProduct = "INSERT INTO `product` (`id`, `sku`, `name`, `price`, `type`) VALUES (null, :sku, :productName , :price, :selectedType)";
  2. $this->db->query($queryInsertProduct);
  3. $this->db->bind(':sku', $sku);
  4. $this->db->bind(':productName', $productName);
  5. $this->db->bind(':price', $price);
  6. $this->db->bind(':selectedType', $selectedType);

Stąd moje pytanie jaki typ danych będzie mieć $type w definicji metody bind (na wejściu), skoro raz jest na wejściu null (jak powyżej), innym razem mogę mu podać PARAM_INT. Wg mnie na wejściu będzie to mixed. public function bind(string $param, mixed $value, mixed $type = null) Tak?
nospor
W przykladach tutaj co podales zawsze jest NULL. Ale type to type od PDO a ten zawsze jest INT. Wiec twoj $type moze byc nullem albo INTem wiec


public function bind(string $param, mixed $value, ?int $type = null)

znak zapytania mowi, ze cos moze byc NULL
sadistic_son
O, i teraz się zrozumieliśmy. Dzięki za odpowiedź smile.gif

Nastepne pytanie, jeśli mogę.

Zabrałem się za naprawę klasy Product oraz usunięcie jej dziedziczenia np z ProductAdd.
W Product pozbyłem się konstruktora aby posługiwać się setterami i getterami. Wygląda ona teraz tak (kawałek):
  1. class Product
  2. {
  3.  
  4. private string $productName;
  5. private string $sku;
  6. private float $price;
  7. private string $productType;
  8. // public function __construct()
  9. // {
  10. // $this->productName = isset($_POST['name']) ? (string) $_POST['name'] : '';
  11. // $this->sku = isset($_POST['sku']) ? (string) $_POST['sku'] : '';
  12. // $this->price = isset($_POST['price']) ? (float) $_POST['price'] : 0;
  13. // $this->productType = isset($_POST['productType']) ? (string) $_POST['productType'] : '';
  14. // }
  15.  
  16. public function setProductName(string $productName): void
  17. {
  18. $this->productName = $productName;
  19. }
  20.  
  21. public function getProductName(): string
  22. {
  23. return $this->productName;
  24. }
  25.  
  26. //itd dla pozostałych zmiennych


Teraz chcę się posłużyć tą klasą. Gdy miałem konstruktor to było jasne dla mnie:
  1. $product = new Product();
  2. $productObject->insertNewProduct($product);
  3.  
  4.  
  5. // gdzie indziej tworzenie metody insertNewProduct($product):
  6. public function insertNewProduct(Product $product)
  7. {
  8. $sku = $product->sku;
  9. $productName = $product->productName;
  10. $price = $product->price;
  11. $selectedType = $product->productType;
To działało. Teraz natomiast pozbyłem się konstruktora i porobiłem settery i gettery i zastanawiam się jak powinno wyglądac wywołanie metody insertNewProduct przy użyciu Product.
  1. $product = new Product();
  2. $product->setProductName($_POST['name']);
  3. $product->setSku($_POST['sku']);
  4. $product->setPrice($_POST['price']);
  5. $product->setProductType($_POST['productType']);
  6. $productObject->insertNewProduct($product);
  7. //czy tak?
  8. //dobrze kombinuję?
No i deklaracja metody:
  1. public function insertNewProduct(Product $product)
  2. {
  3. $sku = $product->getSku();


EDIT: Tzn, że to działa to wiem. Moje pytanie to - czy robię to zgodnie ze sztuką, lub chociaż niedaleko jej.
nospor
Generalnie dobrze, ale nie tu

$sku = $product->sku;
$sku i inne jest juz prywane wiec masz uzyc getter

$sku = $product->getSku();
sadistic_son
Tak tak, to dopisałem w poprzednim poście już jako edit, bo wkleiłem wcześniejszą wersję kodu wcześniej. No ok, to działam żeby teraz przerobić całość, a jest tego od groma.
Dzięki!

a czy w konstruktorze trzeba pisać : void skoro nic nie zwraca?

nospor
Nie, konstruktor to przypadek szczegolny
sadistic_son
A co ma wskazywać typ zwracanych danych w przypadku funkcji która w zależności od warunku zwraca albo false albo np tabliczę czy string?
  1. public function test(int $myInt, string $myString)
  2. {
  3. if($this->myInt == 50){
  4. return false;
  5. }else{
  6. return $this->$myString.'siema';
  7. }
viking
Jeszcze to sobie poczytaj: https://designpatternsphp.readthedocs.io/en...ace/README.html (dla setterów)
nospor
Cytat
A co ma wskazywać typ zwracanych danych w przypadku funkcji która w zależności od warunku zwraca albo false albo np tabliczę czy string?

Jesli tak jest znaczy, ze logika funkcja jest napisana do 4 liter wink.gif

Zwracane moze byc albo DANY TYP albo NULL.
Funkcja nie powinna zwracac mieszanych typow bo to znaczy ze cos z nia jest nie tak.
Jesli zas chcesz sygnalizowac blad, to nie zwracasz false tylko rzucasz wyjatek
Salvation
Cytat(nospor @ 13.01.2023, 11:41:18 ) *
Zwracane moze byc albo DANY TYP albo NULL.

Jestem tego samego zdania, ale przetłumacz to tym co głosowali za wprowadzeniem Union Types xD
nospor
Jeszcze ani razu nie uzylem UNION w moich projektach wiec da sie wink.gif

Ale sa przypadki gddzie trzeba uzyc, jak np. tu w tej metodzie bind dla $value ktore moze byc roznego typy. Ale to tylko powinny byc bardzo nieliczne wyjatki a juz w ogole nie wyobrazam sobie funkcji, ktora zwraca UNION/mixed... grrrrrrr

Zapewne w piekle jest oddzielny kociol tylko dla ludzi uzywajacych za czesto UNION/mixed wink.gif
sadistic_son
Dobra, rozumiem.

ale w takim razie czemu np TUTAJ jest public PDO::lastInsertId(?string $name = null): string|false ?
Jak rozumiem ma tutaj zastosowanie powiedzenie "co wolno wojewodzie to nie tobie smrodzie" biggrin.gif

I jak wtedy będzie wyglądać deklaracja tej metody?
  1. public function lastInsertId()
  2. {
  3. return $this->dbh->lastInsertId();
  4. }
nospor
Metody PHP istnieja od wiekow, kiedy byla jeszcze ciemnosc i zwracali co zwracali. Teraz by zachowac kompatybulnosc wsteczna nie moga ot tak sobie wszystko pozmieniac bo miliony stron przestanie dzialac. Temu w starych metodach php masz jeszcze smietnik i sie tym nie kieruj

Zas u ciebie to albo tak:

public function lastInsertId(): int
{
return (int) $this->dbh->lastInsertId();
}


Albo tak

public function lastInsertId() ?int
{
$id = $this->dbh->lastInsertId();
return $id ? $id : null;
}

Ja zawsze osobiscie stosuje te pierwsza metode.
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-2024 Invision Power Services, Inc.