Retrieve record in class that extends Base_module_record

edited October 2011 in Modules
In my news model, I'm having trouble trying to figure out how to retrieve a record
from another table in the class that extends Base_module_record.

In my get_url function I need to create a url segment for the post based on a 'silo name'
that is selected when creating the news post.

I have silos set up the same as categories in a silos_to_news_model that generates a multi list.

How can I retrieve the name of the silo the user selects from the list?

For testing, I'm currently using a 'link' field in the model that the user creates themselves.

Here is the beginning if my class with the get_url function...

class News_item_model extends Base_module_record { function get_url() { $silo = $this->link; $year = date('Y', strtotime($this->release_date)); $month = date('m', strtotime($this->release_date)); $day = date('d', strtotime($this->release_date)); $url = site_url('news/'.$silo .'/'.$year.'/'.$month.'/'.$day.'/'.$this->slug); return $url; } Rest of code...

Hope I've given enough info.

Thanks.

Comments

  • edited 2:33PM
    I'm not quite sure I understand the question but let me try. Are you wanting to get the name of the silo as opposed to the ID value (which I'm assuming is saved with the news item)?

    If so, I'd recommend adding a "silo" property to your News_item_model and then adding a join to that table in your News_model in the _common_query() method like so:
    function _common_query(){ parent::_common_query(); $this->db->select('news.*, silos.name AS silo'); $this->db->join('silos', 'news.silo_id = silos.id', 'left'); }

    When the News_model generates the record, it will also populate the new "silo" property that was assigned to your News_item_model class:
    class News_item_model extends Base_module_record { public $silo = ''; ....
  • edited 2:33PM
    Thanks for the help.

    Yes, I would like to get the name of the silo to insert into the url as a segment.

    I have a multi-select set up in the news model that is populated by the silos model option list.
    (Ideally this should be a select dropdown where you can only select one silo, but I need to limit
    the list to the silos the user has permissions for...don't know how to do this for a select drop-down yet.)

    The silo that is chosen from the multi-select gets stored in the silos_to_news table, which is set up like the
    categories_to_articles_model from the articles tutorial.

    I tried your solution but can't quite get it to work.

    I don't have this column in my news table...news.silo_id. I tried adding it but it geterates a text field in the form. How do I populate this column with the silo id without it creating a text field?

    The public $silo = '' variable is not being recognized either.

    I apologize if this is really simple stuff. I'm fairly new at CI and OOP.

    Here is my full news_model code...

    <?php if (!defined('BASEPATH')) exit('No direct script access allowed'); require_once(FUEL_PATH.'models/base_module_model.php'); class News_model extends Base_module_model { public $required = array('headline', 'link', 'categories'); public $record_class = 'News_item'; public $parsed_fields = array('content_formatted'); function __construct() { parent::__construct('news'); // table name } function list_items($limit = NULL, $offset = NULL, $col = 'release_date', $order = 'desc') { $this->db->select('id, headline, slug, published, link, silo_name'); $data = parent::list_items($limit, $offset, $col, $order); return $data; } function on_before_clean($values) { if (empty($values['slug'])) $values['slug'] = url_title($values['headline'], 'dash', TRUE); if (!intval($values['release_date'])) $values['release_date'] = datetime_now(); return $values; } function form_fields($values = array()) { $fields = parent::form_fields(); $CI =& get_instance(); $CI->load->model('categories_model'); $CI->load->model('categories_to_news_model'); $CI->load->model('silos_model'); $CI->load->model('silos_to_news_model'); // config settings are located in fuel/application/config/config.php $news_config = $CI->config->item('news'); // html formatting options for news content (automatic or none) if (!empty($news_config['formatting']) ) { $news_config['formatting'] = (array) $news_config['formatting']; if (count($news_config['formatting']) == 1) { $fields['formatting'] = array('type' => 'hidden', 'options' => current($news_config['formatting']), 'default' => $fields['formatting']['default']); } else { $fields['formatting'] = array('type' => 'select', 'options' => $news_config['formatting'], 'default' => $fields['formatting']['default']); } } // caregory options $category_options = $CI->categories_model->options_list('categories.id', 'categories.name', array('categories.published' => 'yes'), 'categories.name'); $category_values = (!empty($values['id'])) ? array_keys($CI->categories_to_news_model->find_all_array_assoc('category_id', array('news_id' => $values['id'], 'categories.published' => 'yes'))) : array(); $fields['categories'] = array('label' => 'Categories', 'type' => 'array', 'options' => $category_options, 'value' => $category_values, 'mode' => 'multi'); // silo options $silo_options = $CI->silos_model->options_list('silos.id', 'silos.name', array('silos.published' => 'yes'), 'silos.name'); $silo_values = (!empty($values['id'])) ? array_keys($CI->silos_to_news_model->find_all_array_assoc('silos_id', array('news_id' => $values['id'], 'silos.published' => 'yes'))) : array(); $fields['silo'] = array('label' => 'Silo', 'type' => 'array', 'options' => $silo_options, 'value' => $silo_values, 'mode' => 'multi'); $fields['slug']['comment'] = 'If no slug is provided, one will be provided for you'; $fields['release_date']['comment'] = 'A release date will automatically be created for you of the current date if left blank'; return $fields; } // add categories and slios function on_after_save($values) { $data = (!empty($this->normalized_save_data['categories'])) ? $this->normalized_save_data['categories'] : array(); $this->save_related('categories_to_news_model', array('news_id' => $values['id']), array('category_id' => $data)); $data = (!empty($this->normalized_save_data['silo'])) ? $this->normalized_save_data['silo'] : array(); $this->save_related('silos_to_news_model', array('news_id' => $values['id']), array('silos_id' => $data)); } // cleanup categories from categories to news table // cleanup silos from silos to news table function on_after_delete($where) { $this->delete_related('categories_to_news_model', 'news_id', $where); $this->delete_related('silos_to_news_model', 'news_id', $where); } function _common_query() { parent::_common_query(); // to do active and published $this->db->order_by('release_date desc'); $this->db->select('news.*, silos.name AS silo'); $this->db->join('silos', 'news.silo_id = silos.id', 'left'); } } class News_item_model extends Base_module_record { public $silo = ''; function get_url() { //$silo = $this->link; $year = date('Y', strtotime($this->release_date)); $month = date('m', strtotime($this->release_date)); $day = date('d', strtotime($this->release_date)); $url = site_url('news/'.$silo .'/'.$year.'/'.$month.'/'.$day.'/'.$this->slug); return $url; } function get_excerpt_formatted($char_limit = NULL, $readmore = '') { $this->_CI->load->helper('typography'); $this->_CI->load->helper('text'); $excerpt = $this->content; if (!empty($char_limit)) { // must strip tags to get accurate character count $excerpt = strip_tags($excerpt); $excerpt = character_limiter($excerpt, $char_limit); } $excerpt = auto_typography($excerpt); $excerpt = $this->_parse($excerpt); if (!empty($readmore)) { $excerpt .= ' '.anchor($this->get_url(), $readmore, 'class="readmore"'); } return $excerpt; } function get_content_formatted($strip_images = FALSE) { $this->_CI->load->module_helper(FUEL_FOLDER, 'fuel'); $content = $this->content; if ($strip_images) { $CI->load->helper('security'); $content = strip_image_tags($this->content); } $content = $this->_format($content); $content = $this->_parse($content); return $content; } private function _format($content) { $this->_CI->load->helper('typography'); $this->_CI->load->helper('markdown'); if (!empty($this->formatting) && !function_exists($this->formatting)) { $this->_CI->load->helper(strtolower($this->formatting)); } if (function_exists($this->formatting)) { $content = call_user_func($this->formatting, $content); } return $content; } } ?>
  • edited 2:33PM
    If you just want to associate the article to a single silo try adding this to your News_model as a property:
    public $foriegn_keys = array('silo_id' => 'silos_model');
    I don't think you need the "silos_to_news_model" because you are only associating one silo to the news record.
  • edited 2:33PM
    Thank you. I can get the silos.id value now but how would you extract silos.name to insert into the url as a string?
  • edited 2:33PM
    You should be able to make it a property of your news_item_model as previously displayed above by declaring the property on the record model and adding it into the _common_query() join.
  • edited 2:33PM
    The silo property (public $silo = '';) throws an undefined variable error when I try to do this.
  • edited 2:33PM
    Sorry. I wasn't calling $silo properly. Forgot to use $this. Here's the correct code for others reading this...

    $url = site_url('news/'.$this->silo .'/'.$year.'/'.$month.'/'.$day.'/'.$this->slug);

    Is there a way to restrict this list of silo names to ones the user has permissions for?
    With multi-select lists, I am filtering permissions on the options_list. Is there a similar method for dropdown selects?
  • edited 2:33PM
    You could do the same as you did for the mult-select. Although the dropdown is automatically created with the $foreign_keys property, it is still available in the form_fields method in the $fields variable to manipulate the options value (you an print_r($fields) in that form_fields method to see it).

    Alternatively, you could overwrite your model's options_list() method on your model which is inherited from MY_Model.
  • edited 2:33PM
    Thanks for all the help, especially on a weekend. Much appreciated.
  • edited 2:33PM
    No problem. Hope it helps
  • edited 2:33PM
    Getting there... having some issues with the permissions for the silos dropdown though.

    Setting permissions on the silos model options_list is throwing errors (missing arg 1 & 2 and undefined vars for args 1 & 2). This worked fine for filtering a multi-select.

    I can see the values for the silos select using print_r but if I try to manipulate them in form_fields it creates another select. I just want to filter the foreign keys select.

    Where am I going wrong?
  • edited 2:33PM
    Can you post the code you are using in your form_fields method?

    Also, if you are overwriting the models options_list method, the signature should look something like the following:
    public function options_list($key = NULL, $val = NULL, $where = array(), $order = TRUE){ //.... your additional filtering code including active record statements can go here like so $this->db->join('silos', 'silos.id = news.silo_id', 'left'); $this->db->where('silos.name', 'my_name'); // ... etc parent::options_list($key, $val, $where, $order); }
  • edited 2:33PM
    I'm likely way off here...
    $silo_options = $CI->silos_model->options_list('silos.id', 'silos.name', array('silos.published' => 'yes'), 'silos.name'); $fields['silo'] = array('options' => $silo_options);

    This is the code I was using in the silos model to filter the multi-list by user permissions...
    function options_list($id, $name) { $permissions = $this->fuel_auth->get_permissions(); $silo_permissions = array(); // typecast to array to avoid errors caused by no array data foreach((array) $permissions as $key => $val) { if (preg_match('#^silos/#', $key)) { $silo = end(explode('/', $key)); $silo_permissions[] = $silo; } else { // if no silos then present an empty list $silo = ''; $silo_permissions[] = $silo; } } if (!$this->fuel_auth->is_super_admin()) { $this->db->where_in('silos.name', $silo_permissions); } return parent::options_list($id, $name); }

    I'd like the foreign_keys select to be filtered the same way.
  • edited 2:33PM
    Try changing it to:
    $fields['silo_id'] = array('label' => 'Silo', 'type' => 'select', options' => $silo_options);
  • edited 2:33PM
    That worked, along with the option_list in the silos model set up like this...

    function options_list() { $permissions = $this->fuel_auth->get_permissions(); $silo_permissions = array(); // typecast to array to avoid errors caused by no array data foreach((array) $permissions as $key => $val) { if (preg_match('#^silos/#', $key)) { $silo = end(explode('/', $key)); $silo_permissions[] = $silo; } else { // if no silos then present an empty list $silo = ''; $silo_permissions[] = $silo; } } if (!$this->fuel_auth->is_super_admin()) { $this->db->where_in('silos.name', $silo_permissions); } return parent::options_list(); }

    In my news model I've added ad initial 'Select...' option. Is there a better way than this?

    // silo options $silo_options = array('Select...'); $silo_options += $CI->silos_model->options_list('silos.id', 'silos.name', array('silos.published' => 'yes'), 'silos.name'); $fields['silo_id'] = array('label' => 'Silo', 'type' => 'select', 'options' => $silo_options, 'required' => TRUE);
  • edited 2:33PM
    I think I will do it this way, merge it

    $silo_options = array_merge(array(''=>'Select...'),$CI->silos_model->options_list('silos.id', 'silos.name', array('silos.published' => 'yes'), 'silos.name'));
    $fields['silo_id'] = array('label' => 'Silo', 'type' => 'select', 'options' => $silo_options, 'required' => TRUE);
  • edited 2:33PM
    As an FYI, you can add the 'first_option' value to your options in the $field declaration array like so:
    $fields['silo_id'] = array('label' => 'Silo', 'type' => 'select', 'options' => $silo_options, 'required' => TRUE, 'first_option' => 'Select...');
  • edited 2:33PM
    oh didn't know you use a non exist value as first option , thanks for the tips !
  • edited 2:33PM
    That's great. Thanks for the help guys.
    I thought there was something like first_option but I couldn't find it.
Sign In or Register to comment.