Retrieve record in class that extends Base_module_record
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
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 = ''; ....
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; } } ?>
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.
$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?
Alternatively, you could overwrite your model's options_list() method on your model which is inherited from MY_Model.
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?
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); }
$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.
$fields['silo_id'] = array('label' => 'Silo', 'type' => 'select', options' => $silo_options);
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);
$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);
$fields['silo_id'] = array('label' => 'Silo', 'type' => 'select', 'options' => $silo_options, 'required' => TRUE, 'first_option' => 'Select...');
I thought there was something like first_option but I couldn't find it.