开发者

Calendar throughout CakePHP site, but CakeBook says to not use a Model in a Component

I have a small calendar widget-type thing on many pages throughout my site. The goal is for it to retrieve events from X category that fall between Y and Z dates.

My assumption (I'm new to CakePHP) was that I should create a component, and have it do the query. Something like this:

class CalendarComponent extends Object {

    var $uses = array('Event');

    function getEvents($category = null, $date = null, $limit = null) {
        $events = $this->Event->find('list', //conditions to get correct events
        return $events;
    }

}

BUT, according to this CakeBook pag开发者_JAVA百科e:

To access/use a model in a component is not generally recommended

So - where would I store this logic / model call if not in a component? I've admittedly not used a component yet (or not created one anyway) due to lack of really understanding how I should use them - any snippet of advice on this is also VERY welcome.


Great question in my opinion and I imagine one that comes up quite often. I was actually dealing with a similar problem where I wanted some site-wide data gathering or functionality shoved into a component.

The first thing to keep in mind:

The book is a guideline.

These 'rules' aren't rules. If there's a good reason for breaking the rule and you understand why the rule is being broken then break the damn thing! Cake itself breaks this rule quite often.

Core components that require/use models:

  • Acl
  • Auth
  • Sessions (fairly positive you can save session data to a model)

So, clearly there are use cases where you need to use a model inside a component. How do you do it though?

Well, there's a couple different ways. What I wound up going with? Something like this:

<?php

    ModelLoadingComponent extends Object {

        public function startup($controller) {
            $controller->loadModel('Model');

            $this->Model = $controller->Model;
        }

    }

?>

That's it! Your component is now setup to use $this->Model...just like you would in a controller.

Edit:

Sorry, to clarify: no, you don't have to setup a new component to load models. I was showing an example for how you could load a component in any model. The startup function I used is a component-specific callback, there's a whole slew of them http://book.cakephp.org/view/998/MVC-Class-Access-Within-Components. These callback methods make components a lot easier to work with. I highly recommend looking at this part of the components tutorial if nothing else.

If you were working inside an AppController object you could call $this->loadModel() but we aren't working an AppController! We're working with a component, really an Object. There is no Object::loadModel() so we have to come up with a different way to get that model. This is where $controller comes into play in our startup callback.

When the startup method is invoked by Cake it will pass the $controller object it's working with on this dispatch as the first parameter. With this we're able to access controller methods...like loadModel().

Why do we do it this way?

Well, we could use ClassRegistry::init('Model') in each of our component methods that need to use the model. If you have 10 methods in your component and only 1 of them uses the model this might work. However, what if you have 10 methods in your component and all 10 of them use the model? Well, you'd be calling ClassRegistry::init('Model') 10 times! That's a lot of overhead when what you really want is just 1 model object. With this method the component is creating one model object. The one we create in startup.

I hope this clarifies your questions and provides some insight into why I use this method for models in components.

Edit: Added a code clarification after I did some experimenting.


I think writing a component is overkill in this case and it would be cleaner to put the getEvents method into the Event model.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜