Welcome Guest, Not a member yet? Register   Sign In
Validation always return error
#1

I have this form:

Code:
   <form action="<?= base_url('admin/blog/post/' . $post['id']) ?>/update" method="post" class="form-horizontal" enctype="multipart/form-data">
        <?= csrf_field() ?>
        <input type="hidden" name="_method" value="put" />
        <div class="row">
            <div class="col-md-12 col-xl-10">
                <div class="form-group">
                    <input type="text" class="form-control" name="title" minlength="1" maxlength="60" placeholder="<?= lang('dashboard.blog.post.title_field_plc') ?>" value="<?= $post['title'] ?>">
                </div>
                <div class="form-group">
                    <textarea name="content" class="summernote"><?= $post['content'] ?></textarea>
                </div>
            </div>
        </div>
    </form>

as you can see I have two field "title" and "content", when I submit the form, this method is called:

PHP Code:
    public function update($id)
    {
        $validationRules = [
            'title'             => 'required|min_length[1]|max_length[60]',
            'author_id'         => 'required|integer',
            'status'            => 'required|in_list[draft,published]'
        ];

        if (!$this->validate($validationRules)) {
            var_dump($this->validator->getErrors());
            print_r($_POST);
            die();
            //return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }
... 

for some reason validationRules always fail, infact I get this error:

string(1) "1" array(3) { ["title"]=> string(31) "Field title is required." }

but I have passed the title field, infact when I do $_POST I can see the `title` field with the content provided.

What I did wrong?
Reply
#2

(This post was last modified: 04-10-2021, 11:13 PM by iRedds.)

I will try to explain the reason.

You are using spoofing:
Code:
<input type="hidden" name="_method" value="put" />
This makes the framework assume that the request method is not POST, but PUT.

In the controller, when the validate() method is called, an instance of the Validation class is created and passed the request to it. And the class automatically determines the data for validation by the type of request.

Since the framework has defined the method as PUT, the Validation class tries to get data from the request body via php://input.

And this is where the fun begins.
When you specify the encryption method 'multipart/form-data' in the enctype attribute in the form tag, the request is encoded in a special way, and get it through the php://input impossible.

I have counted 3 ways to solve the problem so far.
1. Don't use encoding 'multipart/form-data'
2. Do not use spoofing.
3. Do not use controller validation method. In this case, you can write the implementation of this method yourself, and pass the data to the Validation::run() method.

https://github.com/codeigniter4/CodeIgni...ssues/4552
Reply
#3

(04-10-2021, 10:35 PM)iRedds Wrote: I will try to explain the reason.

You are using spoofing:
Code:
<input type="hidden" name="_method" value="put" />
This makes the framework assume that the request method is not POST, but PUT.

In the controller, when the validate() method is called, an instance of the Validation class is created and passed the request to it. And the class automatically determines the data for validation by the type of request.

Since the framework has defined the method as PUT, the Validation class tries to get data from the request body via php://input.

And this is where the fun begins.
When you specify the encryption method 'multipart/form-data' in the enctype attribute in the form tag, the request is encoded in a special way, and get it through the php://input impossible.

I have counted 3 ways to solve the problem so far.
1. Don't use encoding 'multipart/form-data'
2. Do not use spoofing.
3. Do not use controller validation method. In this case, you can write the implementation of this method yourself, and pass the data to the Validation::run() method.

https://github.com/codeigniter4/CodeIgni...ssues/4552

I'm interested in the first solution, 'cause for the other two I have no clue how to setup them. Could you please show me an example of file uploading without using `multipart/form-data`?

Thanks again
Reply
#4

Without using multipart/form-data, you won't upload the file.

If you remove the <input type="hidden" name="_method" value="put" /> then the framework defines the request method as POST, not PUT. And everything will work for you.

Instead of the controller's validation method, you can work with the validator directly.
PHP Code:
$validator = \Config\Services::validation();
$validator->setRules($arrayWithValidationRules)
if (
$validator->run($this->request->gerVar())) 
{
   
// valid
} else {
  
// error

Reply
#5

(04-11-2021, 05:57 AM)iRedds Wrote: Without using multipart/form-data, you won't upload the file.

If you remove the <input type="hidden" name="_method" value="put" /> then the framework defines the request method as POST, not PUT. And everything will work for you.

Instead of the controller's validation method, you can work with the validator directly.
PHP Code:
$validator = \Config\Services::validation();
$validator->setRules($arrayWithValidationRules)
if (
$validator->run($this->request->gerVar())) 
{
   // valid
} else {
  // error


I have removed 
PHP Code:
<input type="hidden" name="_method" value="put" /> 

but when I submit the form I get:

404 - File Not Found

The controller or the method was not found: \App\Controllers\Admin::blog

the form:


PHP Code:
<form action="<?= base_url('admin/blog/post/' . $post['id']) ?>/update" method="post" class="form-horizontal" enctype="multipart/form-data"


these are my routes:


PHP Code:
$routes->group('admin', function ($routes) {

    
/**
     * Admin routes.
     **/
    
$routes->group('/', [
        
'filter'    => config('Boilerplate')->dashboard['filter'],
        
'namespace' => config('Boilerplate')->dashboard['namespace'],
    ], function (
$routes) {
        
$routes->get('/'config('Boilerplate')->dashboard['controller']);
    });

    
/**
     * Blog routes.
     */
    
$routes->group('blog', [
        
'filter'    => 'permission:manage-blog',
        
'namespace' => 'App\Controllers\Blogs',
    ], function (
$routes) {


        
$routes->resource('post', [
            
'filter'     => 'permission:manage-blog',
            
'namespace'  => 'App\Controllers\Blogs',
            
'controller' => 'PostController',
            
'except'     => 'show',
        ]);
    });
}); 

the update() method in the controller seems to be working only if I use "put", but maybe am I missing something here?
Reply
#6

He's also using the jQuery Summernote editor in his form which may affect the form data.
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply
#7

(This post was last modified: 04-11-2021, 06:26 PM by iRedds.)

If you are using the "resource" route generator, the update method handles put and patch requests.
Since you are using the "resource" generator, removing the spoofing method will result in an error.
You can solve it like this:
PHP Code:
//Add a line to the closure where you call the resource method 
$routes->post('post/(:segment)''PostController::update/$1'); 

But I'm worried about that address in the form: <?= base_url('admin/blog/post/' . $post['id']) ?>/update
The format of the address conflicts with the expected format when using the "resource" generator.
For a PUT request, the address should be like this: admin/blog/post/ID.
This means that the "admin/blog/post/ID/update" address should cause an error.

@InsiteFX I do not know this tool, but it seems to me that it does not affect the sending of data. Maybe I'm wrong.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB