add models in models

edited May 2012 in Modules
Hi,
I'm new in FUEL CMS and have general question. What's the easiest way to create multiple model-objects within another model. In other words I need a field in the model which makes it possible to add and edit another model (which is in a 1-to-n-relationship to it). I think the clue is to use the css class add_edit in combination of the multi-mode, but I apparently don't use it properly. Does anyone have a piece of code where this (probably common) case is used?

Example:

Author_model where you can add various Book_model's easily.

cheers

Comments

  • edited 1:18PM
    You can use the "add_edit" css class to modify another modules data from within your own module like so (where "books" is the name of the other module):
    ... $forms['books']['class'] = 'add_edit books';
    If you are wanting the form field to be within your module, I suggest taking a look at the "Associating Categories to Articles" section of the modules tutorial:
    http://www.getfuelcms.com/user_guide/modules/tutorial
  • edited 1:18PM
    thank you. I tried that before. but it always shows an empty window. is there anything i forgot to define?
  • edited 1:18PM
    ok never mind! got it ;)
  • edited 1:18PM
    is it possible to pass the id of the module to the other module (foreign key)?

    in other words i want to create various books with the foreign key author_id within the author model.

    still don't get the connection!

    cheers!
  • edited 1:18PM
    Unfortunately, that currently isn't something you can do at the moment.
  • edited 1:18PM
    thanks a lot for your help!

    i have another question. now since i'm able to add and edit another module within another module, how can i display them in the form?

    what i need is a sort of box/list which displays all added models.

    example:

    $fields['books'] = array('class' => 'add_edit books');

    this returns just a simple text field with add_edit button. after the creation the id of the created element appears in the field. the book is created and saved correctly. but now i want a select-box or list that shows me all books that are created for this author (and are editable).
    i hope you understand what i mean ;)
  • edited 1:18PM
    You could try something like this:
    function form_fields($values = array(), $related = array()) { ... $this->load->model('authors_model'); // get the options using the author's model and a where condition $options = (!empty($values['id']) ? $this->authors_model->options_list('id', 'name', array('id' => $values['id')) : array(); $fields['books'] = array('type' => 'select', 'options' => $options, 'class' => 'add_edit books'); ... return $fields; }
  • edited 1:18PM
    thanks! i tried that before.

    The problem is that the id of the author doesn't exist yet but you have to save and assign books to authors before the author is created.

    so i wrote a module "books_to_authors" which just assigns books to authors. it'll be saved after saving the author, which works if the book-field is just one textfield with the id.

    i still can't manage to create a select box which makes it possible to
    a) load all elements of books which is already assigned to the author
    b) dynamically add the books (without loading the whole author model)
    c) make all editable.

    ideally look like this:

    button

    [add book]

    books:

    - "catcher in the rye" (edit)
    - etc. etc. (edit)


    i'm just to find an elegant way how to make this possible in the backend!

    Cheers,
    keke
  • edited 1:18PM
    Are you using an on_after_save hook and doing a save_related call to save the information for the author similar to below?
    // add books function on_after_save($values) { $data = (!empty($this->normalized_save_data['books'])) ? $this->normalized_save_data['categories'] : array(); $this->save_related('books_to_authors', array('author_id' => $values['id']), array('book_id' => $data)); }
  • edited 1:18PM
    Hello,

    I am also new to fuel cms and need to solve the same problem. I want to manage todolists with multiple tasks. However I could not figure it out with the help of this forum and the admin's answers.

    This is my lists_model:

    <?php if (!defined('BASEPATH')) exit('No direct script access allowed');

    require_once(FUEL_PATH.'models/base_module_model.php');

    class lists_model extends Base_module_model
    {

    public $required = array('list_name');
    public $record_class = 'lists';
    protected $key_field = 'list_id';



    function __construct()
    {
    /* reference to the db table */
    parent::__construct('lists');

    }
    }

    class list_model extends Base_module_record
    {

    }

    And this is my tasks model

    <?php if (!defined('BASEPATH')) exit('No direct script access allowed');

    require_once(FUEL_PATH.'models/base_module_model.php');

    class tasks_model extends Base_module_model {

    public $required = array('task_name');
    public $record_class = 'tasks';
    protected $key_field = 'task_id';
    public $foreign_keys = array('list_id' => 'lists_model');


    function __construct()
    {
    /* reference to the db table */
    parent::__construct('tasks');
    }
    }

    class task_model extends Base_module_record {

    }

    As for now the only consist of a list_id and task_id and a list_name and task_name. Very simple.

    By adding these models/modules to fuel cms the show up just as expected. I can save and delete and edit lists and items just fine.

    Now I want to:

    1. add a button to the list form in order to add tasks.
    2. show tasks below the list form with a delete and edit option.

    I hope someone can help. I am really lost and must admit that I am not really to confident with fuel cms yet. So a detailed solution will be very much appreciated.

    Kind regards from Germany,

    Wilhelmus
  • edited September 2015
    It sounds like you want to use either the repeatable template field or the embedded list field types. The template field type will allow you to create repeatable form fields that can be reordered. The embedded list will provide a list view table with actions (similar to the modules list view).
    http://docs.getfuelcms.com/general/forms#template
    http://docs.getfuelcms.com/general/forms#embedded_list

    The template field type would probably be your best best since it allows you to reorder easily. To implement, you would add it to your model's form_fields method:

    function form_fields($values = array(), $related = array()) { $fields = parent::form_fields($values, $related); $todo_value = (!empty($values['id'])) ? $this->get_todo_value($values['id']) : array(); $fields['todos'] = array( 'display_label' => FALSE, 'type' => 'template', 'fields' => array( 'completed' => array('type' => 'checkbox'), 'todo' => '', ), 'repeatable' => TRUE, 'value' => $todo_value; ); return $fields; }
    Then, you will need to utilize the model's on_after_save hook to save the todo information to the other table with something like the following:
    function on_after_save($values) { $data = $this->normalize_save_values(); if (!empty($data['todos'])) { $this->load->model('tasks_model'); foreach($data['todos'] as $todo) { $todo = $this->tasks_model->create($todo); $todo->save(); } } }
    http://docs.getfuelcms.com/general/models#hooks
  • edited September 2015
    Thank you very much for your quick reply. Everything works perfect. However I had to modify your answer a bit.

    I now run a loop and insert the values as an array, where list_id is the current todo_list_id that is edited, the todo_name is the name and pos is equal to the priority or position of the todo in the list. This number is just incremented everytime I run through the loop.

    foreach($data['todos'] as $todo) { // set value of current todo $value = array( 'list_id' => $todo_list_id, 'todo_name' => $todo['todo_name'], 'todo_pos' => $pos,); // insert value in database $this->iv_questions_model->insert($value); $pos = $pos + 1; }

    Now I wonder if it is possible to also show the todos that are already part of the list e.g. if i have to 2 todos it would be great if two template-fields are already shown with preset data from the database.

    Kind regards,

    Wilhemus
  • edited 1:18PM
    You can do that by assigning the 'value' attribute on the form field. I've modified the answer above to include that. It assumes that there is a method on your model called "get_todo_value" (which it can be named whatever). Basically that method should return an array of associative arrays like so:
    $todo_values = array( 0 => array('id' => 1, 'list_id' => 1, 'todo_name' => 'Todo 1', 'todo_pos' => 1), 1 => array('id' => 2, 'list_id' => 1, 'todo_name' => 'Todo 2', 'todo_pos' => 2) );
  • edited September 2015
    Thank you very much! Everything is working now!

    However I had to pass the data to the default argument like this:

    'default' => $data,
Sign In or Register to comment.