Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Всем доброго дня!
Как я понимаю проблема в том, что в сессию не сохраняются данные формы и текст ошибок валидации. Если я все тоже самое делаю, но без валидации данных в Контроллере, то в сесиию все отлично сохраняется.
Есть простая вью с формой отправки данных (через шаблонизатор 'blade'):
<!--Main content-->
@section('main_content')
<pre>
{{ var_dump( Session::all() ) }} <!-- Or - var_dump( Session::all() and var_dump( Session::all()['_old_input']['name'] ); -->
</pre>
<!---->
<div class="row center-block">
<div class="col-lg-offset-3 col-md-offset-3 col-sm-offset-3 col-lg-6 col-md-6 col-sm-6 col-xs-12">
<form method="POST" action="<?='/contact';?>"> <!-- <?//=route('contact');?> Or в удвоенных фиг.скобках route('contact') -->
<div class="form-group">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" name="name" value="{{ old('name') }}" placeholder="Enter Name">
</div>
<div class="form-group">
<label for="email">Email address:</label>
<input type="email" class="form-control" id="email" name="email" value="{{ old('email') }}" placeholder="Enter E-mail">
</div>
<div class="form-group">
<label for="site">Site:</label>
<input type="text" class="form-control" id="site" name="site" value="{{ old('site') }}" placeholder="Enter Site">
</div>
<div class="form-group">
<label for="text_area">Text:</label>
<textarea class="form-control" id="text_area" name="text_area" rows="3" placeholder="Some text....."> {{ old('text_area') }} </textarea>
</div>
<div class="checkbox">
<label><input type="checkbox" name="checkbox"> Remember me</label>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div> <!--/class="col-"-->
</div> <!--/class="row"-->
@endsection
<!--/Main content-->
Есть простой Контроллер `ContactController.php`
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class ContactController extends Controller {
public function show( Request $request, $prm=false ){
$my_array = ['title1'=>'This variable `$title1` content', 'title2'=>'This variable `$title2` content', 'title3'=>'This variable `$title3` content']; //массив
$my_array2 = ['one'=>array('param1'=>'This variable `param1` content', 'param2'=>'This variable `param2` content', 'param3'=>'This variable `param3` content'),
'two'=>array('param4'=>'This variabl e `param4` content', 'param5'=>'This variable `param5` content', 'param6'=>'This variable `param6` content')
];
$my_array3 = array(
'title'=>'Contact',
'data'=>[ 'one'=>'list 1',
'two'=>'list 2',
'three'=>'list 3',
'four'=>'list 4',
'five'=>'list 5',
],
'dataI'=>['list-1','list-2','list-3','list-4','list-6','list-6'],
'bvar'=>true,
'script'=>"<script>alert('Hello! ++')</script>"
);
/** VALIDATION on Request */
if( $request->isMethod('post') ) {
//$request->session()->reflash();
//$request->session()->keep(['name', 'email', 'site', 'text_area']);
//$request->session()->reflash();
//dump( $request->session()->all() );
$rules = [
'name' => 'required|max:10',
'email' => 'required|email',
//'site'=>'required',
//'text_area'=>'required',
];
$messages = [
'required' => 'The :attribute field is required.',
];
$this->validate($request, $rules, $messages);
dump( $request->all() );
dump( $request->session()->all() );
}
if( view()->exists('default.contact') ){
return view('default.contact')
->withMydata($my_array2)
->withMydata2($my_array)
->withMydata3($my_array3);
}
else { abort(404); }
}
} //__/class ContactController
По идее,когда валидация данных по установленным правилам успешна для кадого из перечисленных полей Формы, то код после инициализации процесса валидации (строка $this->validate($request, $rules, $messages);) будет выполнен и я получаю dump того, что в POST и того, что будет записано в сессию. Когда валидация успешна, данные в Форме не должны оставаться, а вот когда валидация провалена, то должно генерироваться исключение и должен происходить редирект на предыдущую страницу, а данные, сохраняться в сессии и, благодаря указанной конструкции в вьюхе
value="{{ old('name') }}" отображаться в полях. Но у меня этого не происходит.
Если я верно ввожу данные в форму, чтобы валидация была успешна, - я вижу распечатку POST, что значит, валидация таки успешно прошла (и правила то действуют, указанные в Контролллере), но вот когда я ввожу не верные для валидирования данные, чтоб провалить ее, то и сохраненных данных в полях я не вижу, что как я понимаю, должно быть автоматически в этом механизме валидации заложено.
Скажу также, что разрешение на запись flash()-данных, да и вообще запись в сессию, как я понимаю, я тоже прописал в `/app/Http/Kernel.php`
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
];
При этом, как я говорил, если я не буду в контроллере проводить валидацию данных, и установлю $request->flash(); чтобы данные из POST записывались в сессию одноразово, то они записываются и в Форме остаются, т.е. тут все работает корректно.
Но используя валидацию, я эту строку $request->flash(); удаляю, т.к. судя по документации механизм валидации сам это делает и это писать не нужно.
Кто подскажет, что я забыл прописать или сделал не верно, что у меня не работает валидация совместно с записью в сессию и отображением после провала валидации и соответственно редиректа, Формы с данными заполненными при отправки поста?
Не в сети
Если вы хотите получить старые input при ошибке валидации, их нужно вернуть.
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
Изменено vladislavTkachenko (10.07.2017 16:47:05)
Не в сети
))) такая конструкция у меня не работает.
В Доке сказано - если входящие данные не проходят проверку с учетом правил, Laravel автоматически перенаправляет пользователя на предыдущую страницу. Кроме того, все ошибки валидации будут автоматически записаны во flash-переменные.
Значит в сессию все должно записываться и редирект на предыдущую страницу осуществляется так и есть , сами же поля я возвращаю во вьюхе, вытаскивая из сессии. По ходу если я назначаю валидацию в Контроллере, то в сессию данные перестают записываться.
Не в сети
vladislavTkachenko, а вы когда такой код в контроллере прописывали, larevel у вас видел метод make()
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
----------------------------
Как я могу видеть то валидация отрабатывает и ее правила действуют, но я не вижу отображения ошибок валидации, когда она не пройдена и данных в полях input при заполнении Формы при редиректе обратно.
Изменено littus (11.07.2017 11:05:58)
Не в сети
Ну конечно метод видит laravel. Для вывода в форму используйте что-то такое..
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
Не в сети
vladislav, Я так и сделал во вью прописал:
@if( count($errors) > 0 )
<div class="alert alert-danger">
<ul>
@foreach( $errors->all() as $error ) <li>{{ $error }}</li> @endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('contact') }}">
..........
..........
В своем Контроллеле указал:
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()) {
return back()->withErrors($valitor)->withInput();
}
плюс в Контроллере дополнительно указал:
use Illuminate\Validation\Validator;
Выдается ошибка:
FatalErrorException in ContactController.php line 64:
Call to undefined method Illuminate\Validation\Validator::make()
Изменено littus (11.07.2017 11:20:15)
Не в сети
use Validator;
а не
use Illuminate\Validation\Validator;
Изменено vladislavTkachenko (11.07.2017 11:22:12)
Не в сети
Если я ставлю
use Validator;
у себя в Контроллере app/Http/Controllers/Admin/ContactController.php
то мне редактор кода подсвечивает
undefined class validatior
Не в сети
Validator с большой буквы))
Не в сети
)) Разумеется с большой буквы
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
//use Illuminate\Validation\Validator;
use Validator;
class ContactController extends Controller {
public function show( Request $request, $prm=false){
$my_array = ['title1'=>'This variable `$title1` content', 'title2'=>'This variable `$title2` content', 'title3'=>'This variable `$title3` content']; //массив
$my_array2 = ['one'=>array('param1'=>'This variable `param1` content', 'param2'=>'This variable `param2` content', 'param3'=>'This variable `param3` content'),
'two'=>array('param4'=>'This variabl e `param4` content', 'param5'=>'This variable `param5` content', 'param6'=>'This variable `param6` content')
]; //двумерный Массив
$my_array3 = array(
'title'=>'Contact',
'data'=>[ 'one'=>'list 1',
'two'=>'list 2',
'three'=>'list 3',
'four'=>'list 4',
'five'=>'list 5',
],
'dataI'=>['list-1','list-2','list-3','list-4','list-6','list-6'],
'bvar'=>true,
'script'=>"<script>alert('Hello! ++')</script>"
);
/** VALIDATION on Request */
if( $request->isMethod('post') ) {
$rules = [
//'name' => 'bail|required|max:10',
'name' => 'exists:users,name',
//'email' => 'required|email',
//'site'=>'required',
//'text_area'=>'required',
];
$messages = [
'required' => 'The :attribute field is required.',
];
/*
$this->validate($request, $rules, $messages);
dump( $request->all() );
dump( $request->session()->all() );
*/
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
dump( $request->all() );
}
$title_contact_page = 'Contact';
$this->show_controller_method[] = 'show()';
if( view()->exists('default.contact') ){
return view('default.contact')
->withMydata($my_array2)
->withMydata2($my_array)
->withMydata3($my_array3)
->withTitlecontactpage($title_contact_page);
}
else { abort(404); }
}
}
Изменено littus (11.07.2017 11:53:18)
Не в сети
if( $request->isMethod('post') ) {
$rules = [
'name' => 'required',
];
$validator = \Validator::make($request->all(), $rules);
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
}
Запустил у себя, все ок.
Не в сети
Вот я чувствую, что дело не только в этом, я когда прописываю
use Validator;
у себя в Контролллере, то редактор кода уже его подсвечивает как undefined class Validatior. Но класс то есть, иначе валидация вообще бы не прходила.
Может быть при установке что-то не доставилось? Я через Composer ставил, все как нужно. Как теперь понять в чем дело? (((
Изменено littus (11.07.2017 12:17:55)
Не в сети
Ещё получить валидатор можно так
$validator = $this->getValidationFactory()->make($request->all(), $rules, $messages);
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
Не в сети
Подсвечивает потому что это фасад, для него алиса прописан в app.php.
Можно поставить https://github.com/barryvdh/laravel-ide-helper, тогда в ide все норм станет).
Вам правильно выше ответили, попробуйте добавить withInput(request->input())
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()) {
return back()->withInput($request->input())->withErrors($validator);
}
Не в сети
Огромное спасибо всем отписавшимся за помощь, - разобрался, все работает как нужно теперь.
Не знаю, почему не отработала конструкция, хотя должна и так работать (напомню проект на laravel 5.2):
$this->validate($request, $rules)
dump( $request->all() );
Но я у себя сделал так и все стало работать и корректно (возвращаться при провале валидации "старые" поля с заполненными данными при отправке Формы и выводится ошибки валидации):
/** VALIDATION on Request */
if( $request->isMethod('post') ):
$rules = [
'name' => 'required|max:10',
'email' => 'required|email',
'site'=>'required',
];
$messages = [
'required' => 'The :attribute field is required.',
];
$validator = \Validator::make($request->all(), $rules);
if( $validator->fails() ) {
$request->flash();
return view('default.contact')
->withMydata($my_array2)
->withMydata2($my_array)
->withMydata3($my_array3)
->withTitlecontactpage($title_contact_page)
->withInfoMethodController($this->show_controller_method)
->withErrors($validator)
->withInput( $request->all() );
}
dump( $request->all() );
endif;
1. Если линию прописать именно так (без обратного слеша перед Validator) $validator = Validator::make($request->all(), $rules); будет выводиться ошибка `Class 'App\Http\Controllers\Admin\Validator' not found`
2. Конструкции с return back()->withInput($request->input())->withErrors($validator); а также return redirect()->back()->withErrors($validator)->withInput($request->input()); - у меня не отрабатывают. И единственная успешная комбинация, которая все корректно вывела и сделала как должно быть у меня - приведена выше.
3. Вместо ->withInput( $request->all() ); можно прописать и ->withInput( $request->input() ) - тоже работает.
4. Вместо $validator = \Validator::make($request->all(), $rules); можно прописать $validator = $this->getValidationFactory()->make($request->all(), $rules); обратившись непосредственно к методу getValidationFactory() - тоже ОК - работает.
Изменено littus (12.07.2017 18:05:09)
Не в сети
... `Class 'App\Http\Controllers\Admin\Validator' not found`"
Чтобы этого не было, нужно импортировать имя класса (use Validator;), иначе идет обращение к классу Validator в текущем пространстве имен.
И еще, к первому посту, вы не там ожидате old input. Когда валидация валится, происходит redirect, следовательно get запрос, а у вас дамп стоит в ветке if $request->isMethod('post'). Советую сделать два отдельных action для get и post соответсвенно.
Изменено llvllaestro (12.07.2017 20:17:03)
Не в сети
Чтобы этого не было, нужно импортировать имя класса (use Validator;), иначе идет обращение к классу Validator в текущем пространстве имен.
я немного уточню – напрямую импортировать фасады из корневого неймспейса \ – нежелательно. причина в том, что сторонние библиотеки и расширения пхп добавляют в корень свои классы и там запросто можно импортировать чего-то не того. самый распространённый случай – пхп-расширение php-redis добавляет в корень класс Redis который перекрывает одноимённый фасад. работать гарантированно не будет и по какой причине – без бутылки не разберёшься
правильным является импорт фасадов из собственного неймспейса фасадов \Illuminate\Support\Facades, для валидатора это будет класс \Illuminate\Support\Facades\Validator. он полностью идентичен \Validator но гарантирует отсутствие конфликтов с окружением
а ещё интереснее – использовать биндинг параметров метода и контракты. в этом случае нам достаточно будет на экшен добавить параметр $validator с тайпхинтом на \Illuminate\Contracts\Validation\Factory. в этом случае мы избавляемся от статических зависимостей и можем покрывать этот код тестами – просто в тестах в качестве параметра будет передаваться не настоящий валидатор, а его mock
ну и пример кода конечно, куда без этого. на всякий случай скажу что пишу по памяти, не копипаста
<?php
namespace App\Http\Controllers;
use \Illuminate\Contracts\Validation\Factory as ValidationFactory;
class MyController extends Controller
{
public function myAction(ValidationFactory $factory)
{
$validator = $factory->make(…);
…
}
}
а ещё есть формреквесты – они валидацию выполняют до того как данные попадут в контроллер, и возвращают ошибки, данные форм с редиректами, json-ответы и так далее – автоматически. то есть код валидации из контроллера можно будет просто убрать. это хорошая идея, тонкий контроллер – хороший контроллер
Не в сети
llvllaestro, да, спасибо, он у меня был прописан как
use Validator;
, потом я экспериментировал с подключениями Классов и удалил его.
constb, супер, спасибо за возможные варианты и исчерпывающую инфу.
Изменено littus (13.07.2017 18:02:34)
Не в сети
Немного продолжу ))))
Что я не верно сделал с учетом передела валидации через собственный Класс `Request` и, + как мне советовали, я разделил роуты для GET и POST и определил для них отдельные методы в своем Контроллере.
1. app/Http/routes.php
Route::get('/contact_form/{prm?}', ['uses'=>'Admin\ContactformController@show_form_get'])->name('contact_form');
Route::post('/contact_form', ['uses'=>'Admin\ContactformController@show_form_post']);
2.. app/Http/Requests/ContactRequest.php - мой пользовательский Класс-Request с правилами валидации:
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class ContactRequest extends Request
{
public function authorize()
{
return true; //false.
}
public function rules()
{
return [
'name' => 'required|max:10',
//'name' => 'exists:users,name',
'email' => 'required|email',
'site'=>'required',
];
}
} //__/class ContactRequest
3. app/Http/Requests/ContactRequest.php - мой Контроллер с обработкой POST и GET (теперь разделенных по отдельности):
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Requests\ContactRequest; //свой Класс `ContactRequest` с правилами валидации
use App\Http\Controllers\Controller;
use \Illuminate\Support\Facades\Validator;
class ContactformController extends Controller {
public $show_controller_method = array(__METHOD__);
//__________________________________________________________________________________________________________________
/** Method handler http-request with GET
*/
public function show_form_get( ){
$this->show_controller_method[] = 'showform()';
if( view()->exists('default.contact_form') ){
return view('default.contact_form')->withInfoMethodController($this->show_controller_method);
}
else { abort(404); }
} //__/public function show_form_get()
/** Method handler http-request with POST
*/
public function show_form_post( ContactRequest $request ){
/** VALIDATION on Request */
if( $request->isMethod('post') ):
dump( $request->all() );
endif; //__/if( $request->isMethod('post') )
$this->show_controller_method[] = 'showform()';
if( view()->exists('default.contact_form') ){
return view('default.contact_form')->withInfoMethodController($this->show_controller_method);
}
else { abort(404); }
}
} //__/class ContactformController
4. Вью осталась таже, - т.е. там прописаны возвращение данных
value="{{ old('name') }}" value="{{ old('email') }}" и т.д. ...
а также отображение ошибок валидации ежели оные имеются:
@if( count($errors) > 0 )
<div class="alert alert-danger">
<ul>
@foreach( $errors->all() as $error ) <li>{{ $error }}</li> @endforeach
</ul>
</div>
@endif
Сейчас как и прежде сама валидация работает (если она проходит успешно, - я вижу dump() поста, который я прописал в методе public function show_form_post ) Контроллера. Если валидация валится, то как и прежде редирект, но не ошибок валидации ни данных предыдущих input`ов нет.
По идее, должно работать. Почему нет?
Не в сети
Видимо проблемы с сессией. Советую вам пройти серию уроков на laracasts. Обратите внимание на настройки middleware в Kernel. Если есть время начните с 1 эпизода.
Не в сети
Ну вот же я прописал в Kernel.php доступ на запись в сессиию и запись ошибок. - https://prnt.sc/fvmmvu
До того как я переделал через отдельный пользовательский Класс Request работало же.
Не в сети
Может кто-то еще подскажет, но мне сходу трудно сказать где ошибка, по идее должно работать. Поэтому я предлагаю вам попробовать начинать с нуля, если у вас есть время. А с таким наставником (из уроков), точно не упустите ничего из виду. Также вот урок по FormRequests. Удачи
Изменено llvllaestro (14.07.2017 15:38:38)
Не в сети
По идее, должно работать. Почему нет?
ну это конечно гадание на кофейной гуще, но вот мои варианты:
1) дополнительный редирект после того как произошёл редирект – инпуты и ошибки закидываются в сессию «одноразово», то есть доступны только на следующем запросе. если по какой-то причине следующий запрос закончился также редиректом – они не «доживут» до того чтобы попасть в форму. проверяется открытием вкладки Network в DevTools браузера, отключением очистки списка при переходе и внимательным изучением того, что происходит при отправке формы
2) инпуты и ошибки на самом деле есть в сессии, просто что-то идёт не так при их отображении. проверяется установкой laravel-debugbar если он ещё не установлен и вдумчивым изучением вкладки Session на тему что в ней там такое есть после редиректа
сам FormRequest отдаёт редирект как положено. см \Illuminate\Foundation\Http\FormRequest::response()
Не в сети