Ошибка приложения блога Codeigniter: форма загружена без ошибок проверки - PullRequest
0 голосов
/ 05 января 2019

Я работаю над приложением блога в Codeigniter 3.1.8 и Bootstrap 4. У меня есть форма "Редактировать сообщение" с проверкой .

Если проверка не удалась (например, из-за того, что поле Title было очищено), форма должна перезагрузиться с ошибками проверки .

Мой update() (живет в контроллере сообщений) неправильный метод: он использует перенаправление, поэтому форма перезагружается без ошибок проверки в исходное состояние.

public function edit($id) {
    // Only logged in users can edit posts
    if (!$this->session->userdata('is_logged_in')) {
        redirect('login');
    }

    $data = $this->Static_model->get_static_data();
    $data['pages'] = $this->Pages_model->get_pages();
    $data['categories'] = $this->Categories_model->get_categories();
    $data['posts'] = $this->Posts_model->sidebar_posts($limit=5, $offset=0);
    $data['post'] = $this->Posts_model->get_post($id);
    if ($this->session->userdata('user_id') == $data['post']->author_id) {
        $data['tagline'] = 'Edit the post "' . $data['post']->title . '"';
        $this->load->view('partials/header', $data);
        $this->load->view('edit-post');
        $this->load->view('partials/footer');
    } else {
        /* If the current user is not the author
        of the post do not alow edit */
        redirect('/' . $id);
    }
}

public function update() {
    // Form data validation rules
    $this->form_validation->set_rules('title', 'Title', 'required',  array('required' => 'The %s field can not be empty'));
    $this->form_validation->set_rules('desc', 'Short description', 'required',  array('required' => 'The %s field can not be empty'));
    $this->form_validation->set_rules('body', 'Body', 'required',  array('required' => 'The %s field can not be empty'));
    $this->form_validation->set_error_delimiters('<p class="error-message">', '</p>');

    $id = $this->input->post('id');

    // Update slug (from title)
    if (!empty($this->input->post('title'))) {
        $slug = url_title($this->input->post('title'), 'dash', TRUE);
        $slugcount = $this->Posts_model->slug_count($slug);
        if ($slugcount > 0) {
            $slug = $slug."-".$slugcount;
        }
    } else {
        $slug = $this->input->post('slug');
    }

// Upload image
    $config['upload_path'] = './assets/img/posts';
    $config['allowed_types'] = 'jpg|png';
    $config['max_size'] = '2048';

    $this->load->library('upload', $config);

    if(!$this->upload->do_upload()){
        $errors = array('error' => $this->upload->display_errors());
        $post_image = $this->input->post('postimage');
    } else {
        $data = array('upload_data' => $this->upload->data());
        $post_image = $_FILES['userfile']['name'];
    }

    if ($this->form_validation->run()) {
        $this->Posts_model->update_post($id, $post_image, $slug);
        $this->session->set_flashdata('post_updated', 'Your post has been updated');
        redirect('/' . $slug);
    } else {
        redirect('/posts/edit/' . $slug);
    }
}

Я почти уверен, что проблема в этой строке: redirect('/posts/edit/' . $slug);, но я не смог найти жизнеспособную альтернативу.

Использование $this->edit($id) вместо redirect('/posts/edit/' . $slug); также не работает. Я хотел бы, потому что я хочу сохранить код СУХОЙ.

Что мне поменять?


Редактировать. Я сделал это:

if ($this->form_validation->run()) {
        $this->Posts_model->update_post($id, $post_image, $slug);
        $this->session->set_flashdata('post_updated', 'Your post has been updated');
        redirect('/' . $slug);
} else {
        $this->form_validation->run();
        $this->session->set_flashdata('errors', validation_errors());
        var_dump($this->session->flashdata('errors'));
        //redirect('/posts/edit/' . $slug);
}

var_dump($this->session->flashdata('errors')); возвращает все ошибки проверки.

Я хочу добавить класс has-error в группу форм и добавить <<code>p class="error-message">The Title field is required.</p>.

<div class="form-group has-error">
  <input type="text" name="title" id="title" class="form-control error" placeholder="Title" data-rule-required="true" value="Learn to code with us" aria-invalid="true">
  <p class="error-message">The Title field is required.</p>
</div>

Ответы [ 3 ]

0 голосов
/ 06 января 2019

У вас есть 3 варианта:

  1. Использовать флэш-данные в методе обновления при сбое (вы уже используете его в случае успеха). Просто назначьте ошибки переменной флэш-данных и получите ее после того, как вы вернетесь к редактированию.
  2. Объединение методов редактирования и обновления (наиболее распространенных для использования без ajax).
  3. Используйте ajax и возвращайте строки, закодированные в json, для сообщений об ошибках или успехах.

Вариант 2:

Эта опция также решает потенциальную проблему аутентификации, указанную в комментариях.

Пожалуйста, прочтите комментарии, встроенные в код.

public function edit($id) {
        // Only logged in users can edit posts
        if (!$this->session->userdata('is_logged_in')) {
            redirect('login');
        }

        $data['post'] = $this->Posts_model->get_post($id);

        if ($this->session->userdata('user_id') == $data['post']->author_id) {
            show_error('Access denied'); // function exits
        }

        if ($_POST) {

            $this->form_validation->set_rules('title', 'Title', 'required', array('required' => 'The %s field can not be empty'));
            $this->form_validation->set_rules('desc', 'Short description', 'required', array('required' => 'The %s field can not be empty'));
            $this->form_validation->set_rules('body', 'Body', 'required', array('required' => 'The %s field can not be empty'));
            $this->form_validation->set_error_delimiters('<p class="error-message">', '</p>');

            //$id = $this->input->post('id'); not required anymore

            $config['upload_path'] = './assets/img/posts';
            $config['allowed_types'] = 'jpg|png';
            $config['max_size'] = '2048';

            $this->load->library('upload', $config);

            if ($this->form_validation->run() && $this->upload->do_upload()) {
                // always use the name from the upload lib
                // sometimes it changes it in case of duplicates (read docs for more)
                $post_image = $this->upload->data('file_name');

                // doesn't make sense with title validation rule, this will always be true to get
                // passed validation
                if (!empty($this->input->post('title'))) {
                    $slug = url_title($this->input->post('title'), 'dash', TRUE);
                    $slugcount = $this->Posts_model->slug_count($slug);
                    if ($slugcount > 0) {
                        $slug = $slug . "-" . $slugcount;
                    }
                } else {
                    $slug = $this->input->post('slug');
                }

                $this->Posts_model->update_post($id, $post_image, $slug);
                $this->session->set_flashdata('post_updated', 'Your post has been updated');
                redirect('/' . $slug);
            } else {
                $data['errors'] = validation_errors() . $this->upload->display_errors();
            }
        }

        $data = $this->Static_model->get_static_data();
        $data['pages'] = $this->Pages_model->get_pages();
        $data['categories'] = $this->Categories_model->get_categories();
        $data['posts'] = $this->Posts_model->sidebar_posts($limit = 5, $offset = 0);
        $data['tagline'] = 'Edit the post "' . $data['post']->title . '"';
        $this->load->view('partials/header', $data);
        $this->load->view('edit-post');
        $this->load->view('partials/footer');
    }
0 голосов
/ 08 января 2019

Мне удалось получить желаемый результат, используя set_flashdata(), как предложено @ Alex

В контроллере у меня есть:

public function update() {
    // Form data validation rules
    $this->form_validation->set_rules('title', 'Title', 'required',  array('required' => 'The %s field can not be empty'));
    $this->form_validation->set_rules('desc', 'Short description', 'required',  array('required' => 'The %s field can not be empty'));
    $this->form_validation->set_rules('body', 'Body', 'required',  array('required' => 'The %s field can not be empty'));
    $this->form_validation->set_error_delimiters('<p class="error-message">', '</p>');

    $id = $this->input->post('id');

    // Update slug (from title)
    if (!empty($this->input->post('title'))) {
        $slug = url_title($this->input->post('title'), 'dash', TRUE);
        $slugcount = $this->Posts_model->slug_count($slug);
        if ($slugcount > 0) {
            $slug = $slug."-".$slugcount;
        }
    } else {
        $slug = $this->input->post('slug');
    }

// Upload image
    $config['upload_path'] = './assets/img/posts';
    $config['allowed_types'] = 'jpg|png';
    $config['max_size'] = '2048';

    $this->load->library('upload', $config);

    if(!$this->upload->do_upload()){
        $errors = array('error' => $this->upload->display_errors());
        $post_image = $this->input->post('postimage');
    } else {
        $data = array('upload_data' => $this->upload->data());
        $post_image = $_FILES['userfile']['name'];
    }

    if ($this->form_validation->run()) {
        $this->Posts_model->update_post($id, $post_image, $slug);
        $this->session->set_flashdata('post_updated', 'Your post has been updated');
        redirect('/' . $slug);
    } else {
        $this->form_validation->run();
        $this->session->set_flashdata('errors', validation_errors());
        redirect('/posts/edit/' . $slug);
    }
}

По виду:

<?php if ($this->session->flashdata('errors')) {
         $errors = $this->session->flashdata('errors');
         echo '<div class="error-group alert alert-warning alert-dismissible">' . "\n";
         echo '<button type="button" class="close" data-dismiss="alert">&times;</button>' . "\n";
         echo $errors;
         echo '<p class="error-message">We have restored the post.</p>';
         echo '</div>';
} ?>
0 голосов
/ 06 января 2019

В этом сценарии я хотел бы объединить оба метода в один метод, основанный на проверке, чтобы узнать, сохраняю ли я запись или нет.

ваш код будет выглядеть примерно так:

public function edit($id) {
    // Only logged in users can edit posts
    if (!$this->session->userdata('is_logged_in')) {
        redirect('login');
    }
    $Post = $this->Posts_model->get_post($id);
    // user does not own the post, redirect
    if ($this->session->userdata('user_id') !== $Post->author_id) {
        redirect('/' . $id);
    }

    // Form data validation rules
    $this->form_validation->set_rules('title', 'Title', 'required',  array('required' => 'The %s field can not be empty'));
    $this->form_validation->set_rules('desc', 'Short description', 'required',  array('required' => 'The %s field can not be empty'));
    $this->form_validation->set_rules('body', 'Body', 'required',  array('required' => 'The %s field can not be empty'));
    $this->form_validation->set_error_delimiters('<p class="error-message">', '</p>');

    // if validation fails, or the form isn't submitted
    if ($this->form_validation->run() === false ) {
        $data = $this->Static_model->get_static_data();
        $data['pages'] = $this->Pages_model->get_pages();
        $data['categories'] = $this->Categories_model->get_categories();
        $data['posts'] = $this->Posts_model->sidebar_posts($limit=5, $offset=0);
        $data['post'] = $Post;

        $data['tagline'] = 'Edit the post "' . $data['post']->title . '"';
        $this->load->view('partials/header', $data);
        $this->load->view('edit-post');
        $this->load->view('partials/footer');
    }else{
        // Update slug (from title)
        if (! empty($this->input->post('title'))) {
            $slug = url_title($this->input->post('title'), 'dash', TRUE);
            $slugcount = $this->Posts_model->slug_count($slug);
            if ($slugcount > 0) {
                $slug = $slug."-".$slugcount;
            }
        } else {
            $slug = $this->input->post('slug');
        }
        // Upload image
        $config['upload_path'] = './assets/img/posts';
        $config['allowed_types'] = 'jpg|png';
        $config['max_size'] = '2048';

        $this->load->library('upload', $config);

        if(!$this->upload->do_upload()){
            $errors = array('error' => $this->upload->display_errors());
            $post_image = $this->input->post('postimage');
        } else {
            $data = array('upload_data' => $this->upload->data());
            $post_image = $_FILES['userfile']['name'];
        }       
        $this->Posts_model->update_post($id, $post_image, $slug);
        $this->session->set_flashdata('post_updated', 'Your post has been updated');
        redirect('/' . $slug);
    }
}

и вам не нужно реализовывать обновление отдельно, вы просто публикуете в / edit / $ id вместо / update / $ id ... это грубый пример, ваша проверка на слаг (который я не затрагивал) на) это не правильный способ сделать это, если он проходит проверку, заголовок уже заполнен, так как он установлен на обязательный, так что я предполагаю, что вы имели в виду if (! empty(slug) ), но опять же в другом вы устанавливаете слаг непосредственно из пользовательского ввода, поэтому я бы добавил его к проверке и удостоверился, что он уникален в базе данных, за исключением $ id, который редактируется в настоящее время.

Опять же, это результат копирования и вставки из вашего исходного кода. Возможно, я что-то пропустил, поэтому внимательно прочитайте, чтобы убедиться, что ничего не пропало, и включите ошибки проверки в данные, передаваемые представлению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...