Clicky

Skocz do zawartości


Zdjęcie
- - - - -

[K2] Praca z większymi formularzami - moje rozwiązanie.

10 odpowiedzi w tym temacie

  • Zaloguj się, aby dodać odpowiedź

#1 phpion

phpion

    Senior Mastah

  • Użytkownik
  • PipPipPip
  • 774 postów
  • Skąd:Sosnowiec, Dąbrowa Górnicza

Napisano 02 luty 2009 - 09:38

Witam,
chciałem przedstawić swój sposób na pracę z większymi formularzami, a konkretnie z ich przetwarzaniem, walidacją oraz zapisywaniem. Całość opiszę na podstawie istniejącego rozwiązania, nie będę go uogólniał - gdyby ktoś miał pytania to niech je zadaje. Ok, więc do dzieła.

Uwaga! Bezpośrednie wklejenie zamieszczonych źródeł nie będzie działać. Tutorial ten powinien stanowić raczej pewnego rodzaju ideę do rozwiązania problemu pracy z bardziej rozbudowanymi formularzami.

Opisywany przeze mnie formularz dotyczy produktu i zawiera:
- dane podstawowe,
- dane internacjonalizacyjne,
- powiązanie z kategoriami,
- powiązanie z atrybutami,
- galerię zdjęć.
Każda z tych sekcji powinna być odpowiednio sprawdzona (Validation) i zapisywana jest przez inny model, w związku z czym w kodzie robi się totalny bałagan. Na potrzeby tego tutoriala (w zasadzie dla większej przejrzystości) pokażę obsługę tego formularza okrojną do 3 pierwszych sekcji (czyli bez atybutów oraz zdjęć).

Cała moja idea polega na tym, aby walidację poszczególnych sekcji przenieść do osobnych plików. W związku z tym utworzyłem:
application/libraries/Validator.php:
/**
* Klasa służąca do kompleksowej walidacji danych.
*
* @package validators
*/
class Validator {
protected $errors_file = null;
protected $form = array();
protected $errors = array();
protected $validation = null;

public function __construct(array $data, $errors_file = NULL) {
$this->validation = new Validation($data);

if (!is_null($errors_file)) {
$this->errors_file = $errors_file;
}

$this->errors = $this->form;

$this->configure();
}

/**
* Metoda definiująca filtry oraz reguły sprawdzane podczas walidacji.
*
*/
protected function configure() {

}

/**
* Dokonuje sprawdzenia poprawności wprowadzonych danych.
*
* Zwraca TRUE jeśli dane są poprawne oraz FALSE jeśli są błędne.
*
* @return boolean
*/
public function validate() {
if ($this->validation->validate()) {
$this->form = $this->validation->as_array();

return TRUE;
}
else {
$this->form = arr::overwrite($this->form, $this->validation->as_array());
$this->errors = arr::overwrite($this->errors, $this->validation->errors($this->errors_file));

return FALSE;
}
}

protected function add_error($field, $name) {
$this->errors[$field] = $name;
}

/**
* Zwraca sprawdzane dane.
*
* @return array
*/
public function get_form() {
return $this->form;
}

/**
* Zwraca błędy.
*
* @return unknown
*/
public function get_errors() {
return $this->errors;
}
}

Następnie będą tworzone walidatory dla poszczególnych sekcji; walidatory te będą dziedziczyły po Validator.

Pierwszy walidator dotyczy danych produktu (sprawdzane tylko niektóre pola):
application/libraries/validators/backend/Backend_Product_Validator.php:
class Backend_Product_Validator extends Validator {
protected $errors_file = 'backend/form_error_messages/product';
protected $form = array(
'id' => '',
'sku' => '',
'producer_id' => '',
'shop_price' => '',
'catalog_price' => '',
'promotion_price' => '',
'is_novelty' => '',
'is_on_stock' => '',
'is_active' => ''
);

protected function configure() {
require_once Kohana::find_file('helpers', 'filter');

$this->validation->pre_filter('trim');
$this->validation->pre_filter('filter_float', 'shop_price');
$this->validation->pre_filter('filter_float', 'catalog_price');
$this->validation->pre_filter('filter_float', 'promotion_price');
$this->validation->add_rules('sku', 'required', 'backend_check_unique_product_sku');
$this->validation->add_rules('shop_price', 'required');
}
}


Drugi dotyczy wersji językowych:
application/libraries/validators/backend/Backend_Product_i18n_Validator.php:
class Backend_Product_i18n_Validator extends Validator {
protected function configure() {
$this->validation->pre_filter('trim');
}

public function validate() {
parent::validate();

$return = TRUE;

if ($this->form['1']['name'] == '') {
$this->add_error('empty_name', 'Tłumaczenia dla wersji polskiej są wymagane.');

$return = FALSE;
}

if ($this->form['1']['description'] == '') {
$this->add_error('empty_description', 'Tłumaczenia dla wersji polskiej są wymagane.');

$return = FALSE;
}

return $return;
}
}

Sposób jego implementacji różni się od pierwszego, gdyż nastąpiła potrzeba przeładowania metody validate(). Dodatkowo walidator ten nie opiera się na pliku z tłumaczeniami komunikatów błędów.

Trzeci walidator sprawdza czy wybrano conajmniej jedną kategorię dla produktu:
application/libraries/validators/backend/Backend_Product_category_Validator.php:
class Backend_Product_category_Validator extends Validator {
public function validate() {
parent::validate();

if (count($this->form) === 0) {
$this->add_error('empty', 'Proszę zaznaczyć przynajmniej jedną kategorię, do której przypisany zostanie produkt.');
return FALSE;
}

return TRUE;
}
}

W tym momencie mamy napisane 3 walidatory. Przydałaby się jeszcze klasa, która umożliwiałaby ich łancuchowe wywoływanie, jeden po drugim aby zautomatyzować cały proces walidacji/filtracji wprowadzanych danych. W tym celu napisałem klasę Validator_Chain:
application/libraries/Validator_Chain.php:
final class Validator_Chain {
private $validators = array();
private $form = array();
private $errors = array();

public function __construct($validators = array()) {
$this->validators = $validators;
}

public function validate() {
$validation_level = 0;

foreach ($this->validators as $k => $v) {
if ($v->validate()) {
$this->form[$k] = $v->get_form();
$validation_level++;
}
else {
$this->form[$k] = $v->get_form();
$this->errors[$k] = $v->get_errors();
}
}

return $validation_level === count($this->validators);
}

public function get_form() {
return $this->form;
}

public function get_errors() {
return $this->errors;
}
}

Ok, mamy już przygotowe odpowiednie klasy, które wspomogą proces przetwarzania formularza. Przydałoby się więc zastosować to w praktyce:
application/controllers/backend_product.php:
class Backend_product_Controller extends Backend_Controller_Core {
public function form() {
$id = (int)$this->input->get('id', 0);
$form = array();
$errors = array();

// utworzenie potrzebnych modeli
$mdl_product = new Backend_product_Model();
$mdl_product_i18n = new Backend_product_i18n_Model();
$mdl_category = new Backend_category_Model();
$mdl_product_category = new Backend_product_category_Model();

// jezeli wyslano formularz
if (request::method() == 'post') {
$id = (int)$this->input->post('id', 0);

// wczytanie klas walidatorow
require_once Kohana::find_file('libraries', 'Validator_Chain');
require_once Kohana::find_file('libraries', 'Validator');
require_once Kohana::find_file('libraries/validators/backend', 'Backend_Product_Validator');
require_once Kohana::find_file('libraries/validators/backend', 'Backend_Product_i18n_Validator');
require_once Kohana::find_file('libraries/validators/backend', 'Backend_Product_category_Validator');

// tablica obiektow konkretnych walidatorow
$validators = array(
'product' => new Backend_Product_Validator($this->input->post('product')),
'product_i18n' => new Backend_Product_i18n_Validator($this->input->post('product_i18n', array())),
'product_categories' => new Backend_Product_category_Validator($this->input->post('product_category', array()))
);

// utworzenie walidatora lancuchowego
$validator_chain = new Validator_Chain($validators);

// jezeli walidacja wszystkich sekcji przebiegla pomyslnie
if ($validator_chain->validate()) {
// pobranie wszystkich danych z walidatora lancuchowego
$form = $validator_chain->get_form();

// zapis danych produktu
$id = $mdl_product->save($id, $form['product']);

// zapis danych internacjonalizacyjnych
$mdl_product_i18n->save($id, $form['product_i18n']);
// zapis powiazan z kategoriami
$mdl_product_category->save($id, $form['product_categories']);

$this->session->set_flash('flash_confirm', 'Dane produktu zostały pomyślnie zapisane.');
url::redirect('product/form?id='.$id);
}
// wystapily bledy podczas walidacji jakiejs sekcji
else {
$this->template->flash_error = 'Wystąpiły błędy podczas zapisu danych produktu.';

// przypisanie wprowadzonych danych
$form = $validator_chain->get_form();
// oraz bledow
$errors = $validator_chain->get_errors();
}
}
else {
// pobranie danych z bazy danych
$form['product'] = $mdl_product->get($id);
$form['product_i18n'] = $mdl_product_i18n->get_list($id);
$form['product_categories'] = $mdl_product_category->get_list($id);
}

// utworzenie widoku
$this->template->content = new View('backend/product/form');
$this->template->content->id = $id;
$this->template->content->languages = Kohana::config('locale.list');
$this->template->content->categories = $mdl_category->get_tree();

$this->template->content->form = $form;
$this->template->content->errors = $errors;
}
}

Pozostał jeszcze plik widoku:
application/views/backend/product/form.php:
<?= form::open_multipart(null, array('id' => 'mainForm')) ?>
<?= form::hidden('id', $id) ?>

<?= form::open_fieldset() ?>
<legend>Dane podstawowe</legend>
<?= form::hidden('product[id]', $id) ?>

<dl>
<dt>
<?= form::label('product_sku', 'SKU:') ?>
</dt>
<dd>
<?= form::input('product[sku]', $form['product']['sku'], 'id="product_sku"') ?>
<?= form::error($errors['product'], 'sku') ?>
<?= javascript::unique_check('product', 'sku', 'product_sku', $id) ?>
</dd>

<dt>
<?= form::label('product_producer_id', 'Producent:') ?>
</dt>
<dd>
<?= form::dropdown('product[producer_id]', $producers, $form['product']['producer_id'], 'id="product_producer_id"') ?>
</dd>

<dt>
<?= form::label('product_is_novelty', 'Nowość:') ?>
</dt>
<dd>
<?= form::backend_checkbox('product[is_novelty]', pgsql::stob($form['product']['is_novelty']), 'id="product_is_novelty"') ?>
</dd>

<dt>
<?= form::label('product_is_on_stock', 'Na stanie:') ?>
</dt>
<dd>
<?= form::backend_checkbox('product[is_on_stock]', pgsql::stob($form['product']['is_on_stock']), 'id="product_is_on_stock"') ?>
<p class="help">Odznaczenie tej opcji uniemożliwia zakup danego towaru oraz wyświetla informację przy opisie informującą o braku towaru na magazynie.</p>
</dd>

<dt>
<?= form::label('product_is_active', 'Aktywny:') ?>
</dt>
<dd>
<?= form::backend_checkbox('product[is_active]', pgsql::stob($form['product']['is_active']), 'id="product_is_active"') ?>
<p class="help">Ukrywa produkt bez względu na stan magazynowy.</p>
</dd>
</dl>

<hr />
<?= form::backend_close_fieldset() ?>

<?= form::open_fieldset() ?>
<legend>Cennik</legend>

<dl>
<dt>
<?= form::label('product_shop_price', 'Cena sklepowa:') ?>
</dt>
<dd>
<?= form::input('product[shop_price]', $form['product']['shop_price'], 'id="product_shop_price" class="short"') ?> zł
<?= form::error($errors['product'], 'shop_price') ?>
<p class="help">Sklepowa cena produktu.</p>
</dd>

<dt>
<?= form::label('product_catalog_price', 'Cena katalogowa:') ?>
</dt>
<dd>
<?= form::input('product[catalog_price]', $form['product']['catalog_price'], 'id="product_catalog_price" class="short"') ?> zł
</dd>

<dt>
<?= form::label('product_promotion_price', 'Cena promocyjna:') ?>
</dt>
<dd>
<?= form::input('product[promotion_price]', $form['product']['promotion_price'], 'id="product_promotion_price" class="short"') ?> zł
<p class="help">Spośród ceny sklepowej i promocyjnej system wybiera najniższą, która będzie główną ceną dla danego produktu.</p>
</dd>
</dl>

<hr />
<?= form::backend_close_fieldset() ?>

<?= form::open_fieldset() ?>
<legend>Internacjonalizacja</legend>

<?php foreach ($languages as $l): ?>
<dl>
<dt>
<?= form::label('product_i18n_'.$l['id'].'_name', 'Nazwa produktu (<strong>'.$l['code'].'</strong>):') ?>
</dt>
<dd>
<?= form::input('product_i18n['.$l['id'].'][name]', isset($form['product_i18n'][$l['id']]) ? $form['product_i18n'][$l['id']]['name'] : '', 'id="product_i18n_'.$l['id'].'_name"') ?>
<?php if ($l['id'] == '1'): ?><?= form::error($errors['product_i18n'], 'empty_name') ?><?php endif; ?>
</dd>

<dt>
<?= form::label('product_i18n_'.$l['id'].'_description', 'Opis produktu (<strong>'.$l['code'].'</strong>):') ?>
</dt>
<dd>
<?= form::markdown_editor(array('name' => 'product_i18n['.$l['id'].'][description]', 'id' => 'product_i18n_'.$l['id'].'_description'), isset($form['product_i18n'][$l['id']]) ? $form['product_i18n'][$l['id']]['description'] : '') ?>
<?php if ($l['id'] == '1'): ?><?= form::error($errors['product_i18n'], 'empty_description') ?><?php endif; ?>
</dd>
</dl>

<hr />
<?php endforeach; ?>
<?= form::backend_close_fieldset() ?>

<?= form::open_fieldset() ?>
<legend>Kategorie</legend>

<?= category_tree::checkbox_tree($categories, 0, $form['product_categories']) ?>
<?= form::error($errors['product_categories'], 'empty') ?>
<?= form::backend_close_fieldset() ?>
<?= form::close() ?>

Zastosowałem tu kilka własnych helperów, z których najważniejszy w tej chwili to form::error:
application/helpers/pws_form.php:
class form extends form_Core {
/**
* Zwraca box z błędem.
*
* Metoda używana do wyświetlania błędów podczas walidacji formularzy.
*
* @param array $errors
* @param string $item
* @return string
*/
public static function error(&$errors, $item) {
return isset($errors[$item]) && $errors[$item] != '' ? '<p class="error">'.$errors[$item].'</p>' : '';
}
}

Metoda ta zwraca treść błędu jeżeli istnieje. Mi osobiście bardzo się przydaje takie uproszczenie przy wyświetlaniu błędów.

To w zasadzie tyle. Całość wydaje mi się dość przejrzysta i wygodna w obsłudze. Nie musimy się męczyć z X walidacjami bezpośrednio w kontrolerze - wszystko zamykamy w osobnych plikach.

Co sądzicie o takim rozwiązaniu?
Notifero - Technologie Informatyczne | Warsztat: Kohana 3.x/2.x + PostgreSQL/MySQL | Programista Kohana

#2 thejw23

thejw23

    Senior Mastah

  • Webmastahy
  • PipPipPip
  • 824 postów

Napisano 02 luty 2009 - 10:52

hmm.. sam nie wiem. rozumiem o co chodzi i jak to dziala, ale nie rozumiem tak do konca po co, poniewaz zwykla walidacja wydaje sie prostsza. moze napisze jak ja waliduje:

1) kontroler glowny z ktorego dziedziczy cala reszta ma zmienne:
	public $form_fields = array();
public $form_errors = array();
public $form_post = array();


oraz metode
    public function make_field($field,$rules=array(),$default='') {
        $this->form_fields[$field]=$default;
        $this->form_errors[$field]='';
        if (!empty($rules))
          foreach ($rules as $rule)
              $this->form_post->add_rules($field, $rule);
    }


2) sama walidacja wyglada tak:
$this->form_post  = new Validation($this->input->post()); //czyli standard
          $this->make_field('phone',array('required'));
          $this->make_field('res_email',array('required','email'));
          // i tak dalej, wszystkie pola formularza, podaje je tylko raz
          $submit=$this->input->post('submit');
      if ($this->form_post->validate() AND $post_data = $this->form_post->as_array()) { //standard
            //zapis do bazy
            $this->save($post_data); //uzywam auto_modeler, metoda zapisujaca do bazy
        } else if (!empty($submit)) {
            //nadpisanie danymi usera
            $this->form_fields = arr::overwrite($this->form_fields, $this->form_post->as_array());
            $this->form_errors = arr::overwrite($this->form_errors, $this->form_post->errors('error_messages'));         
        }
          //przypisanie wartosci
          $this->template->content->book_form->form = $this->form_fields;
          $this->template->content->book_form->errors = $this->form_errors;


3) w widoku mam:
<?php echo form::input(array('name'=>'phone','class'=>'w180'), $form['phone']); ?>
<?php echo form::error($errors['phone']);?>


i to by bylo na tyle. to jest przyklad dla jednego modelu, ale jesli bylo by ich wiecej, to prawdopodobnie wystarczy w metodzie save dodac kolejno kazdy uzywany model i przekazac mu tablice, chyba moze nawet byc cala, nawet z polami ktorych nie ma w danej tabeli, bo i tak w modelu jest lista pol ktore zostaja potem do bazy zapisane).

acha, jeszcze jedno. w automodeler dodalem:
     //this allow to have diffrent name and diffrent db key
    protected $names = array();


dzieki czemu moge miec dowolne nazwy pol w formularzu. w set key na poczatku:
	if (!empty($this->names))
    foreach ($this->names as $key=>$value)
        $this->change_key($value,$key,$data);


przykladowe names wyglada tak:
	protected $names = array(
          'state'=>'region',
          'town'=>'city',
    );




#3 phpion

phpion

    Senior Mastah

  • Użytkownik
  • PipPipPip
  • 774 postów
  • Skąd:Sosnowiec, Dąbrowa Górnicza

Napisano 02 luty 2009 - 11:15

i to by bylo na tyle. to jest przyklad dla jednego modelu, ale jesli bylo by ich wiecej, to prawdopodobnie wystarczy w metodzie save dodac kolejno kazdy uzywany model i przekazac mu tablice, chyba moze nawet byc cala, nawet z polami ktorych nie ma w danej tabeli, bo i tak w modelu jest lista pol ktore zostaja potem do bazy zapisane).

No właśnie. Walidacja danych dla innych modeli wymusza konieczność pisania coraz większej liczby reguł walidacyjnych (oraz samych walidatorów) w kontrolerze. W przypadku mojego formularza zrobił mi się mały bałagan w związku z czym poszukałem lepszego (moim zdaniem) rozwiązania.

Ponadto część pól w moim przypadku jest dynamiczna (konkretnie: internacjonalizacja) co dalej skomplikowałoby kontroler. Dzięki mojemu rozwiązaniu zamykam walidację w osobnych plikach, a w kontrolerze obsłguję jedynie sytuację przy poprawnej oraz niepoprawnej walidacji. Dla mnie takie rozwiązanie jest wygodniejsze ale każdy może mieć swoje preferencje :)
Notifero - Technologie Informatyczne | Warsztat: Kohana 3.x/2.x + PostgreSQL/MySQL | Programista Kohana

#4 mck

mck

    Jestę Blogerę

  • Admin
  • 1544 postów

Napisano 02 luty 2009 - 12:00

Ponadto część pól w moim przypadku jest dynamiczna (konkretnie: internacjonalizacja) co dalej skomplikowałoby kontroler.

wszystko fajnie, ale tu chyba przesadzasz ;) co takiego skomplikowanego może być w internacjonalizacji formularza/walidacji?
zmieniasz dynamicznie wartość configu locale.language (Kohana::config_set()) - zmienia Ci się katalog z językiem - otrzymujesz komunikaty o błędzie w wybranym języku.
to samo do zrobienia z nazwami pól formularza (Kohana::lang())
:)

#5 phpion

phpion

    Senior Mastah

  • Użytkownik
  • PipPipPip
  • 774 postów
  • Skąd:Sosnowiec, Dąbrowa Górnicza

Napisano 02 luty 2009 - 12:32

mck:
Heh, właśnie takie rozwiązanie mnie nie satysfakcjonuje. Wyświetlam pola dla wszystkich wersji językowych na raz. Dzięki temu mam wszystko co dotyczy produktu w jednym miejscu (wypełniam pola jedno pod drugim).
Notifero - Technologie Informatyczne | Warsztat: Kohana 3.x/2.x + PostgreSQL/MySQL | Programista Kohana

#6 thejw23

thejw23

    Senior Mastah

  • Webmastahy
  • PipPipPip
  • 824 postów

Napisano 02 luty 2009 - 14:39

No właśnie. Walidacja danych dla innych modeli wymusza konieczność pisania coraz większej liczby reguł walidacyjnych (oraz samych walidatorów) w kontrolerze.


nie do konca, walidacja danych z formularza odbywa sie tylko raz, nastepnie cala tablice ze wszystkimi polami przekazuje do metody save kontrolera, a tam ponownie cala tablice przekazuje do poszczegolnych metod save kazdego modelu. bez babrania sie w wybieranie ktore pola sa od ktorego modelu. jedyne ale - musze nazwac pola unikalnie, ale dzieki wspomnianej modyfikacji do auto_modeler nie jest to problem, w samym modelu okreslam jaka nazwa ktoremu polu odpowiada i tych nazw musze sie potem trzymac w formularzu. nawet przekazywanie kilku id nie powinno byc problemem, bo w formularzu moge nazwac sobie 'product', a w modelu zrobic product=>id i wtedy wszystko trafi tam gdzie trzeba i tak jak trzeba (wspominam o tym, poniewaz auto_modeler jesli jest przekazane id robi update, jesli nie to insert).

reasumujac - cala walidacja (reguly) to jest po 1 linijce kodu dla kazdego pola. jesli jest 40 pol, to po prostu wywalam to do osobnej metody, ale nie zaciemniac glownego kodu kontrolera.

ale - tak jak pisalem, ja to na razie robilem tylko dla jednej tabeli, jednego modelu. w teorii nie wydaje mi sie aby byl jakikolwiek problem jesli chodzi o powyzszy przyklad. ale to tylko teroria - do czasu, az bede potrzebowal sam tego uzyc :)

jesli chodzi o internacjonalizacje - moze wlasny helper ktory pobierze wszystkie nazwy w dostepnych jezykach i pozniej z tablicy je wyswietlac?

bardzo sobie cenie Twoje opinie, ACL jest swietny, ale tutaj wydaje mi sie, ze chyba troche za bardzo komplikujesz :)

#7 mck

mck

    Jestę Blogerę

  • Admin
  • 1544 postów

Napisano 02 luty 2009 - 16:56

Wyświetlam pola dla wszystkich wersji językowych na raz. Dzięki temu mam wszystko co dotyczy produktu w jednym miejscu (wypełniam pola jedno pod drugim).

"wyświetlam"? na pewno to chciałeś tu napisać? ;)

co do tematu, to nie każę Ci robić tak jak napisałem - ty przedstawiłeś swój sposób, ja swój. twój jest niby bardziej ergonomiczny (niby wszytko na kupie), a mój wydaje mi się być bardziej ekonomiczny i niemalże podobnie ergonomiczny :)

#8 phpion

phpion

    Senior Mastah

  • Użytkownik
  • PipPipPip
  • 774 postów
  • Skąd:Sosnowiec, Dąbrowa Górnicza

Napisano 02 luty 2009 - 20:40

"wyświetlam"? na pewno to chciałeś tu napisać? ;)

Tak, chodzi mi o wyświetlanie. Rozumiem, że Tobie chodziło o to, że edytuję opis w języku polskim, zapisuję, przełączam się na wersję angielską, edytuję, zapisuję itd. Ja natomiast wolę mieć wszystkie opisy jeden pod drugim.

Nie upieram się, że moje rozwiązanie jest idealne. Jednak bronię swojego stanowiska, że moim zdaniem rozwiązanie jest dość wygodne. Stosuję je i nie narzekam :) hehe. Tak jak pisałem wcześniej: każdy ma swoje własne preferencje i może woleć inne podejścia.

:)

@written.by.jacek:
No właśnie, opisujesz wszystko dla jednego modelu. Dla jednego modelu nie ma przecież problemu, prościej jest napisać wszystko bezpośrednio w kontrolerze. Nie ma sensu bawić się w tworzenie osobnych plików walidatorów, dołączanie ich bla bla bla. W takim przypadku wygodniej zastosować standardową walidację. Wygodniej bo prościej. Spróbuj jednak w standardowy sposób zrealizować przykład jaki opisałem (w tym upload plików). Ja właśnie pisząc to standardowo stwierdziłem: "hola, przecież można zrobić to lepiej" i wówczas powstał pomysł z *_Validator i Validator_Chain.
Notifero - Technologie Informatyczne | Warsztat: Kohana 3.x/2.x + PostgreSQL/MySQL | Programista Kohana

#9 thejw23

thejw23

    Senior Mastah

  • Webmastahy
  • PipPipPip
  • 824 postów

Napisano 02 luty 2009 - 21:33

niedlugo bede musial walidowac kilka modeli i upload plikow - sprawdze i jesli po mojemu sie nie da to na pewno skorzystam z Twojego rozwiazania. fajnie, ze dzielisz sie swoimi pomyslami, mam nadzieje, ze moje 'marudzenie' tego nie zmieni :P

#10 phpion

phpion

    Senior Mastah

  • Użytkownik
  • PipPipPip
  • 774 postów
  • Skąd:Sosnowiec, Dąbrowa Górnicza

Napisano 02 luty 2009 - 21:54

Nie twierdzę, że się nie da. Da się. Mój sposób jest po prostu innym zapisałem "standardowego", zapisem bardziej hmmm atomowym? :) hehe. Jednak równie dobrze walidację można zrobić poprzez ify jednak dla wygody korzysta się z bardziej kompleksowych rozwiązań jak Validation.

PS: każde "marudzenie" jest jak najbardziej cenne jeżeli jest dobrze uargumentowane. Na szczęście na tym forum tak właśnie jest więc wszelkie wymiany zdań i poglądów są jak najbardziej pozytywne.
Notifero - Technologie Informatyczne | Warsztat: Kohana 3.x/2.x + PostgreSQL/MySQL | Programista Kohana

#11 thejw23

thejw23

    Senior Mastah

  • Webmastahy
  • PipPipPip
  • 824 postów

Napisano 23 luty 2009 - 14:49

dodam tylko, ze sprawdzilem swoja wersje i dziala. czyli mam 1 wiekszy formularz na ktory skladaja sie dane z 2 modeli (tabel w bazie).  ja to robie tak:

1) pobieram z bazy polaczone dane dla jednego konkretnego wpisu(sql z palca), sa one pozniej przypisane do widoku
$kwiatki = $kwiatki_searcher->get_kwiatki($id);

2) tworze modele
$bratki_model = new Bratki_Model();
$storczyki_model = new Storczyki_Model();

3) tworze pola do walidaji, nadajac im unikalne nazwy
$this->make_field('kolce'); //itd wszystkie pola

4) ustalam aliasy dzieki ktorym pola nie pokrywajace sie z nazwa kolumny w bazie trafia tam gdzie trzeba
$bratki_model->aliases=array('lodyga'=>'has_lodyga','smierc'=>'trujacy');

5) ustalam pola ktorych wcale nie chce zmieniac
$storczyki_model->skip=array('smierdzi');

6) walidacja i zapis
if ($this->form_post->validate(array_merge($this->input->post(), $_FILES))) {
   if (!$this->upload_check('bratek_photo')) unset($this->form_fields['bratek_photo'']); //sprawdzenie uploadu
   $bratki_model->set_fields($this->form_fields)
   $storczyki_model->set_fields($this->form_fields)
   $bratki_model->save();
   $storczyki_model->save();
}


nic nie musze rozbijac, przypisywac czesci danych z formularza to jednego modelu, czesci do drugiego itp. dany model zapisuje tylko dane ktore sa mi potrzebne, mam pelna dowolnosc w nazywaniu pol formularza.

nie chce tutaj na nowo dyskusji zaczynac, po prostu sprawdzilem, dziala, podzielilem sie tym faktem.




Użytkownicy przeglądający ten temat: 0

0 użytkowników, 0 gości, 0 anonimowych