I am having trouble understanding how to use observers with ORM models correctly. I think my question is similar to this one: http://fuelphp.com/forums/discussion/11500/custom-model-properties-extension
I have an ORM Model, and use the following code to grab a list of pages, and later i pass the result to my view.
$data['pages'] = Model_pages::find('all');
In my view i cycle through the results in this way:
foreach($pages as $page) {
....
echo $page->title;
....
echo \Html::anchor(
\Router::get('content_pages_edit',array('page_id'=>$page->page_id)),
'Edit Page' )
....
}
The line of code for echoing the 'edit' link for each page i would like to move into the model.
What i'm trying to do is use observers to change the result of Model_pages::find() and add custom properties to each object in the results, after this it is then passed to $data['pages'] as usual.
In my model i would like a method which would receive the results of ::find(), and allow me to manipulate the values, before returning the modified results, something like this:
....
protected static $_observers = array('Orm\\Observer_Self');
....
protected static function _event_im_not_sure_of( $results ) {
....
foreach($results as $index=>$result)
$results[ $index ]->link_edit_page = \Router::get(
'content_pages_edit',
array('page_id'=>$result->page_id)
);
....
return $results;
}
And hopefully, in my view i can echo the edit link like this:
foreach($pages as $page) {
....
echo $page->title;
....
echo \Html::anchor( $page->link_edit_page, 'Edit Page' );
....
}
If possible it would be good to use a 'self' observer, so i can keep the code inside the model. Is there a way to call a method on the model each time ::find() is called?
I'm not sure of which 'event' im supposed to use, i have tried a few with no luck.
protected function _event_after_load($model) {}An observer is fired per model object, so if your find returns 10 records, 10 model objects are created, and the observer is fired on each of them. It gets passed the model object itself.
$model->link_edit_page = \Router::get(There is no need to return anything, you modify the passed model object directly.
'content_pages_edit',
array('page_id'=>$model->page_id)
);
Thanks for the feedback Harro, i did try messing with the _event_after_load method previously with no luck, i have implemented your suggestions and get the following error:
"BadMethodCallException [ Error ]: Call to undefined method Content_pages\Model_Pages::_event_after_load()"
<?php
namespace Content_pages;
class Model_Pages extends \Orm\Model {
protected static $_observers = array('Orm\\Observer_Self');
protected static $_table_name = 'pages';
protected static $_primary_key = array('page_id');
protected static $_properties = array(
'page_id',
'title' => array(
'data_type' => 'varchar',
'label' => 'Title',
'validation' => array('required', 'min_length' => array(3), 'max_length' => array(255)),
'form' => array('type' => 'text'),
'default' => ''
),
'body' => array(
'data_type' => 'longtext',
'label' => 'Body',
'validation' => array('required', 'min_length' => array(3), 'max_length' => array(4000)),
'form' => array('type' => 'textarea'),
'default' => ''
)
);
protected function _event_after_load($model) {
$model->link_edit_page = \Router::get(
'content_pages_edit',
array('page_id'=>$model->page_id)
);
}
}
I have also tried declaring the event function as a protected static function too, and get the same error.
Thanks Harro! That seems to have worked ok :) You've been a great help again.
For any google-ers, this is working the code for the model:
<?php
namespace Content_pages;
class Model_Pages extends \Orm\Model {
protected static $_observers = array('Orm\\Observer_Self');
protected static $_table_name = 'pages';
protected static $_primary_key = array('page_id');
protected static $_properties = array(
'page_id', // both validation & typing observers will ignore the PK
'title' => array(
'data_type' => 'varchar',
'label' => 'Title',
'validation' => array('required', 'min_length' => array(3), 'max_length' => array(255)),
'form' => array('type' => 'text'),
'default' => ''
),
'body' => array(
'data_type' => 'longtext',
'label' => 'Body',
'validation' => array('required', 'min_length' => array(3), 'max_length' => array(4000)),
'form' => array('type' => 'textarea'),
'default' => ''
)
);
public function _event_after_load() {
$this->link_edit = \Router::get(
'content_pages_edit',
array('page_id'=>$this->page_id)
);
}
}
It looks like you're new here. If you want to get involved, click one of these buttons!