'Using a single form for insert and update function, Codeigniter

I'm trying to use a single form for inserting a new data and updating the value of an existing data.I have no trouble displaying the form, fetching the data and updating it, but when I'm trying to insert a new data, the form does not appear. Here's my view

     <div class="card-body">
           <small><?php echo validation_errors(); ?></small>
            <?php if (isset($packages)) { ?>
            <form action="<?= base_url('admin/update_package/' . $packages->id) ?>" method="POST" enctype="multipart/form-data">
            <div class="form-group">
           <label for="name" class="control-label">Package Name</label>
            <input type="text" class="form-control mb-3" name="title" placeholder="Enter Package Name" value="<?php echo !empty($packages->title) ? $packages->title : ''; ?>">
          </div>
         <div class="form-group">
           label for="short_name" class="control-label">Inclusions</label>
           <textarea id="compose-textarea" class="form-control" name="tour_location" style="height: 300px;"><?php echo !empty($packages->tour_location) ? $packages->tour_location : ''; ?></textarea>
        </div>
        <div class="form-group">
        <label for="short_name" class="control-label">Description</label>
         <textarea id="compose-textarea2" class="form-control" name="description" style="height: 300px;"><?php echo !empty($packages->description) ? $packages->description : ''; ?></textarea>
         </div>
         <div class="form-group">
         <label for="price" class="control-label">Price</label>
        <input type="number" step="any" class="form-control form" required name="cost" value="<?php echo !empty($packages->cost) ? $packages->cost : 0; ?>">
         </div>
         <div class="form-group">
         <label for="status" class="control-label">Status</label>
          <select name="status" id="status" class="custom-select select">
         <option value="1" <?php echo isset($status) && $status == 1 ? 'selected' : '- Select Status -' ?>>Active</option>
        <option value="0" <?php echo isset($status) && $status == 0 ? 'selected' : '- Select Status -' ?>>Inactive</option>
        </select>
        </div>
         <div class="form-group">
        <label for="short_name" class="control-label">Images</label>
         <div class="custom-file">
         <label class="btn custom-file-label text-light" for="customFile">Choose file
        <input type="hidden" name="current_image" value="<?php echo !empty($packages->upload_path) ? $packages->upload_path : ''; ?>">
        <input type="file" class="form-control custom-file-input" id="customFile" name="image" multiple accept="image/*"><small><?php if (isset($error)) {
        echo $error;} ?></small>
        </label>
        </div>
        </div>
        <?php 
         } ?>
         <!-- <div class="col-md-4">
        <img src="<?php echo base_url('images/' . $packages->upload_path) ?>" alt="Package Image" class="w-100 h-100">
        </div> -->
    
         <div class="card-footer">
          <input type="submit" name="packageData" class="btn btn-success " value="Save">
          <a class="btn btn-flat btn-default" href="<?php echo base_url('admin/packages'); ?>">Cancel</a>
            </div>
          </form>
          </div>
    
    
    
    
    My model
    
    
    
    <!-- language: lang-html -->
    
         public function insert($data = array())
            {
                if (!empty($data)) {
                    $this->db->insert('packages', $data);
    
                    return $this->db->insert_id();
                }
                return false;
            }
        public function edit($id)
            {
                $query = $this->db->get_where("packages", array('id' => $id));
    
                return $query->row();
            }
    
            public function update($data, $id)
            {
                return $this->db->update("packages", $data, array('id' => $id));
            }

And then Controller

public function insert_package()
    {
        $packageData = array();

        // If add request is submitted
        if ($this->input->post('packageData')) {
            // Form field validation rules
            $this->form_validation->set_rules('title', 'Package Name', 'required');
            $this->form_validation->set_rules('tour_location', 'Inclusions', 'trim');
            $this->form_validation->set_rules('description', 'Description', 'trim|required');
            $this->form_validation->set_rules('cost', 'Price', 'required');
            $this->form_validation->set_rules('status', 'Status', 'required');
            // $this->form_validation->set_rules('image', 'Images', 'required');

            // Validate submitted form data
            if ($this->form_validation->run() == true) {
                $ori_filename = $_FILES['image']['name'];
                $update_image = time() . "" . str_replace(' ', '-', $ori_filename);
                $config = [
                    'upload_path' => './images',
                    'allowed_types' => 'gif|jpg|png',
                    'file_name' => $update_image,
                ];

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

                if (!$this->upload->do_upload('image')) {
                    $error = array('error' => $this->upload->display_errors());
                    $this->load->view(base_url('admin/packages'), $error);
                } else {

                    $image = $this->upload->data('file_name');
                    $packageData = array(
                        'title' => $this->input->post('title'),
                        'tour_location' => $this->input->post(htmlentities('tour_location')),
                        'description' => $this->input->post(htmlentities('description')),
                        'cost' => $this->input->post('cost'),
                        'status' => $this->input->post('status'),
                        'upload_path' => $image
                    );
                    $img = new Admin_model;
                    // Insert member data
                    $img->insert($packageData);
                    $this->session->set_flashdata('status', 'Package InsertedSuccesfully');
                    redirect(base_url('admin/packages'));
                }
            }
        }

        $data['title'] = 'Add Package';

        $this->load->view('../admin/template/admin_header');
        $this->load->view('../admin/template/admin_topnav');
        $this->load->view('../admin/template/admin_sidebar');
        $this->load->view('../admin/packages/manage_package', $data);
        $this->load->view('../admin/template/admin_footer');
    }

    public function edit_package($id)
    {
        $data['title'] = 'Update Package';

        $this->load->view('../admin/template/admin_header');
        $package = new Admin_model;
        $data['packages'] = $package->edit($id);
        $this->load->view('../admin/template/admin_topnav');
        $this->load->view('../admin/template/admin_sidebar');
        $this->load->view('../admin/packages/manage_package', $data);
        $this->load->view('../admin/template/admin_footer');
    }

    public function update_package($id)
    {
        $this->form_validation->set_rules('title', 'Package Name', 'required');
        $this->form_validation->set_rules('tour_location', 'Inclusions', 'trim');
        $this->form_validation->set_rules('description', 'Description', 'trim|required');
        $this->form_validation->set_rules('cost', 'Price', 'required');
        $this->form_validation->set_rules('status', 'Status', 'required');

        if ($this->form_validation->run() == true) {
            $current_image = $this->input->post('current_image');
            $new_image = $_FILES['image']['name'];

            if ($new_image == TRUE) {

                $update_image = time() . "-" . str_replace(' ', '-', $_FILES['image']['name']);
                $config = [
                    'upload_path' => './images',
                    'allowed_types' => 'gif|jpg|png',
                    'file_name' => $update_image,
                ];

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

                if (!$this->upload->do_upload('image')) {
                    if (file_exists('./images' . $current_image)) {
                        unlink('./images' . $current_image);
                    }
                }
            } else {
                $update_image = $current_image;
            }

            $packageData = array(
                'title' => $this->input->post('title'),
                'tour_location' => $this->input->post(htmlentities('tour_location')),
                'description' => $this->input->post(htmlentities('description')),
                'cost' => $this->input->post('cost'),
                'status' => $this->input->post('status'),
                'upload_path' => $update_image
            );
            
            $this->Admin_model->update($packageData, $id);
            $this->session->set_flashdata('status', 'Package InsertedSuccesfully');
            redirect(base_url('admin/packages/'));
        } else {
            return $this->edit_package($id);
        }
    }

I found a question here and an answer and suggestion but I can't still solve my problem.



Solution 1:[1]

The easiest way to reuse a form for both insert and update, is to leave the form action blank. If the form action is left blank, the form is posted back to the same URL that was used to display it. This works if you're using the same method (one for insert, one for update) for both processing and rendering the from.

Since your update form processing is at admin/update_package/$id, but your update form rendering is at admin/edit_package/$id, the form action you need to specify depends on what URL you're using to display the update form.

If you're using a link to admin/update_package/$id to display the update form, you can leave the form action blank (or remove it completely): <form method="POST" enctype="multipart/form-data">

update_package then runs the form validation and then uses edit_package to display the form, but the URL remains admin/update_package/$id which is where you want to post back to, so no form action is needed.

In this case, I suggest that you also make the edit_package method in your controller private, so you can't accidentally display the form via the edit_package URL: private function edit_package($id)


However, if you're using a link to/the URL admin/edit_package/$id to display the update form, posting back to that URL does not trigger the form processing, so you do need to specify a form action in this case.

You can use the $packages variable to tell whether the form is being used for insert or update, and set the action to the update_package URL if $packages exists: action="<?= isset($packages) ? base_url('admin/update_package/'.$packages->id) : ''; ?>"

Insert then gets an empty action which posts back to the same URL that was used to render the insert form.


Edit: Also remove the <?php if (isset($packages)) that surrounds the form, or it won't show on insert either.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1