• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ActiveRecord for CodeIgniter: Rails-style model interactions

#71
[eluser]Matthew Pennell[/eluser]
I created the initial implementation of this class, but then got bogged down with a project for months - glad to see the great work that's been done by chromice and others on extending the ActiveRecord class. I'll hopefully be able to find time to contribute to the ongoing work in the new year. Smile

#72
[eluser]zeratool[/eluser]
Hello people,

I wonder why i got this error

"faultCode1faultStringFatal error:Call to a member function find() on a non-object in /home/httpd/webapps/myapp/controllers/index.php on line 16"

just followed the instructions but still no luck

from a controller file:

$this->ad =& $this->load->model('ad');
$this->ad->find(1);


-------
from a model:

class Ad extends ActiveRecord {

function __construct()
{
parent::ActiveRecord();
$this->_class_name = strtolower(get_class($this));
$this->_table = $this->_class_name . 's';
$this->_columns = $this->discover_table_columns();
}

}


pls somebody help me, thanks

#73
[eluser]KJSDFHASD78FASDF78SA[/eluser]
I've uploaded the new version (look for "Development version"). I still have little time to write a proper manual and a simple tutorial, and may not have it for the next several months. But the good news is that I use this library in my projects a lot, so it is under constant development.

NB! MySQL is my database of choice, so all features are guaranteed to work in MySQL v4.1 and higher. If you use some other database advanced (or even simple) stuff may not work or may be broken, fill free to provide your own implementation and fixes.

@zeratool: $this->load->model() method does not return anything. So nothing gets assigned to $this->ad.

#74
[eluser]beemr[/eluser]
Chromice, Buddy Bradley, et al. Muchos gracias for the great library.

Question: How can I access the ActiveRecord join relationships to get field metadata across tables?

For my own project, I've made a library which uses MySQL "show full columns" to assist in building forms. As it has developed, I've placed it into ActiveRecord 0.7 so it would be available for all of my models. If I can figure it out, I'd like it to access related tables through the ActiveRecord relationships.

I'd like to be able to do this:
$this->user->join_profiles()->field_meta_public(TRUE)
and receive form attributes for all of the "public" fields in both tables. Right now, it does this:

In controller:
Code:
$data['fields'] = $this->user->field_meta_public(TRUE);

In view:
Code:
<?php foreach($fields['input'] as $field)
    {
         echo form_input($field);    
    }
?>
<?php foreach($fields['checkbox'] as $field)
    {
         echo form_checkbox($field);    
    }
?>

#75
[eluser]beemr[/eluser]
Here's the code after adding 'fields_meta_' to the $watch array:
Code:
/**
     * _fields_meta
     *
     * Uses MySql's show full columns string to display a full array of
     * field metadata.  The optional parameter will return an array of
     * $input, $textarea, and $checkbox arrays ready to be used by the CI
     * form helper. $scope is switched by adding _public _private or _all.
     * _public is any field that is NOT NULL, default!==null, type doesn't
     * contain 'time', or doesn't have 'admin' in comments. _private is
     * the remainder of the fields. _all is all of the fields. 'Boolean'
     * is an assumed type for any tinyint(1) NOT NULL with a default value
     * of 0 or 1.
     *
     * For future: validation rules, POST catching
     *
     * @access    public
     * @param    string
     * @param    string
     * @return    object
     */

    function _fields_meta($scope,$form = FALSE)
    {
        $sql = "SHOW FULL COLUMNS FROM ". $this->_table;
        $query = $this->db->query($sql);
        foreach ($query->result() as $field)
        {
            /* Explanation of the ugly regex:
            **   match until first non '('
            **   then optionally match numbers '\d' inside brackets '\(', '\)
            */
            preg_match('/([^(]+)(\((\d+)\))?/', $field->Type, $matches);
            $type           = sizeof($matches) > 1 ? $matches[1] : null;
            $max_length     = sizeof($matches) > 3 ? $matches[3] : null;

            $F              = new stdClass();
            $F->name        = $field->Field;
            $F->type        = ($type == 'tinyint' && $max_length == 1 && $field->Default == 0|1) ? 'boolean' : $type;
            $F->default     = $field->Default;
            $F->max_length  = $max_length;
            $F->primary_key = ($field->Key == "PRI") ? 1 : 0;
            $F->comment     = $field->Comment;
            $F->collation   = $field->Collation;
            $F->extra       = $field->Extra;
            $F->unique        = ($field->Key == "UNI") ? 1 : 0;
            $F->required    = ($field->Null == "YES") ? 0 : 1;

            $retval[] = $F;
        }
        switch($scope)
        {
            case 'public':
                $public = array();
                foreach ($retval as $field)
                {
                    if ($field->name != 'id' && strpos($field->name,'_id')!=strlen($field->name)-3 && $field->default!==null && $field->required && strpos($field->comment,'admin') === FALSE && strpos($field->type,'time') === FALSE)
                    {
                        array_push($public, $field);
                    }
                }
                $retval = $public;
                break;
            case 'private':
                $private = array();
                foreach ($retval as $field)
                {
                    if (($field->name == 'id' || strpos($field->name,'_id')==strlen($field->name)-3 || (!$field->required && !$field->default) || strstr($field->type,'time')) || strstr($field->comment,'admin'))
                    {
                        array_push($private, $field);
                    }
                }
                $retval = $private;
                break;
            default:
        }
        switch($form)
        {
            case TRUE:
                $input = array();
                $textarea = array();
                $checkbox = array();
                foreach($retval as $field)
                {
                    switch($field->type)
                    {
                        case 'text':
                            array_push($textarea, array(
                                'name' => $field->name,
                                'id' => $field->name,
                                'maxlength' => $field->max_length,
                                'size' => 40
                            ));
                            break;
                        case 'boolean':
                            array_push($checkbox, array(
                                'name' => $field->name,
                                'id' => $field->name,
                                'checked' => ($field->default) ? TRUE : FALSE
                            ));
                            break;
                        default:
                            array_push($input, array(
                                'name' => $field->name,
                                'id' => $field->name,
                                'maxlength' => $field->max_length,
                                'size' => $field->max_length
                            ));
                    }
                }
                $retval = array(
                    'input' => $input,
                    'textarea' => $textarea,
                    'checkbox' => $checkbox
                );
                break;
            default:
        }
        return $retval;
    }
}
?>

#76
[eluser]easymind[/eluser]
Hi, nice work. I am also using it to create a formlibrary. I only have a slight wish/problem.

I want to foreach through the fields, of an object I created with your class and filled with a tablerow.

So for example:
Code:
$Voorstelling =& $this->load->model('Voorstelling');
$voorstelling = $Voorstelling->find($id);
foreach($voorstelling as $field=>$value)
{
    echo "$field has value $value<br/>";
}

As you are probably aware this is not doing what I want because the fields and their values are among many many other variables and values in the object. It seems the whole $CI or $this is inside the object. Any idea?

#77
[eluser]KJSDFHASD78FASDF78SA[/eluser]
@beemr

You can try to retrieve the list of joined table's columns via $this->_select property. However, if you need full info, you've got to "SHOW FULL COLUMNS FROM " for each joined table ($this->_join property).

@easymind

The simplest way to do that is to ask the model to return a plain object instead of an Active Record instance:
Code:
$this->load->model('voorstelling');
$voorstelling = $this->voorstelling->find($id, RETURN_NEW, PLAIN_OBJECT);

foreach($voorstelling as $field=>$value)
{
    echo "$field has value $value<br/>";
}

#78
[eluser]easymind[/eluser]
Well, as I said. I still have got the whole $this inside the object. I have in the object:
- _parent_name
- objectname
- _ci_scaffolding
- _ci_scaff_table
- config
- input
- benchmark
- uri
- ...etc and inbetween I have my table fields

Your constants RETURN_NEW and PLAIN_OBJECT are 'noticed' but probably used...

#79
[eluser]easylancer[/eluser]
I need a PHP 4 version of the ActiveRecord Library, anyone has it?

#80
[eluser]beemr[/eluser]
Thanks for pointer, Chromice. Very easy to access. Love the direction of this library. The AR Models read like simple documentation, and the methods available to controllers almost read like a simple flowchart.

Already making a slim Auth library with your Mod, which is how I started writing the table-sniffing code. Right now, I have to add my methods to your library in order to build a form object referencing the joined tables. Was wondering if you know how I might limit the edits that I am making to your code. I'd like to keep my mess clear of your library, but not sure if it's possible.

At a minimum, I think I have to ad the $watch string ('fields_meta_') to your class overloading. Can I have the function '_fields_meta' and its dependancies load through an additional library or as an extension of the Model class? I've successfully made both, but haven't figured out how the $watch call can make the connection outside of its own library. I'm thinking this is a dead end, and I'll have to muck your code. The code integration is pretty much what I posted before. I'll post the latest if you need it.

By all means, ignore this if it prevents your noble work on AR! Thanks! (and to Buddy Bradley, respect)


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2021 MyBB Group.