Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP]Wzorzec MVC - model
Evinek
post 19.02.2014, 20:30:21
Post #1





Grupa: Zarejestrowani
Postów: 280
Pomógł: 46
Dołączył: 23.03.2010

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


Chodzi o model, który pobiera newsy.
Mam na przykład takie coś:
  1. class News extends Model {
  2. public function getAll() {
  3. return $this->db->query('SELECT * FROM `news`')->fetchAll();
  4. }
  5. }

Muszę również pobierać newsy:
a) tylko 5 najnowszych
b) tylko usunięte (delete = 1)
c) tylko te, które mają datę publikacji mniejszą niż aktualna (publish < time())
d) tylko widoczne (visible = 1)

e) połączenie a + b, a + c, b + c, a + b + c + d i tak dalej, i tak dalej.

I pytanie, jak rozwiązać to aby nie tworzyć wielu metod, a najlepiej żeby była jedna czy dwie?

Klasa bazy danych
  1. class Database {
  2.  
  3. protected $pdo;
  4. protected $stmt;
  5.  
  6. public function __construct($type, $host, $name, $user, $pass) {
  7. $this->pdo = new PDO($type . ':host=' . $host . ';dbname=' . $name, $user, $pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
  8. }
  9.  
  10. public function query($sql, $data = array()) {
  11. $this->stmt = $this->pdo->prepare($sql);
  12. $this->stmt->setFetchMode(PDO::FETCH_ASSOC);
  13. foreach($data as $key=>$value) {
  14. if(is_int($value))
  15. $this->stmt->bindValue(':' . $key, $value, PDO::PARAM_INT);
  16. else
  17. $this->stmt->bindValue(':' . $key, $value);
  18. }
  19. $this->stmt->execute();
  20. return $this;
  21. }
  22.  
  23. public function fetch() {
  24. return $this->stmt->fetch();
  25. }
  26.  
  27. public function fetchAll() {
  28. return $this->stmt->fetchAll();
  29. }
  30.  
  31. public function rowCount() {
  32. return $this->stmt->rowCount();
  33. }
  34.  
  35. public function lastId() {
  36. return $this->pdo->lastInsertId();
  37. }
  38.  
  39. public function pdo() {
  40. return $this->pdo;
  41. }
  42. }
Go to the top of the page
+Quote Post
Turson
post 19.02.2014, 22:49:03
Post #2





Grupa: Zarejestrowani
Postów: 4 291
Pomógł: 829
Dołączył: 14.02.2009
Skąd: łódź

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


Najprostsze rozwiązanie jakie mi teraz przychodzi do głowy to przekazywanie warunku w parametrze
  1. $model->getData("WHERE delete=1");

  1. public function getData($query=null){
  2. return $this->db->query('SELECT * FROM `news` '.$query)->fetchAll();
  3. }


ale czy rozsądne, wątpię...

Ten post edytował Turson 19.02.2014, 22:49:40
Go to the top of the page
+Quote Post
vonski
post 19.02.2014, 23:25:43
Post #3





Grupa: Zarejestrowani
Postów: 292
Pomógł: 89
Dołączył: 27.12.2006
Skąd: Warszawa

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


Może coś w tym stylu:

  1. public function getMany($fields = null, $cond = null, $limit = null, $orderBy = null)
  2. {
  3. $query = "SELECT ";
  4. if(!is_null($fields)) {
  5. $query .= ... // doklejasz listę pól do zapytania
  6. } else {
  7. $query .= "* ";
  8. }
  9.  
  10. $query .= "FROM " . $this->tableName . ' ';
  11.  
  12. if(!is_null($cond)) {
  13. $query .= ... // doklejasz $cond
  14. }
  15.  
  16. // ...sprawdzasz resztę zmiennych i ewentualnie doklejasz
  17.  
  18. return $this->db->query($query);
  19. }


Użycie:

  1.  
  2. getMany('*', null, 5, "date DESC");
  3. getMany('*', "delete = 1");
  4. getMany('*', "publish < " . time());
  5. getMany('*', 'visible = 1');


Do prostych zastosowań wystarczy, do bardziej zaawansowanych zainteresowałbym się Doctrine 2, zamiast pisał coś swojego smile.gif


--------------------
Zend Certified Engineer | Microsoft Certified Professional: Programming in HTML5 with JavaScript & CSS3 | Blog
Go to the top of the page
+Quote Post
Pyton_000
post 19.02.2014, 23:29:40
Post #4





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Zrób sobie metodę np. whereBuilder z parametrami który buduje WHERE, potem w get... doklejasz to co zostało wygenerowane
Go to the top of the page
+Quote Post
Turson
post 19.02.2014, 23:33:18
Post #5





Grupa: Zarejestrowani
Postów: 4 291
Pomógł: 829
Dołączył: 14.02.2009
Skąd: łódź

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


Cytat(Pyton_000 @ 19.02.2014, 23:29:40 ) *
Zrób sobie metodę np. whereBuilder z parametrami który buduje WHERE, potem w get... doklejasz to co zostało wygenerowane

A czy nie napisałem tego samego?
Go to the top of the page
+Quote Post
Evinek
post 20.02.2014, 17:21:30
Post #6





Grupa: Zarejestrowani
Postów: 280
Pomógł: 46
Dołączył: 23.03.2010

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


Czyli ogólnie nic nowego czego bym nie wiedział. Myślałem nad tym, ale jakoś źle mi to wygląda. Nie wiem czy ktoś zauważył, ale używam bindowania więc wasze przykłady mi się nie przydadzą.
A kod w stylu:
  1. $where = array('delete = :delete', 'visible = :visible', 'publish > :publish');
  2. $data = array('delete' => $_POST['delete'], 'visible' => $_POST['visible'], 'publish' => time());
  3. $model->getMany($where, $data, 5); // $model->getMany(where, dane_do_bindowania, limit);

wydaje mi się zbyt mocno przesadzony.
Miałem i nadal mam nadzieje na inny sposób na to.
Go to the top of the page
+Quote Post
vonski
post 20.02.2014, 18:16:01
Post #7





Grupa: Zarejestrowani
Postów: 292
Pomógł: 89
Dołączył: 27.12.2006
Skąd: Warszawa

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


To może napisz chociaż jak byś chciał żeby to wyglądało. Bo "innych sposobów na to" istnieje mnóstwo, tylko ciężko wyczuć jaki Tobie się będzie podobał. Możesz np. napisać klasę, powiedzmy Query i użyć jej mniej więcej w ten sposób:

  1. $query = new Query('news');
  2. $query->fields('title, created_at')
  3. ->where('delete', array('eq' => '1'))
  4. ->where('visible', array('eq' => '1'), 'and')
  5. ->where('publish', array('eq' > time()), 'and')
  6. ->limit(10)
  7. ->orderBy('title');
  8. $query->build();


I powiedzmy, że build() zbuduje takie zapytanie: "SELECT title, created_at FROM news WHERE delete = :delete AND visible = :visible AND publish > :publish ORDER BY title ASC LIMIT 10".
Możesz potem ten obiekt $query przekazać do metody query() z Twojej klasy Database i niech już ona sobie z nim radzi - wszystkie informacje - czyli samo zapytanie jak i parametry do zbindowania - tam siedzą.
To jest jeden z wielu sposobów.. ale też może Ci się wydać mocno przesadzony... Możesz też użyć już wspomnianego Doctrine - integruje się szalenie łatwo, za pomocą composera smile.gif


--------------------
Zend Certified Engineer | Microsoft Certified Professional: Programming in HTML5 with JavaScript & CSS3 | Blog
Go to the top of the page
+Quote Post
memory
post 20.02.2014, 18:23:55
Post #8





Grupa: Zarejestrowani
Postów: 616
Pomógł: 84
Dołączył: 29.11.2006
Skąd: bełchatów

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


chyba za bardzo chcesz dobrze
Go to the top of the page
+Quote Post
vonski
post 20.02.2014, 18:33:03
Post #9





Grupa: Zarejestrowani
Postów: 292
Pomógł: 89
Dołączył: 27.12.2006
Skąd: Warszawa

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


chyba nie rozumiem smile.gif


--------------------
Zend Certified Engineer | Microsoft Certified Professional: Programming in HTML5 with JavaScript & CSS3 | Blog
Go to the top of the page
+Quote Post
memory
post 20.02.2014, 18:36:24
Post #10





Grupa: Zarejestrowani
Postów: 616
Pomógł: 84
Dołączył: 29.11.2006
Skąd: bełchatów

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


pisałem do Evinek smile.gif
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: 7.07.2025 - 14:14