Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 10.07.2017 14:36:06

Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Всем доброго дня!
Как я понимаю проблема в том, что в сессию не сохраняются данные формы и текст ошибок валидации. Если я все тоже самое делаю, но без валидации данных в Контроллере, то в сесиию все отлично сохраняется.

Есть простая вью с формой отправки данных (через шаблонизатор '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(); удаляю, т.к. судя по документации механизм валидации сам это делает и это писать не нужно.

Кто подскажет, что я забыл прописать или сделал не верно, что у меня не работает валидация совместно с записью в сессию и отображением после провала валидации и соответственно редиректа, Формы с данными заполненными при отправки поста?

Не в сети

#2 10.07.2017 16:44:46

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Если вы хотите получить старые input при ошибке валидации, их нужно вернуть.

        $validator = Validator::make($request->all(), $rules, $messages);
        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

Изменено vladislavTkachenko (10.07.2017 16:47:05)

Не в сети

#3 10.07.2017 18:22:21

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

))) такая конструкция у меня не работает.

В Доке сказано  - если входящие данные не проходят проверку с учетом правил, Laravel автоматически перенаправляет пользователя на предыдущую страницу. Кроме того, все ошибки валидации будут автоматически записаны во flash-переменные.
Значит в сессию все должно записываться и редирект на предыдущую страницу осуществляется так и есть , сами же поля я возвращаю во вьюхе, вытаскивая из сессии. По ходу если я назначаю валидацию в Контроллере, то в сессию данные перестают записываться.

Не в сети

#4 11.07.2017 11:03:04

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

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)

Не в сети

#5 11.07.2017 11:09:30

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Ну конечно метод видит laravel. Для вывода в форму используйте что-то такое..

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

Не в сети

#6 11.07.2017 11:18:54

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

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)

Не в сети

#7 11.07.2017 11:21:38

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

use Validator;

а не

use Illuminate\Validation\Validator;

Изменено vladislavTkachenko (11.07.2017 11:22:12)

Не в сети

#8 11.07.2017 11:43:49

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Если я ставлю

use Validator;

у себя в Контроллере app/Http/Controllers/Admin/ContactController.php
то мне редактор кода подсвечивает 

undefined class validatior 

Не в сети

#9 11.07.2017 11:45:01

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Validator с большой буквы))

Не в сети

#10 11.07.2017 11:52:41

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

)) Разумеется с большой буквы

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)

Не в сети

#11 11.07.2017 11:59:22

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

      if( $request->isMethod('post') ) {
            $rules = [
                'name' => 'required',
            ];

            $validator = \Validator::make($request->all(), $rules);
            if ($validator->fails()) {
                return back()->withErrors($validator)->withInput();
            }
        }

Запустил у себя, все ок.

Не в сети

#12 11.07.2017 12:17:09

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Вот я чувствую, что дело не только в этом, я когда прописываю

use Validator;

у себя в Контролллере, то редактор кода уже его подсвечивает как  undefined class Validatior. Но класс то есть, иначе валидация вообще бы не прходила.
Может быть при установке что-то не доставилось? Я через Composer ставил, все как нужно. Как теперь понять в чем дело? (((

Изменено littus (11.07.2017 12:17:55)

Не в сети

#13 12.07.2017 10:29:27

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Ещё получить валидатор можно так

$validator = $this->getValidationFactory()->make($request->all(), $rules, $messages);
if ($validator->fails()) {
    return back()->withErrors($validator)->withInput();
}

Не в сети

#14 12.07.2017 16:35:11

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Подсвечивает потому что это фасад, для него алиса прописан в 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);
        }

Не в сети

#15 12.07.2017 17:56:18

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Огромное спасибо всем отписавшимся за помощь, - разобрался, все работает как нужно теперь.
Не знаю, почему не отработала конструкция, хотя должна и так работать (напомню проект на 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)

Не в сети

#16 12.07.2017 18:13:49

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

... `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)

Не в сети

#17 13.07.2017 12:17:12

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Чтобы этого не было, нужно импортировать имя класса (use Validator;), иначе идет обращение к классу Validator в текущем пространстве имен.

я немного уточню – напрямую импортировать фасады из корневого неймспейса \ – нежелательно. причина в том, что сторонние библиотеки и расширения пхп добавляют в корень свои классы и там запросто можно импортировать чего-то не того. самый распространённый случай – пхп-расширение php-redis добавляет в корень класс Redis который перекрывает одноимённый фасад. работать гарантированно не будет и по какой причине – без бутылки не разберёшься smile

правильным является импорт фасадов из собственного неймспейса фасадов \Illuminate\Support\Facades, для валидатора это будет класс \Illuminate\Support\Facades\Validator. он полностью идентичен \Validator но гарантирует отсутствие конфликтов с окружением

а ещё интереснее – использовать биндинг параметров метода и контракты. в этом случае нам достаточно будет на экшен добавить параметр $validator с тайпхинтом на \Illuminate\Contracts\Validation\Factory. в этом случае мы избавляемся от статических зависимостей и можем покрывать этот код тестами – просто в тестах в качестве параметра будет передаваться не настоящий валидатор, а его mock

ну и пример кода конечно, куда без этого. на всякий случай скажу что пишу по памяти, не копипаста smile

<?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-ответы и так далее – автоматически. то есть код валидации из контроллера можно будет просто убрать. это хорошая идея, тонкий контроллер – хороший контроллер smile

Не в сети

#18 13.07.2017 18:01:39

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

llvllaestro, да, спасибо, он у меня был прописан как

use Validator;

, потом я экспериментировал с подключениями Классов и удалил его.
constb, супер, спасибо за возможные варианты и исчерпывающую инфу.

Изменено littus (13.07.2017 18:02:34)

Не в сети

#19 14.07.2017 13:23:33

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Немного  продолжу ))))
Что я не верно сделал с учетом передела валидации через собственный Класс `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`ов нет.

По идее, должно работать. Почему нет?

Не в сети

#20 14.07.2017 15:14:24

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Видимо проблемы с сессией. Советую вам пройти серию уроков на laracasts. Обратите внимание на настройки middleware в Kernel. Если есть время начните с 1 эпизода.

Не в сети

#21 14.07.2017 15:24:13

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Ну вот же я прописал в Kernel.php доступ на запись в сессиию и запись ошибок. - https://prnt.sc/fvmmvu
До того как  я переделал через отдельный пользовательский Класс Request работало же.

Не в сети

#22 14.07.2017 15:38:07

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

Может кто-то еще подскажет, но мне сходу трудно сказать где ошибка, по идее должно работать. Поэтому я предлагаю вам попробовать начинать с нуля, если у вас есть время. А с таким наставником (из уроков), точно не упустите ничего из виду. Также вот  урок по FormRequests. Удачи smile

Изменено llvllaestro (14.07.2017 15:38:38)

Не в сети

#23 15.07.2017 06:05:16

Re: Валидация данных (POST) . В сессию не сохраняются данные формы и текст

По идее, должно работать. Почему нет?

ну это конечно гадание на кофейной гуще, но вот мои варианты:

1) дополнительный редирект после того как произошёл редирект – инпуты и ошибки закидываются в сессию «одноразово», то есть доступны только на следующем запросе. если по какой-то причине следующий запрос закончился также редиректом – они не «доживут» до того чтобы попасть в форму. проверяется открытием вкладки Network в DevTools браузера, отключением очистки списка при переходе и внимательным изучением того, что происходит при отправке формы
2) инпуты и ошибки на самом деле есть в сессии, просто что-то идёт не так при их отображении. проверяется установкой laravel-debugbar если он ещё не установлен и вдумчивым изучением вкладки Session на тему что в ней там такое есть после редиректа

сам FormRequest отдаёт редирект как положено. см \Illuminate\Foundation\Http\FormRequest::response()

Не в сети

Подвал раздела