ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

Fed Up with CodeIgniter CRUD

July 29, 2007 7:19pm

Subscribe [10]
  • #1 / Jul 29, 2007 7:19pm

    kirkaracha

    273 posts

    I’ve been working with CodeIgniter off and on for about a year, and I’m about ready to move to something else because things that should be easy are very frustrating. I want to do very simple CRUD forms, use the same form view for adding and editing, display the errors in a list at the top of the form page, mark the labels of the fields with errors, have the form remember the submitted values, and validate my inputs, and trying to do this in CodeIgniter is more complicated than it should be.

    I’ve read the manual, searched the forums, and watched all of the videos many times. I can’t find a complete example of a working form with validation and error display. All of the tutorials and videos say they leave off validation to keep things simple, but I need a complete example of a working CRUD form with validation. There’s too much emphasis on how quick and easy the basics are, and not enough information about how to write production-ready code.

    I don’t want to use a third-party solution like Rapyd or CodeCrafter, because I want a framework that can handle basic CRUD functionality on its own and I don’t want to maintain two separate things. What am I missing?

  • #2 / Jul 29, 2007 7:40pm

    coolfactor

    354 posts

    Show us some of your code. Give specifics. Hard to extrapolate where you’re having troubles from that post.

  • #3 / Jul 29, 2007 11:37pm

    JayTee

    108 posts

    The hardest part of doing what you’re talking about is how big your code gets when you’re trying to use CRUD.  Here’s an example:

    Let’s say I have an object called “invoice”.  I have a form that I want to use for both editing and adding an existing entry.  Here’s what you could do for an input in your view:

    <?= form_input('dt_create',($this->validation->dt_create ? $this->validation->dt_create : $invoice->dt_create)) ?>

    You could do something similar in the controller to limit the code in the view:
    Controller:

    ...
    $data = array(
      "dt_create"=>$this->validation->dt_create ? $this->validation->dt_create : $invoice->dt_create;
    );

    View:

    <?= form_input('dt_create',$dt_create) ?>

    Either way, you have to go back and forth between the validation class and your database information to ensure that you’re using one of the values in your creation page.

    Hope this helps,

    Jon

  • #4 / Jul 30, 2007 4:54am

    BravoAlpha

    51 posts

    Here’s a rough example (using JayTee’s invoice example) of what I’m currently using:

    invoices table (MySQL)

    CREATE TABLE IF NOT EXISTS `invoices` (
      `invoice_id` int(10) unsigned NOT NULL auto_increment,
      `client` varchar(255) NOT NULL,
      `description` varchar(255) NOT NULL,
      `amount` float(8,2) NOT NULL,
      PRIMARY KEY  (`invoice_id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
    
    INSERT INTO `invoices` (`invoice_id`, `client`, `description`, `amount`) VALUES 
    (1, 'kirkaracha', 'CRUD', 1.00);

    invoice.php

    <?php
    
    class Invoice extends Controller {
    
        function index()
        {
            $this->db->orderby('invoice_id desc');
            $data['invoices'] = $this->db->get('invoices');
            
            $this->load->helper('url'); // Assuming this helper isn't auto-loaded
            $this->load->view('invoice_index', $data);
        }
    
        function form($invoice_id = FALSE)
        {
            if ($invoice_id)
            {
                $this->db->where('invoice_id', $invoice_id);
                $query = $this->db->get('invoices', 1);
                
                if ($query->num_rows() != 0)
                    $invoice = $query->row();
                else
                    show_404();
            }
            
            $this->load->library('validation');
            
            $rules['client']      = 'trim|required|max_length[255]|xss_clean|htmlspecialchars';
            $rules['description'] = 'trim|required|max_length[255]|xss_clean|htmlspecialchars';
            $rules['amount']      = 'trim|required|numeric';
            $this->validation->set_rules($rules);
            
            $fields['client']      = 'client';
            $fields['description'] = 'description';
            $fields['amount']      = 'amount';
            $this->validation->set_fields($fields);
            
            if ($this->validation->run())
            {
                $input = array(
                    'client'      => $this->input->post('client'),
                    'description' => $this->input->post('description'),
                    'amount'      => $this->input->post('amount')
                    );
                
                if ($invoice_id)
                {
                    $this->db->where('invoice_id', $invoice_id);
                    $this->db->update('invoices', $input);
                }
                else
                    $this->db->insert('invoices', $input);
                
                redirect('invoice');
            }
            else
            {
                if ($invoice_id && $this->input->post('submit') === FALSE)
                {
                    $this->validation->client      = $invoice->client;
                    $this->validation->description = $invoice->description;
                    $this->validation->amount      = $invoice->amount;
                }
                
                $this->load->view('invoice_form');
            }
        }
    
    }
    
    ?>

    invoice_index.php

    <?php echo anchor('invoice/form', 'Create a new invoice'); ?>
    
    Invoices:
    <ul>
    <?php foreach($invoices->result() as $invoice): ?>
        <li>
            <?= anchor('invoice/form/'.$invoice->invoice_id, 'Invoice #'.$invoice->invoice_id); ?>
    
            <?php echo $invoice->client; ?>
    
            <?php echo $invoice->description; ?>
    
            <?php echo $invoice->amount; ?>
        </li>
    <?php endforeach; ?>
    </ul>

    invoice_form.php

    <form method="post">
        <fieldset>
            <legend>Create/Edit Invoice</legend>
    
            <?php echo $this->validation->error_string; ?>
    
            <label>Client <input type="text" name="client" value="<?php echo $this->validation->client; ?>" ></label>
            <label>Description <input type="text" name="description" value="<?php echo $this->validation->description; ?>" ></label>
            <label>Amount <input type="text" name="amount" value="<?php echo $this->validation->amount; ?>" ></label>
            <input type="submit" name="submit" value="Submit" />
        </fieldset>
    </form>
  • #5 / Jul 30, 2007 10:33am

    kirkaracha

    273 posts

    Thanks, everyone. I think I’ll try BravoAlpha’s method.

  • #6 / Jul 30, 2007 12:21pm

    kbauman

    19 posts

    I generally put empty values into my forms so that the forms can be used for inserts, and updates. I also pass an error value that is empty if it’s an insert.

    I use something like the following:

    function images(){
              $data['authorized'] = $this->data['authorized'];
          $cat = $this->uri->segment(3, 0);
          $error = $this->uri->segment(4);        
                $p_data['title'] = "Suzanne Bauman - Image Management";
            $p_data['sub_heading'] = "Image Management";
            $p_data['message'] = $this->uri->segment(4);
            $p_data['copyright_name'] = "Suzanne Bauman";
            $p_data['category'] = $cat;
            $p_data['categories'] = $this->data['categories'];
            $p_data['id'] = '';
            $p_data['medium_val'] = '';    
            $p_data['size_val'] = '';
            $p_data['price_val'] = '';
            $p_data['sold_sel'] = "select";
            $p_data['title_val'] = '';    
            $p_data['photo_val'] = '';
            $p_data['matted_sel'] = "select";
            $p_data['framed_sel'] = "select";
            $p_data['form_message'] = "Add A New Image";
            $p_data['form_open'] = "admin/upload_image";
            $p_data['form_close'] = "Upload Image";
            if ($cat != '0')
            {
              if ($cat == 'modify')
                {
                $p_data['id'] = $this->input->post('id');
                $p_data['image'] = $this->input->post('image');
                $p_data['medium_val'] = $this->input->post('medium');    
                    $p_data['size_val'] = $this->input->post('size');
                    $p_data['price_val'] = $this->input->post('price');    
                    $p_data['sold_sel'] = $this->input->post('sold');    
                    $p_data['title_val'] = $this->input->post('title');    
                    $p_data['matted_sel'] = $this->input->post('matted');    
                    $p_data['framed_sel'] = $this->input->post('framed');
                $p_data['category'] = $this->input->post('category');
                $p_data['form_message'] = "Modify An Image";
                $p_data['form_open'] = "admin/modify_image";
                $p_data['form_close'] = "Modify Image";
                }
                else
              {
              $tbl = 'art_'.$cat;
              $this->db->select('*');
              $this->db->from($tbl);
              $this->db->orderby('art_order', 'asc');
              $p_data['query'] = $this->db->get();
              }
            }
            $data['main_nav'] = $this->data['main_nav'];
            $data['admin_nav'] = $this->data['admin_nav'];
            $data['main_content'] = $this->load->view('admin/images_view', $p_data, true);
          $this->load->view('admin/admin_template', $data);    
        }
  • #7 / Aug 06, 2007 7:49pm

    Crafter

    148 posts

    Don’t think that using ANY framework will make your complex application smaller or less complex. One of the biggest gains in using a framework is how well things fit together. The components of your applications are joined automagically so that you can concentrate on your business logic.

    Nobody is going to write a complete application for you, but there are a number of resources you could consult, like
    http://codeigniter.com/wiki/Tutorials/
    http://www.derekallard.com
    http://codeigniter.com/wiki/Applications_Using_Code_Igniter/

  • #8 / Aug 07, 2007 1:22am

    usmc

    74 posts

    Don’t think that using ANY framework will make your complex application smaller or less complex. One of the biggest gains in using a framework is how well things fit together. The components of your applications are joined automagically so that you can concentrate on your business logic.

    Nobody is going to write a complete application for you, but there are a number of resources you could consult, like
    http://codeigniter.com/wiki/Tutorials/
    http://www.derekallard.com
    http://codeigniter.com/wiki/Applications_Using_Code_Igniter/

    I couldn’t agree more.  Well said.

  • #9 / Jun 09, 2009 2:58pm

    searain

    101 posts

    BravoAlpha, kirkaracha, or any other developers?

    Did you have more or updated version for the scripts you posted here?  This script has handled “CRU”.  How about “delete”, I like this approach to handle the CRUD, it is more close to my own code base (not on CI), so it is easier for me to use this approach.

    I already did my own “delete” based on the script here.  But I would like to use CI experts’ “delete” scripts to see if I miss anything.

  • #10 / Jun 09, 2009 4:02pm

    Nicholai

    24 posts

    Check out this post to see how I handle add/update with validation, without using a ton of code (many thanks to Colin Williams for the help). Here’s an expanded version that has deletes as well:

    function _tasktypes_form_rules()
        {
        //this function contains all of the field validation rules so bad data can't enter the system
            $form = array(
                       array(
                             'field'   => 'ttName',
                             'label'   => 'Name',
                             'rules'   => 'required'
                          ),
                       array(
                             'field'   => 'ttDescription',
                             'label'   => 'Description',
                             'rules'   => 'required'
                          ),
                       array(
                             'field'   => 'ttPriority',
                             'label'   => 'Priority',
                             'rules'   => 'numeric'
                          ),   
                       array(
                             'field'   => 'ttDisplayOrder',
                             'label'   => 'Display Order',
                             'rules'   => 'numeric'
                          ),
            );
                    
            return $form;
        }    
    
        function _tasktypes_form_defaults()
        {
        //set default values when calling the Add function the first time, to prevent invalid index errors
                $values = array(
                             'ID'   => '',
                             'ttName'   => '',
                             'ttDescription'   => '',
                             'ttPriority'   => '',
                             'ttDisplayOrder'   => '',
                          );
            return $values;
        }
            
        function add()
        {
    
            //set rules for the form
            $form = $this->_tasktypes_form_rules();
            $this->form_validation->set_rules($form);     
    
            $form['title'] = 'Add a Task Type';
            $form['action'] = site_url('tasktypes/add');
            $form['button_text'] = 'Add Task Type';
    
            if ($this->form_validation->run() == FALSE)
            {
                //if the post array doesn't exist yet, fill in the default values
                if (! $_POST)
                {
                    $form['values'] = $this->_tasktypes_form_defaults();
                }
                else
                {
                    $form['values'] = $_POST;
            }
            $this->load->view('admin_task_types_form', $form);
            }
            else
            {
                if ($this->task_types_model->save($_POST))
                {
                    redirect('tasktypes/display');
                }
                else
                {
                    $form['error'] = "Don't know why, but it failed";
                    $form['values'] = $_POST;
                    $this->load->view('admin_task_types_form', $form);
                }
            }
        }    
        
        function edit($ID = NULL)
        {
    
            //only edit if the record exists
            if ( ! $item = $this->task_types_model->get($ID))
            {
                show_404();
                return;
            }
    
            //set rules for the form
            $form = $this->_tasktypes_form_rules();
            $this->form_validation->set_rules($form);
                    
            $form['title'] = 'Edit Task Type';
            $form['action'] = site_url('tasktypes/edit/'. $ID);
            $form['button_text'] = 'Save';
            
            if ($this->form_validation->run() == FALSE)
            {
                //if the post array doesn't exist yet, fill in the values from the database (pulled when checking existence of the record)
                if (! $_POST)
                {
                    $form['values'] = (array) $item;
                }
                else 
                {
                    $form['values'] = $_POST;
                }
                $this->load->view('admin_task_types_form', $form);
            }
            else
            {
                if ($this->task_types_model->save($_POST))
                {
                    redirect('tasktypes/display');
                }
                else
                {
                    $form['error'] = "Don't know why, but it failed";
                    $form['values'] = $_POST;
                    $this->load->view('admin_task_types_form', $form);
                }
            }
        }
    
        function delete($ID = NULL)
        {
            //only delete if the record exists
            if ( ! $item = $this->task_types_model->get($ID))
            {
                show_404();
                return;
            }
    
            $this->task_types_model->ID = ($ID);
            $this->task_types_model->delete($ID);
    
            redirect('tasktypes/display');    
        }
  • #11 / Jun 09, 2009 4:05pm

    Nicholai

    24 posts

    And here is the model.  It’s easiest to let the controller handle business logic and let the model handle any data operations.

    class Admin_task_types_model extends Model {
    
        var $table = 'TaskTypes';
    
        function Admin_task_types_model()
        {
            parent::Model();
        }
    
        function get($ID)
        {
        //if passing a single ID, return one row. if passing NULL, return the entire result set.
            if (isset($ID))
            {
                $this->db->where('ID', $ID);
                $query = $this->db->get($this->table);
                return $query->row();
            }
            else
            {
                $query = $this->db->get($this->table);
                return $query->result();
            }
        }
    
        function save($item)
        {
            //if passing an ID,  call Update.  if not,  call Create.
            $item = (object) $item;
                    
            return (isset($item->ID) and $item->ID > 0) ? $this->_update($item) : $result = $this->_create($item);
        }
    
        function _create($item)
        {
            $item = (object) $item;
            $item->ttDateAdded = date('Y-m-d H:i:s');
            $item->ttDateLastChanged = $item->ttDateAdded;
            $item->ttAddedBy = '1';
            $item->ttLastChangedBy = '1';
    
        return $this->db->insert($this->table, $item);
        }
    
        function _update($item)
        {
            $item = (object) $item;
            $item->ttDateLastChanged = date('Y-m-d H:i:s');
            $item->ttLastChangedBy = '1';        
    
            $this->db->where('ID', $item->ID);
            return $this->db->update($this->table, $item);
        }
    
        function delete() {
    
            // if passing an ID,  delete the record.
            if ($this->ID) {
                $this->db->where('ID', $this->ID);
                $this->db->delete($this->table);
            }
        }
  • #12 / Jul 13, 2009 7:35am

    Fencer

    1 posts

    I can see how using CodeIgniter for CRUD could save a lot of time - once you climb its steep learning curve.

    I’ve been working from the book “CodeIgniter for Rapid PHP Application Development” trying to set up a CRUD application.

    The complexity of that code is so frustrating that I looked back at my traditional PHP database CRUD code for comparison. It’s far easier to follow than any CodeIgniter CRUD operation I’ve seen so far.

    With traditional CRUD coding, you can SEE WHAT THE CODE IS DOING, but with CodeIgniter that’s much more difficult because it’s all abstracted. CodeIgniter may offer less code, but at the cost of complexity.

    I know it’s a great framework, but it needs some really good sample CRUD applications to download to make learning easier.

    I suggest newcomers to MVC should buy the PDF version of “CodeIgniter for Rapid PHP Application Development” from the Packt website for a good introduction. MVC may well be overkill for a lot of developers. It’s certainly far from simple. I’ll stick with it to learn some of its simpler operations befeore I decide whether MVC is for me.

  • #13 / Jul 13, 2009 10:34am

    Johan André

    412 posts

    MVC may well be overkill for a lot of developers. It’s certainly far from simple. I’ll stick with it to learn some of its simpler operations befeore I decide whether MVC is for me.

    I disagree. I come from a standard PHP-coding background and once I read up on MVC (ie understood the basic concept) my programming got alot cleaner. I did’nt find it very hard to learn it. Framework or not, MVC is a very good way of structuring things. I don’t write non-MVC-based websites anymore. I really like the concept of keeping stuff in the right location (models, views, controllers, helpers, libraries…).

  • #14 / Jul 13, 2009 8:16pm

    searain

    101 posts

    It took me 5 evenings to teach myself “traditional php” a few years ago (I was an ASP developer then) and only with these 5 evenings php learning time, I finished a big php project in one month.  And recently ,with years php experience it still took me another 5 evenings just to catch up with CRUD using CodeIgniter.  So fencer said that CI CRUD took “a lot of time”, could be relatively true comparing with the learning curve of traditional php.

    But I don’t think 5 evenings to catch up CRUD in CI is “a lot of time”.  After mastering the crud, the large part of the CI learning tasks is done (specially for the php deveolper’s part of work.).  Although using and developing these libraries, helpers, plug ins would be an ongoing learning task.

    So I think CI’s learning curve is not high at all.

    Now talking about MVC or not? 

    I think we should go to MVC, if we still stuck with the traditional php, without using MVC or Framework, it might be OK for now, but 1 year, 2 or 3 years later, you may find yourself fall behind the market and mainstream.  And you may find your code base is too old too difficult to update due to not so many programmers still use it, so not so many employers will hire traditional php developer, and not so many 3rd stuff you can merge with your own system.

    Even I still believe that the realty CMS I developed is better on traditional php (it is a very simple and easy CMS and if using traditional php, it will be working well with traditional designers, there are still a lot of them we have to work with.), I am rewriting it on CI with MVC approach, if the designers are stuck with the traditional approach, it is him needs change.

    Talk about learning CI or learning CI CRUD?  I do agree with Fencer that find a good book and/or a good sample code system is really helpful.  I have been using several tutorial and sample codes.  But these sample codes were too simple, I got the idea but I still cannot use it on my own easily.  After I bought the book “professional CodeIgniter” by Thomas Myer, and install the sample codes, I then found his sample code was “big” enough to cover almost all my CRUD questions.  The sample codes are still too simple, just for a demo purposes. But with that as a reference, I got the general ideas and pitfalls I should be aware etc.  After read that book and sample codes in 2-3 evenings time, I can start to rewrite my traditional php code base to CI MVC based now.

    In simple words, MVC is the approach we should go, CI is simple and clean framework with short learning curve, and find good sample codes will be really helpful in learning CI. (it is kind hard to find the sample codes you need in the beginning when you are new and don’t know where to go and which sample codes to try etc.)

  • #15 / Aug 15, 2009 7:40am

    ntheorist

    84 posts

    I’m currently developing a CMS with CI and i’m tackling the same issue. The way i’m going is by creating extending controller classes in combination with an ORM (datamapper) which has the validation within it. Having the models self-validate leaves a TON of room for bizlogic and couldn’t be more helpful.

    Start with creating a CRUD_Controller which extends the base controller (or another extend) and running perhaps a switch statement within _remap before calling the method. The _remap loads the template according to the class/method name, and the method would load the data into the template. This way, to add a CRUD controller for say, a User model, you’d have

    class User extends Crud_Controller {
    
          function User()
          {
                parent::Crud_Controller();
          }
    
          // Create, Read, Update, Delete methods inherited
    
          // User-controller specific methods and CRUD overrides go here
    
    }

    views/templates could then be constructed with some automation (in _remap) based on get_class($this), ie. ‘User’, to figure out which model templates to load.

    if that all sounds complicated, it’s cuz it is 😛, but if you can create a standard file structure you could use this method to produce a mostly-automated crud and then all you’d have to do is create view files and an override here and there. Plus it gives you access points to base crud operations allowing for insertion of ACL and such.

    n

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases