Giter Site home page Giter Site logo

sprig's Introduction

Sprig

A database modeling system for the Kohana framework (v3.0+).

Quick Start

Each model must:

  • extend the Sprig class
  • define a protected _init() method and set the field mappings

Example of a model:

class Model_Post extends Sprig {
    
    protected function _init()
    {
        $this->_fields += array(
            'id' => new Sprig_Field_Auto,
            'title' => new Sprig_Field_Char,
            'blog' => new Sprig_Field_BelongsTo(array(
                'model' => 'Blog',
            )),
            'author' => new Sprig_Field_BelongsTo(array(
                'model' => 'User',
            )),
            'body' => new Sprig_Field_Text,
            'published' => new Sprig_Field_Boolean,
        );
    }
    
}

Interacting with models

Loading models is done with the Sprig::factory($name) method:

$post = Sprig::factory('post');

Loading models by calling new Model_Foo will not work! You must use the factory() method.

Data

Model data is read using object properties:

$title = $post->title;
$body  = $post->body;

Model data is changed the same way:

$post->title = 'A New Title';

You can also use the values() method set many fields using an associative array:

$post->values(array(
    'title' => 'A New Title',
));

Create, Read, Update, and Delete (CRUD)

Reading records is done by setting the search values, then calling the load() method:

$post = Sprig::factory('post');
$post->id = 5;
$post->load();

if ($post->loaded())
{
    // Do something with the post
}

It is also possible to pre-populate the model using an array of values:

$post = Sprig::factory('post', array('id' => 10))
    ->load();

Creating new records is done using the create() method:

$post = Sprig::factory('post', array(
        'title'     => 'My First Blog Post',
        'body'      => 'Created using a Sprig model!',
        'published' => FALSE,
    ));

// Create a new blog post
$post->create();

If the model data does not satisfy the validation requirements, a Validate_Exception will be thrown. This exception should be caught and used to show the end user the error messages:

try
{
    // Create a new blog post
    $post->create();
}
catch (Validate_Exception $e)
{
    // Get the errors using the Validate::errors() method
    $errors = $e->array->errors('blog/post');
}

Updating a record is done using the update() method:

if ($_POST)
{
    try
    {
        $post->values($_POST)->update();
    }
    catch (Validate_Exception $e)
    {
        $errors = $e->array->errors('blog/post');
    }
}

Note that you must always call load() before update() or the query will not be built properly.

Deleting a record is done using the delete() method:

$post->delete();

Forms

It is possible to generate a complete form very quickly using the inputs() method:

<dl>
<?php foreach ($post->inputs() as $label => $input): ?>
    <dt><?php echo $label ?></dt>
    <dd><?php echo $input ?></dd>
    
<?php endforeach ?>
</dl>

Each input will be populated with the current value of the field.

If you need the field name as the inputs() key instead of the label, use FALSE:

$inputs = $post->inputs(FALSE);

echo $inputs['title'];

Customizing the Form

Creating custom forms can by done using the input() method to create place individual fields:

<div class="post-title">
    <?php echo $post->input('title', array('class' => 'spellcheck fancy')) ?>
</div>
<div class="post-body">
    <?php echo $toolbar ?>
    <?php echo $post->input('body', array('class' => 'wysiwyg')) ?>
</div>

This allows much finer control of how your forms are displayed, at gives control over what fields will be updated.

Field Object Reference

Accessing a field object is done using the field() method:

$title = $post->field('title');

An array of fields can be accessed using the fields() method:

$fields = $post->fields();

Types of fields

Sprig offers most database column types as classes. Each field must extend the Sprig_Field class. Each field has the following properties:

empty : Allow empty() values to be used. Default is FALSE.

primary : A primary key field. Multiple primary keys (composite key) can be specified. Default is FALSE.

unique : This field must have a unique value within the model table. Default is FALSE.

null : Convert all empty() values to NULL. Default is FALSE.

editable : Show the field in forms. Default is TRUE.

default : Default value for this field. Default is '' (an empty string).

choices : Limit the value of this field to an array of choices. This will change the form input into a select list. No default value.

column : Database column name for this field. Default will be the same as the field name, except for foreign keys, which will use the field name with _id appended. In the case of HasMany fields, this value is the column name that contains the foreign key value.

label : Human readable label. Default will be the field name converted with Inflector::humanize().

description : Description of the field. Default is '' (an empty string).

filters : Validate filters for this field.

rules : Validate rules for this field.

callbacks : Validate callbacks for this field.

Sprig_Field_Auto

An auto-incrementing (sequence) field.

Implies primary = TRUE and editable = FALSE.

Sprig_Field_Boolean

A boolean (TRUE/FALSE) field, representing by a checkbox.

Implies empty = TRUE and default = FALSE.

Sprig_Field_Char

A single line of text, represented by a text input.

Also has the min_length and max_length properties.

Sprig_Field_Password

A password, represented by a password input.

Also has the hash_with property, a callback used to hash new values.

Note: For security reasons, the input generated by a password field will never have a value attribute.

Sprig_Field_Float

A float or decimal number, represented by a text input.

Also has the places property.

Sprig_Field_Integer

An integer number, represented with a text input (or a select input, if the choices property is set).

Also has the min_value and max_value properties.

Sprig_Field_Text

A large block of text, represented by a textarea.

Sprig_Field_Enum

Extends Sprig_Field_Char, but requires the choices property.

Sprig_Field_Email

Extends Sprig_Field_Char, but requires a valid email address as the value.

Sprig_Field_Timestamp

Extends Sprig_Field_Integer, but requires a valid UNIX timestamp as the value.

Also has the format (any string accepted by date) and auto_now_create and auto_now_update properties.

Sprig_Field_Image

Extends Sprig_Field_Char, represents an image file.

Requires the path property, the path to the directory where images will be stored.

Sprig_Field_HasOne

A reference to another model by the parent model primary key value. Does not produce a form input.

Has the model property, the name of another Sprig model.

Sprig_Field_BelongsTo

A reference to another model by the child model primary key value. Represented by a select input.

Has the model property, the name of another Sprig model.

Sprig_Field_HasMany

A reference to many other models by this model primary key value. Does not produce a form input.

Has the model property, the name of another Sprig model.

Sprig_Field_ManyToMany

A reference to another model by a pivot table that contains the both primary keys. Represented by a list of checkbox inputs.

Has the model property, the name of another Sprig model.

Has the through property, the name of the pivot table. By default, uses both model names, sorted alphabetically and combined with an underscore. For example: a many-to-many relationship between Model_Post and Model_Tag would default to post_tag as the table name.

Many To Many Relations

There's a few ways to add and remove many to many relations. The first is to use the raw field names:

$post->foos = array(1, 2, 3);

This will completely overwrite all the relationships for this model. The only relations to this model will be 1, 2 and 3.

The second way is to use the relate() and unrelate() methods:

$post->relate('foos', 1);

You can also pass an object:

$post->relate('foos', $foo);

Or an array of ids:

$post->relate('foos', array(1, 2, 3));

Or an array of objects!

$post->relate('foos', array($foo1, $foo2, $foo3));

Removing Relations

To remove a relation, use the same techniques as above.

$post->foos = array(1, 2, 3);

This will completely overwrite all the relationships for this model. The only relations to this model will be 1, 2 and 3.

Use unrelate() instead of relate():

$post->unrelate('foos', 1);

You can also pass an object:

$post->unrelate('foos', $foo);

Or an array of ids:

$post->unrelate('foos', array(1, 2, 3));

Or an array of objects!

$post->unrelate('foos', array($foo1, $foo2, $foo3));

sprig's People

Contributors

dewos avatar ekingery avatar jerph avatar kerkness avatar leth avatar levi avatar samsoir avatar sfgeorge avatar zombor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sprig's Issues

Sprig->loaded() Bug

Sprig->loaded() has an invalid return bug.

For example:

In the quick start guide, you have the following:

 $post = Sprig::factory('post');
 $post->id = 5;
 $post->load();

 if ($post->loaded())
 {
     // Do something with the post
 }

Assume that 'Post Model' has one one primary key ( 'id' ) and there is NO post with an ID of 5 (as in the example) in the database. When sprig's loaded() function gets called it will come to line 477 in sprig.php

 return (bool) $this->$pk;

Because the id was actually set ( $post->id = 5; ), the function will essentially return

 return (bool) 5;

Which is true, even though in the database there is no post with an ID of 5.

Booleans don't make working checkboxes via input()

Unless i'm doing something fundamentally wrong, I have a tinyint column in my database, defined as a Sprig_Field_Boolean, and using input() to draw it will always draw it unchecked, and will only save the value if the box is checked.

I solved this by editing sprig/classes/sprig/field/boolean.php

$checkbox = Form::checkbox($name, 1, $value, $attr);

to

$checkbox = Form::checkbox($name, 1, ($value?TRUE:FALSE), $attr);

because Form::checkbox uses if ($value === TRUE), and my database was giving it a 1.

As for the other fix, i just did an array merge (i have 3 boolean checkboxes) that are 0, and they get overwritten if they are in the $_POST as 1

Call single input from Sprig

Just a feature request.. not even sure it's a good one ( untested code example )

// usage
echo $post->input('title');

// instead of
echo $post->fields('title')->input('title');


/**
 * Get the input for a single field 
 *
 * @param string $name
 * @param array $attr
 * @return string
 */
public function input($name, array $attr = NULL)
{
    if (is_array($this->_fields[$name]->choices))
    {
        return Form::select($this->_fields[$name], $this->_fields[$name]->choices, $this->_fields[$name]->value, $attr);
    }
    else
    {
        return Form::input($this->_fields[$name], $this->_fields[$name]->verbose(), $attr);
    }
}

default value not being assigned

Bug in Sprig_Field::clone() preventing default value from being set

I updated mine to the following..

public function __clone()
{
    // Set an empty value
    if ($this->default !== NULL)
    {
        $this->set($this->default);
    } 
    else 
    {
        $this->set(NULL);
    }
}

Add Description to Sprig_Field ?

or someway to allow for .. ?

foreach( $post->inputs('TRUE') as $id=>$field ) :
    echo $field->label;
    echo $field->description;
    echo $field->input($id);
endforeach;

Feature Request : ignore property for fields

Some forms require fields which are not actually part of a data model. It would be nice to use Sprig to still generate the form, validate these fields but not throw an error when the field is NOT actually in the table.

I suggest an 'ignore' property or 'db_ignore' property is added to Sprig_Field and when set to TRUE the main Sprig class will ignore this field during DB::insert and DB::update calls.

If you think this is worth while I will build it into my forked version of Sprig and send a pull request.

loaded() state seems to be wrong

TestCase One:

$sprig->id = 1; 
$sprig->load(); 
$sprig->delete(); 

// id =1 is correctly deleted 
$sprig->id = 1; 
$sprig->load(); 

// loaded returns TRUE 
$this->assert_equal($sprig->loaded(), FALSE); 

TestCase 2:

$sprig->id = 1;
$sprig->load();
$this->assert_equal($sprig->loaded(), TRUE);

// id 10 does not exist => test returns TRUE
$sprig->id = 10;
$sprig->load();
$this->assert_equal($sprig->loaded(), FALSE);

LazyLoader Branch: HasMany Read Bug

I'm hoping this does not relate to this issue

Got a chance to play with the lazyloader branch today, cool stuff... To put it simply, when _get()'ing a HasMany relationship, it loops through the Database_Result and then attempts to set the key of the $value array as an object.

On line 45 of hasmany.php

     $value[$id] = parent::value($id);

Easy patch:

     $id = parent::value($id);
     $value[$id] = $id;

Feature Request: Extend $hash_with to more general call backs

As I suggested on the forums

I think a generalisation of the $hash_with property in Sprig Password would make Sprig much more flexible without modifying lots of code.

My suggestion:

In Sprig_Field implement:

public function on_set($value)
{
    return $value;
}

public function before_save($value)
{
    return $value;
}

These methods can then be over-ridden by sub-classes to implement things like password hashing or other modification of values.

$field->on_set($value) would be called directly before the value is set in Sprig::set() and $field->before_save($value) should be called directly before the save to database but AFTER Validation in Sprig::create() and Sprig::update(). There is currently no way to mimic this (save) functionality without duplicating the entire save() and update() code in an extension of Sprig.

The on_set functionality could now be mimicked by setting an appropriate call back (say to a static method) using $hash_with property but if the use isn't for hashing, this is a confusing name.

There is an argument for using callbacks as properties instead of class methods as it allows the call back to be passed in the array to Sprig_Field::construct(). If that behaviour is more desriable perhap instead of the above Sprig_Field could get two properties called $on_set_callback and $before_save_callback or similar. These could be NULL by default and if callable, hould be called like the methods above. This way I can specify callback to any existing Sprig_Field_* class without having to override the whole class. If I want to keep the callbacks in the Class, I can create them as static methods and pass the appropriate callback array() to construct().

As you may be able to tell, I've swayed more towards the second implementation - change the name of $hash_with to something more generic and add another to allow modification directly before saving to Database.

Thoughts are welcome from all.

Sprig->__get and HasMany relation

The latest commit seems to have upset the HasMany relationship.

line 164 tries to load the id's using the field's get method, but it should be using the related method?

line 164 in latest commit is:
if ($ids = $field->get())
but it should be ?:
if ($ids = $this->related($name))

Sprig delete() does not delete a record

There are no errors, but nothing is deleted.

Problem is in this condition
if ($changed = $this->changed())

There shouldn't be changed fields, but primary key fields IMO.

Sprig_Field_ForeginKey & Function 'select_list' Bug

Sprig's "select_list()" function defaults the 'key' and 'value' to' id' and 'name' (respectively) even though not all tables might contain a 'id' or 'name' column.

This error occurs when any Sprig_Field_ForeginKey is being constructed and immediately calls the select_list() function when trying to build the '$this->choices' list for 'inputs()'.

 $this->choices = Sprig::factory($options['model'])->select_list();

Because it uses the defaults in select_list(), the function will throw a Database_Exception list if the table it is connecting to doesn't have a 'id' field or'name' field. (ID is pretty common so it isn't a problem, but 'name' is not).

Sprig->check() Bug

Sprig->check() has a bug when trying to invoke the "in_array" rule for a "HasOne" relationship. It attempts to find a Model (aka the $needle) in an array of integers (primary key's of possible "HasOne" relationships aka the $haystack).

When it tries to invoke the in_array rule it gets the following error:

 Object of class Model_$name could not be converted to int

Sorry if this sounds confusing... it's very hard to word. Let me know if you need me to go into more detail or send you my example.

Sprig_Field "unqiue" attribute

Please verify that "unqiue" attribute for a field is being enforced properly.

Instead of throwing a "Validation_Exception", it's throwing a

"Database_Exception [ 1062 ]: Duplicate entry" (the "unqiue" validation rule is never enforced, therefore throwing a duplicate entry error using InnoDB)

(Although this does work, it would be cleaner for SPRIG to throw a Validation_Exception)

HasMany value() function array-building error

It looks like a Database_Result object is getting passed into this as $value, which gets converted to an array of model objects. When iterating through the $value array to build the final resulting array (on line 45) it has this:

$value[$id] = parent::value($id);

This throws an exception, however, as it seems to be trying to use the Model object as a key for the resulting $value array. It seems like it ought to instead be:

$value[parent::value($id)] = $id;

This would result in an array that has the primary key of the model as the index and the model instance itself as the value.

Am I on the right track, or am I missing something in how this is built to work?

Sprig_Field_ForeignKey needs a custom verbose-method

Sprig_Field_ForeignKey needs a custom verbose-method that retrieves the value, similar to the verbose method in Sprig_Field_HasMany:

public function verbose($value)
{
    return $this->value($value);
}

This is related to the previous issue about the input-method of the Sprig_Field_BelongsTo class, which uses the verbose method to retrieve the value.

Update Quick Start menu

Quickstart says to "define a public init() method and set the field mappings".

The user should be defining "protected function _init()" instead of "public function init()", to complement the abstract function in spring.php as documented in the code.

ForeignKeys are currently required to be integers

I've got a model (Post) that BelongsTo another (Book). Book has as a primary key the Amazon identifier for the book, which can be a numeric ISBN or an alphanumeric ASIN.

Establishing the relationship between a Post and a Book is easy when the Book has an ISBN. But when the book has an ASIN (starting with the letter "B", for example) the __set fails.

It looks like because Sprig_Field_ForeignKey extends Sprig_Field_Integer, all foreign key relationships are required to be Integers. And that just won't work in this case.

Feature Request: Sprig_Field_ManyToMany Add

Sprig_Field_ManyToMany public function add(array $values)

Ex:
Where 'authors' and 'books' have a many-to-many relationship through authors_books

 $new_book = Sprig::factory('book', array(
      'name' => 'My New Book'
 ))->load();

 if ($new_book->loaded())
 {
      $author->field('books')->add(array($new_book));
 }

Table prefix for column names in load function

If I pass a query that contains a join to sprig, it fails if the tables have columns with the same name (eg. they both have an id field). I can prefix all the columns in the query I pass but not the ones that sprig adds from the model.

As a temp fix I changed line 837 of sprig.php to
$query->select($this->_table[1].'.'.$name);
but im sure that there is a nicer way to do this

Typo in Sprig->create() method

Typo in line 385 preventing the updating of the ID field

// Line reads
if ($this->_fields[$field] instanceof Spig_Field_Auto)

//  Should read
if ($this->_fields[$field] instanceof Sprig_Field_Auto)

Sprig_Field_Timestamp issue?

Sprig_Field_Timestamp extends Sprig_Field_Integer. While setting the timestamp it creates a formatted result. However, it calls parent::set at the end with that formatted result and the Integer set function alters it. The example I'm seeing is:

'2009-10-21 21:07:23' -> 2009

Possible fix is to extend Sprig_Field_Char.

Sprig_Field_HasMany Bug

This is more of a convention vs. configuration problem, but could be a bug.

I've been testing with two Models. Model "Perm_Group" HasMany "Perm" models. Model "Perm" HasOne "Perm_Group".

 class Model_Perm_Group extends Sprig {
      protected $_table = 'perm_groups';
      protected function _init()
      {

            ...

            'perms'                  => new Sprig_Field_HasMany(array(
                 'model'             => 'Perm',
            )),
      }    
 }


 class Model_Perm extends Sprig {
      protected $_table = 'perms';
      protected function _init()
      {

            ...

            'group'             => new Sprig_Field_HasOne(array(
                 'model'          => 'Perm_Group',
                 'column'      => 'perm_group_id',
            )),
      }    
 }

Notice that the field for Model "Perm" is called "group" and not "perm_group". I was under the impression that since I explicitly stated the column, a HadMany relationship would search for the column name and not the field name. When trying to fetch all of the perms in the perm group:

 $perm_group->perms

It returns ALL the rows in the "perms" table regardless of the foreign key. This is because it is looking for a field with name "perm_group" which it wouldn't find, since it is named "group" (with a column name "perm_group_id"). It then returns all the rows.

However if I switch Model_Perm's HasOne relationship to

 'perm_group'             => new Sprig_Field_HasOne(array(
      'model'         => 'Perm_Group',
  )),

Everything works fine. I'm not sure if this is more of a "I screwed up the convention vs. configuration design pattern" or this is a bug.

If I went against the design pattern, a possible feature request would be to have a Sprig_Field_Reference. It would also help with maintenance and backward compatibility of models for developers.

 'perm_group'       => new Sprig_Field_HasOne(array(
      'model'         => 'Perm_Group',
  )),
  'group'               => new Sprig_Field_Reference('perm_group'),

Calling $foo->input() on empty fields triggers lazy load

I'm doing some form validation and have spotted a bug;

If input is set using $foo->values($_POST) and any of the fields match the default value it will cause the $foo->input(...) call to attempt to lazy-load from the database, using the other fields in the where clause.

This is an issue primarily because the script I'm writing is only allowed insert privileges on the table, not select. But in the long run, this shouldn't really be causing an extra select.

I'm not really sure how to fix this...

Sprig_Field_BelongsTo->input

The value of the select is retrieved using the verbose method. Shouldn't this be retrieved using the value method?

return Form::select($name, $choices, $this->value($value), $attr);

The Sprig_Field_HasMany class uses the value method.

Lazyloading create() relationships not set correctly

In line 930, local array $relations is set to store a list of relation table rows to create:

$relations[$name] = $value;

However $name is NOT set to the name or the field as expected. $name still contains the last field name from the previous foreach loop. This foreach loop starts;

foreach ($data as $field => $value)
    {
        $field = $this->_fields[$field];

Which means that there is no variable with the correct field name to key this array as expected.

Suggested fix is to change lines 922 to 924 to read:

foreach ($data as $name => $value)
    {
        $field = $this->_fields[$name];

This error ISN"T duplicated in update() as the foreach loop uses $name rather than $field as expected.

Rule not_empty not working

Trying to get a field to validate as required. Doesn't seem work.

$field = new Sprig_Field_Char(array(
    'rules' => array(
        'not_empty' => NULL,
    ),
));

Also tried setting $field->null = FALSE and $field->empty = FALSE, not sure what these are intended for yet.

Sprig->init() MantToMany infinite recursion

When the "through" property is being automatically generated for a MantToMany field, it reaches the line:

 $table = array((string) $this, (string) Sprig::factory($field->model));

Which will cause infinite recursion between the two models because both have a ManyToMany field ( therefore continuously calling "(string) Sprig::factory($field->model))" )

$this->_primary_key Bug

Line 666 (I guess it's bad luck :) ) in create()

 foreach ($this->_primary_key as $field)

assumes that $this->_primary_key is always going to be an array. However, based on default config during init() lines 132-136

 if ( ! $this->_primary_key)
 {
      // This is the primary key
      $this->_primary_key = $name;
 }

will make $this->_primary_key a string, not an array.

Primary key model

When trying to update (possibly during create to), if a model is a primary key (BelongsTo) the query builder will send the model into the where clause

Line 1064:
$query->where($this->_fields[$this->_primary_key]->column, '=', $this->_original[$this->_primary_key]);

Sprig->verbose($field) gives errors

My model item has a field date which is a Sprig_Field_Timestamp

$item = Sprig::factory('item');
echo $item->verbose('date');

This gives a nice error: Missing argument 1 for Sprig_Field_Timestamp::verbose() (line 797)
I suppose this does not only apply to the timestamp field, but any field in general, as there is no default value for the verbose-method argument.

edit: Also, the check "if ($value)" is a bit awkward: value 0 is valid, but not shown?

HasMany and ManyToMany have no way to set the values

As far as I can see there is no way to use HasMany and ManyToMany relationships in the current code.

In both classes the set() method simply casts the value to and array and then sets it.

This means that if you assign a Sprig object, it gets cast to an array and asigned which completely fails.

Even if you set it using an array of integers (or primary keys) which won't be destroyed by the cast, there is no code in create() or update() that actually handles updating the pivot table or model table.

Further, an error is genrated when using many to many as the raw() method calles $this->value->as_array() however $this->value has been cast to an array so can't possibly be an object with an as_array() method.

I'm surprised no one else has mentioned any of this here so I thought I would. Would submitting patches be of assistance to get this working properly?

Thanks

Sprig_Field_Float::verbose() doesn't appear to work with DECIMAL

is_float() returns FALSE for MySQL's DECIMAL data types becase it is not a true floating point.

Here's my workaround:

class Sprig_Field_Decimal extends Sprig_Field_Float {

    public function verbose($value)
    {
        if (is_numeric($value))
        {
            if ($this->places)
            {
                return number_format($value, $this->places);
            }
            else
            {
                return (string) $value;
            }
        }
        else
        {
            return '';
        }
    }

} // End Sprig_Field_Decimal

Sprig objects with many/many to many relationships are currently unserializabe

Related to http://dev.kohanaphp.com/issues/2297

I have fixed the issue temporarily by adding the following method to Sprig

/**
 * Allow serialization of initialized object containing related objects as a Database_Result
 * @return array    list of properties to serialize
 */
public function __sleep()
{
    foreach ($this->_related as $field => $object)
    {
        if ($object instanceof Database_Result)
        {
            if ($object instanceof Database_Result_Cached)
            {
                continue;
            }

            // Convert result object to cached result to allow for serialization
            // Currently no way to get the $_query property form the result to pass to the cached result
            // @see http://dev.kohanaphp.com/issues/2297

            $this->_related[$field] = new Database_Result_Cached($object->as_array(), '');              
        }
    }       

    // Return array of all properties to get them serialised
    $props = array();

    foreach ($this as $prop => $val)
    {
        $props[] = $prop;
    }

    return $props;
}

This converts Database_Result objects in $_related into Database_Result_Cached objects which will survive serialization (for example when a user and their roles are stored in session in Auth).

The issue recorded above is regarding the fact that there is no way to retrieve the query from the Mysql result object so it is lost in the conversion. This is not of practical significance in this case but is less than ideal in general.

This seems to me like a neat way to make Sprig objects serialize safe without changing the interface to use a different container object for relations or anything more drastic.

If for some reason it is decided not to include this in Sprig core, I will put it in a fork for people to use if required however it seems that having objects that are potentially unserializable is not particularly desirable and I don't think this is an untidy solution. It would be even better if the issue posted to Redmine is also resolved in some way.

Sprig->create() Bug (Quick Fix)

Minor bug during create(). This is related to Issue 13 (Sprig->check() Bug)

Currently, during create() the following is executed (line 682 in Sprig.php):

 // Check the data
 $data = $this->check($this->as_array());

It sends the entire object as an array to the check method, even if the some of the fields aren't changed (because it skips the $this->changed() method it also doesn't properly convert models to ints which was the problem in Issue 13).

Simple fix is to not send any parameters and let check() pull the changed values

 // Check the data
 $data = $this->check();

HasOne. How to set fk name?

For example, I have Model_Test1 with HasOne field named 'test2', and Model_Test2 with column 'test1_id' as foreign key. When I call $test1->test2, I receive empty test2 object.

How can I tell Sprig to use 'test_id' instead of 'test1' currently using by default?

Sprig_Field_ManyToMany choices

In Sprig_Field_ManyToMany, $this->choices is never set.

This causes an "ErrorException [ Warning ]: Invalid argument supplied for foreach()" any time the inputs() method is used for a many-tomany field.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.