2016-02-10 10 views
7

Możliwe jest sprawdzanie poprawności żądania za pomocą reguł dla dodatkowych pól lub usunięcie tych pól z żądania?Sprawdzanie poprawności lub usuwanie dodatkowych pól w języku laravel

Prosty przykład, mam FormRequest obiekt z reguł:

public function rules() { 
     return [ 
      'id' => 'required|integer', 
      'company_name' => 'required|max:255', 
     ]; 
    } 

A kiedy się żądanie POST z innych dziedzin Chcę dostać błędu/wyjątku w sterowniku lub chcę się tylko pola id i Company_Name , bez żadnych innych. Istnieje jakakolwiek cecha tego typu w laravel, czy muszę zrobić to po swojemu?

+0

Próbuję zrozumieć, co chcesz. Masz na myśli, kiedy formularz jest zaksięgowany z wieloma polami w formularzu, powiedzmy, jak 5 pól imię, nazwisko, kraj, płeć, wiek i chcesz wybrać tylko dwa pola ignorujące innych, powiedzmy tylko płeć, kraj? – Digitlimit

+0

Powinna to być pierwsza linia obrony dla wprowadzania dodatkowych pól w formularzu przez agressor. Kiedy mam formularz z tymi 5 polami, to chcę tylko te pola w żądaniu po stronie serwera, jeśli ktoś doda jakiekolwiek inne pole o wartości, to chcę odrzucić to żądanie lub usunąć te dodatkowe pola z żądania. – Son

Odpowiedz

6

Twoja prośba o wpis z laravel ma więcej rzeczy niż tylko dane wejściowe formularza, więc musisz sprawdzić prośbę, aby zobaczyć, co jest w środku.

Aby dostać tylko pola, które chcesz można użyć:

$request->only(['fieldname1', 'fieldname2', 'fieldname3']); 

lub

$request->except(['fieldnameYouDontWant1', 'fieldnameYouDontWant2', 'fieldnameYouDontWant3']); 

wykluczyć te, których nie chcesz.

+0

Tak, wiem o tym. Zrobiłem to przez zastąpienie metody sprawdzania poprawności w klasie FormRequest, ale zastanawiałem się, czy istnieje lepszy sposób? – Son

0

Możesz to zrobić za pomocą kontrolera. Możesz wysłać tylko dwa lub niektóre pola do bazy danych. Użyj $request->only() zamiast $request->all() i podaj tablicę danych, które chcesz zapisać w bazie danych. store() metoda swoich controller „s powinna wyglądać następująco:

public function store(Request $request) 
{ 
    ModelName::create($request->only(['id','company_name'])); 
    return redirect('RouteName'); 
} 
+0

Tak, to będzie działać, ale chcę użyć FormRequests do tego, nie chcę określić drugi raz, co powinno być w mojej formie. Po raz pierwszy robię to w FormRequest przy użyciu reguł, chcę ponownie użyć tych zasad. Kiedy masz dużo formularzy w aplikacji, łatwo zapomnieć o czymś. – Son

1

Zrobiłem to metodą obejścia validate() w klasie FormRequest.

abstract class MyFormRequest extends FormRequest { 
    public function validate() { 
     foreach ($this->request->all() as $key => $value) { 
      if (!array_key_exists($key, $this->rules())) { 
       throw new ValidationException("Field " . $key . " is not allowed."); 
      } 
     } 
     parent::validate(); 
    } 
} 

Myślę, że to nie jest najlepszy sposób, ale to działa. Należy uaktualnić go, aby pokazać informacje o wszystkich błędnych pól naraz :)

0

mam nowe rozwiązanie tego problemu, należy utworzyć nową funkcję w swojej klasie żądanie forma:

public function only_in_rules(){ 
    return $this->only(array_keys($this->rules())); 
} 

Następnie w kontrolerze, call $request->only_in_rules() insteads z $request->all()

-1

Aby wyjąć kluczyk ze wniosek w laravel, użyj:

$request->request->remove('key') 
2

Robi się trochę trudniejsze, kiedy zaczynam się ja nto zagnieżdżone sprawdzanie poprawności elementu tablicy, szczególnie jeśli dotyczy to symboli wieloznacznych. Umieść to w niestandardowej klasie Request i wprowadź ją do swojej metody kontrolera. Powinien obejmować wszystkie przypadki.

public function authorize() 
{ 
    //Dot notation makes it possible to parse nested values without recursion 
    $original = array_dot($this->all()); 
    $filtered = []; 
    $rules = collect($this->rules()); 
    $keys = $rules->keys(); 
    $rules->each(function ($rules, $key) use ($original, $keys, &$filtered) { 
     //Allow for array or pipe-delimited rule-sets 
     if (is_string($rules)) { 
      $rules = explode('|', $rules); 
     } 
     //In case a rule requires an element to be an array, look for nested rules 
     $nestedRules = $keys->filter(function ($otherKey) use ($key) { 
      return (strpos($otherKey, "$key.") === 0); 
     }); 
     //If the input must be an array, default missing nested rules to a wildcard 
     if (in_array('array', $rules) && $nestedRules->isEmpty()) { 
      $key .= ".*"; 
     } 

     foreach ($original as $dotIndex => $element) { 
      //fnmatch respects wildcard asterisks 
      if (fnmatch($key, $dotIndex)) { 
       //array_set respects dot-notation, building out a normal array 
       array_set($filtered, $dotIndex, $element); 
      } 
     } 
    }); 

    //Replace all input values with the filtered set 
    $this->replace($filtered); 

    //If field changes were attempted, but non were permitted, send back a 403 
    return (empty($original) || !empty($this->all())); 
} 
+1

Ładne rozwiązanie! Zmieniłem '$ rules = explode ('|', $ rules);' na 'if (is_string ($ rules)) {$ rules = explode ('|', $ rules); } ', aby działało również dla reguł opartych na tablicach. –

+0

Zaktualizował fragment kodu, aby uwzględnić tę zmianę. Dzięki! – Claymore

2

Można używać z wyjątkiem metody zamówienie, które dadzą Ci pola oprócz podanych polach

$request = $request->except('your_field'); 

jeśli chcesz usunąć wiele pól z wniosku można przekazać tablicę pól

$request = $request->except(['field_1','field_2',...]) 

Reference: Laravel requests

0

Zaczynając forma laravel 5.5 można wywołać validate metoda bezpośrednio pod adresem Request np.

class YourController extends Controller 
{ 

    public function store(Request $request) { 

     $cleanData = $request->validate([ 
     'id' => 'required|integer', 
     'company_name' => 'required|max:255', 
     ]); 

     // Now you may safely pass $cleanData right to your model 
     // because it ONLY contains fields that in your rules e.g 

     $yourModel->create($cleanData); 
    } 
}