Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Walidacja danych umieszczona w MVC
Forum PHP.pl > Forum > PHP > Object-oriented programming
brzoza91
Witam
Chciałbym stworzyć walidacje danych umiejscowioną w MVC. W poniższym kodzie walidacje umieściłem w kontrolerze(akcja insert). Mój cały problem sprowadza się do tego miejsca

  1. if(!$validation->isError==0){
  2.  
  3. //co tutaj zrobic
  4.  
  5.  
  6.  
  7. }else {
  8. $model=$this->loadModel('dish');
  9. $model->insert($_POST);
  10. $this->redirect('?task=dish&action=index');
  11.  
  12. }


Gdy dane są poprawne to jest ładowany model, który umieszcza ładnie i poprawnie dane w bazie danych.
Lecz co zrobić gdy dane są niepoprawne? W moim założeniu jest żeby po wprowadzeniu błędnych danych wyświetliła się dalej strona z formularzem z informacją o błędnych danych. Więc jak zrobić aby przekazać obiekt $validation do widoku z formularzem tak abym mógł potem w widoku wyciągnąć informacje o błędach


dishcontroller.php
  1. require_once ('controller.php');
  2. require_once ('validator.php');
  3.  
  4.  
  5. class DishController extends Controller{
  6.  
  7.  
  8. public function index(){
  9. $view=$this->loadView('dish');
  10. $view->index();
  11. }
  12.  
  13. //laduje widok z formularzem dodania potrawy
  14. public function add(){
  15. $view=$this->loadView('dish');
  16. $view->add();
  17. }
  18. //laduje widok z przegladem potrawy
  19. public function show(){
  20. $view=$this->loadView('dish');
  21. $view->show($_GET['id']);
  22. }
  23.  
  24. //laduje model ktory umieszcza dane w bazie
  25. public function insert(){
  26. $validation= new Validator;
  27.  
  28. $validation->MessageText=NULL;
  29. $validation->isError=0;
  30.  
  31. $dishname=$_POST['dishname'];
  32.  
  33. echo "PRZED:<br>";
  34. $validation->viewMessage();
  35.  
  36. if(!$validation->CheckString($dishname,2)){
  37. $validation->setMessage('dishname','Nazwa dania jest zbyt krótka');
  38. };
  39.  
  40. echo "PO:<br>";
  41. $validation->viewMessage();
  42.  
  43. if(!$validation->isError==0){
  44.  
  45. //co tutaj zrobic
  46.  
  47.  
  48.  
  49. }else {
  50. $model=$this->loadModel('dish');
  51. $model->insert($_POST);
  52. $this->redirect('?task=dish&action=index');
  53.  
  54. }
  55. }
  56.  
  57. public function delete(){
  58. $model=$this->loadModel('dish');
  59. $model->delete($_GET['id']);
  60. $this->redirect('?task=dish&action=index');
  61. }
  62. };




dishview.php

  1. class DishView extends View{
  2.  
  3. public function index(){
  4. $dish=$this->loadModel('dish');
  5. $this->set('dishList', $dish->getAll());
  6. $this->render('indexDish','dish/');
  7. }
  8.  
  9. public function add($obj=null){
  10. $this->render('addDish', 'dish/'); //laduje plik z formularzem addDish.html.php, formularz ten przesyła dane do akcji insert();
  11. }
  12.  
  13.  
  14. public function show($id){
  15. $dish=$this->loadModel('dish');
  16. $this->set('dishShow', $dish->getOne($id));
  17. $this->render('showDish', 'dish/');
  18. }
  19. }
thek
Jak dla mnie chyba sensowniejsze byłoby wrzucenie walidacji do modelu i tam reagowanie na tego typu sytuację. Kontroler tylko by monitorował "co jest grane". Przykładowo walidacja mogła by rzucać jakiś wyjątek informujący o nieprawidłowym jej przebiegu.
brzoza91
umieszczenie walidacji w modelu daje mi w sumie to samo, bo nie wiem jak wtedy wyświetlić stronę z formularzem i informacją o błędach.
thek
No pomyśl... Masz model z metodą, która może rzucić wyjątek w przypadku naprawdę problemów, albo strukturę danych wynikową wspartą strukturą zwracającą komunikaty błędów. Całość wywołania metody z modelu obejmujesz try-catch w razie czego, ale monitorujesz też strukturę błędów. Jeśli jest ona pusta to ok, ale jeśli nie - to reagujesz.
Pilsener
Najsensowniej jest powiązać ściśle walidację z formularzem i to niezależnie od OOP czy MVC. W strukturalnym radziłem sobie tak, że definiowałem walidację w szablonie formularza a następnie ją obsługiwałem odpowiednimi funkcjami - wystarczyło raz napisać validator a potem tylko go stosować.

Tutaj radzę na obiektach, jakoś tak logicznie:
Fomularz - obiekt
Walidator - też obiekt

Zatem:
  1.  
  2. $form = new My_Form();
  3. $validator = new My_Validator();
  4. $form->addValidator($validator);
  5.  
  6. if($form->isValid()){
  7.  
  8. }


Oczywiście walidator można dodać bezpośrednio w klasie My_Form, wtedy nie zaprzątasz sobie nim głowy wcale, w kontrolerze skupiasz się na logice aplikacji.
thek
@Pilsener: Bo to bardzo dobre podejście. Klasa walidatora powinna być osobną, bo w końcu to ona się zajmuje tym zadaniem, nie formularz sam w sobie i dzięi temu całość jest elastyczniejsza, gdyż nie ograniczamy walidacji jedynie do formularza. Możemy walidować wtedy wszelkie dane przychodzące do aplikacji, także pliki, strumienie. Walidator powinien mieć więc funkcje, która przyjmuje jakieś dane i konfrontuje je z regułami dla tych danych wybranymi oraz informuje o powodzeniu lub nie. Można jeszcze wcześniej dane przefiltrować (trimowanie, usuwanie znaków niedozwolonych itp). Przykład?
  1. $form = new Form();
  2. $form->add_data($_POST);
  3. $form->add_data($_FILES);
  4. $filters = new Filterset();
  5. $filters->add_rules(
  6. 'trim', //bez klucza, to wytrimuje wszystkie pola formularza
  7. 'zipcode' => array('expr' => '[^0-9-]*') //oczyści pole z wszystkich znaków innych niż podane w regule
  8. )
  9. );
  10. $validator = new Validator();
  11. $validator->add_rules(
  12. 'id' => array(
  13. 'not_empty',
  14. 'numeric',
  15. 'greater_than' => 0,
  16. ),
  17. 'zipcode' => array('match' => '[0-9]{2}-[0-9]{3}'),
  18. 'username' => array('custom' => array('user_func' => 'tu_funkcja_usera_do_sprawdzenia_unikatowości_nicka')),
  19. 'password' => array('min_length' => 8),
  20. 'retype_pass' => array('match_field' => 'password'),
  21. 'avatar' => array('not_empty', 'sizelimit' => '128 kB',)
  22. )
  23. );
  24. $form->apply_filters($filters);
  25. $form->apply_validator($validator);
  26. if($form->is_valid())
  27. {
  28. }

Oczywiście to przykładowo jest i może być inaczej w modelu implementowane i nie musi nawet być podobne, ale takie coś jest w miarę elastyczne, gdyż co dane wejściowe (niekoniecznie formularz!) to można reguły modyfikować, dodawać nowe operacje dla danych, czy wręcz pozwolić sobie na wywoływanie funkcji własnych. Zauważcie custom przy regułach dla pola username, gdzie można przekazać obiekt modelu User z wywołaniem funkcji sprawdzającej unikatowość. To tylko przykład, który obrazuje jak bardzo elastyczny można walidator zrobić. Przy walidacji formularza jedynie sprawdzi się czy formularz potraktowany dodanym walidatorem zawiera strukturę błędów czy może jest ona pusta. Zwróć też uwagę, że można obsłużyć bardziej złożone rzeczy. Ja w przykładzie połączyłem tablice POST i FILES smile.gif Równie dobrze mogłem posłać do walidacji uchwyt do pliku, strumień czy wywołanie z CLI. Zależnie jak bardzo klasa walidatora byłaby uniwersalna i jakie reguły bym przewidział. Jednak ich uzupełnianie byłoby bajecznie proste.
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.