Global model initialization in Kohana - php

I'm new to Kohana and bumped into the following problem:
I have 3 models, model1, model2, model3. Every time I want to use a method from one of the models (in a different controller method / model) I have to
$model1 = New Model_Model1();
In a controller, I can do a public $model1 and create the model in the constructor, that's OK. In a model, however, I managed to get an infinite loop of model initialization.
In CodeIgniter, it's easy: I can autoload models. How do I make my models globally accessible in Kohana so that I could $this->model1->dosth(); from anywhere, without worrying about creating multiple instances of the same model?

First of all, the only reason you can do $this->model->method() in CodeIgniter is because it has a super object;
In Kohana you can create an instance method in your model and simply call Model::instance() ... if you need a global instance. If you need to access them in controllers only then you can override the default controller, load your models in the constructor and use them in your child controllers.
It all depends on your situation really. Loading a new model instance isn't always a bad thing.

Related

Eloquent (without Laravel) caching implementation

I am using Eloquent without Laravel and I'm wondering if there's a method which can be used (and does not rely on Laravel components) to integrate a caching method which then automatically caches all model queries (caching backend can be variable, say APCu or memcache).
I'm thinking that it should be possible to write a model base class which handles this but I'm not quite sure how I would go about implementing this. Does anybody have any ideas in this direction?
If you want to auto cache your query, you have to override the find(), findOrFail() , where() ... methods
Because of how Eloquent is built you can't simply add a method find() in your custom model class
https://laracasts.com/discuss/channels/eloquent/override-find-method/replies/72028
class MyCacheModel extends \Illuminate\Database\Eloquent\Model
{
// override methods as explained in previous link
// cache the result in redis for how long you want
}
Then in your model instead of extending Eloquent\Model, extends now from your MyCacheModel. With a bit of customization you can set how long queries will be cached and if a model shouldn't be cached then just use the Eloquent\Model.

PHP MVC (Laravel), should I create another class instead of using the model if I'm not talking to the DB

I'm using Laravel and Eloquent (ORM) specifically, but I believe this to be a general MVC question...
I have a view and a couple of controller methods that receive an Eloquent Object, and can access the attributes by $foo->bar (again this is an Model Object).
I want to re-use these same views\controller methods with some objects that I create manually. These objects will not be persisted to the DB, but they have the same design and structure as the Eloquent objects (they are essentially a heavily filtered\modified subset of data retrieved that I'm unable to re-create from an Eloquent statement).
Let's assume I have a Foo.php model that Eloquent uses. For the manually created Foo object, should I use the Foo.php model or create another Foo.php class?
And specific to Laravel, where should this live and how to do I keep from being confused about which Foo I'm using?
In other words. To re-use code (in view\controller) that receives and Eloquent (ORM) Object, should I create a new class for objects not retrieved from the DB (created manually), or should I use the existing model?
It really depends on the size of your project and how much you want to decouple the Eloquent from your views.
If this is a huge project that maybe in the future you would remove eloquent, so create a class that will be passed to the views as simple data objects.
If you think that eloquent is here to stay, so simply create manually the eloquent object and pass it to the views.
here are some of the options:
option 1: manually create eloquent object (without persisting)
$eloquentForView = new Whatever();
$eloquentForView->username = "just for view";
option 2: create an object specifically for your views
class WhateverDataView {
public $username;
}
option 3: simply pass an array
from eloquent object:
$eloquentObj->toArray();
simple code
$dataForView = ['username'=>'whatever username'];

Making a model persistent in the controller using doctrine2 or making the model persistent it self

Hello I'm new in doctrine and I don't know what to do in the following situation:
I have a controller which create a new model object "Ad". Who has the responsability of making that object persistent in the DB?. The controller because it created it? or the model it self?
Acording to MVC, the model should be the only one who deals with the DB, so I guess I have to create a method call "persist" or create an interface called model which will have this method and inject the entity manager in the constructor of every model instead of making the object persistent using the entity manager in the controller.
PD: I don't want to use any framework like Zend, CI etc.
Thank you!
The "model" is a layer, not a file or class that deals with persistence. Persistence belongs in there, but together with your Domain Objects, Services, Factories and whatever else your application needs.
The controllers (and views) are part of the presentation layer and as such should only be responsible for tasks regarding that.
If you are implementing domain objects then it is usually a good choice to use the data mapper pattern to handle persistence. If you set it up that way, then the objects themselves don't need to know anything at all about if and how they are persisted. This makes your code confirm to the SOLID principles and makes it testable.
Now you could work with your data mappers and domain objects in your controller, but a better solution for most applications is a service layer. It will allow you to reuse your service methods in multiple controllers and keep your codebase DRY. This is especially helpful if you have multiple endpoints to access your application (think normal website, admin area, API's, etc...).
A service layer class could look like this for example:
namespace MyApp\Models;
class OrderService
{
public function getOrders($limit=null, $offset=null)
{
$orders = new OrderCollection;
$orders->setLimit($limit);
$orders->setOffset($offset);
$orderCollectionMapper = new OrderCollectionMapper;
$orderCollectionMapper->populate($orders);
return $orders;
}
}
The controller. When your model is validated/ready to save.

Scope of creating AR model instance

Can I create an instance of every model everywhere in my application or there is limits to do so.
For example can I use below codes everywhere in my app ?
$issue = Issue::model()->findByPk($id);
OR
$issue = new Issue;
Yes, those codes will work everywhere in your app because Yii uses a "lazy loading" approach which loads the Issue model when it's needed. Just be careful about keeping your code organized. If you are accessing records outside of the associated class's controller or model (e.g. using the first line above in a controller called ArticleController), you might need to use relations instead.

CakePHP: Can I create a function in a controller that doesn't have an associated view?

I have an index action in my users_controller that get a list of users. For each user i want to calculate the number of projects they have associated (one user => many projects). I was thinking of using a method like getProjectTotal and calling it for each user. Would I put this method in the users_controller and call it like
$this->getProjectTotal($id)
in the view?
Thanks,
Jonesy
Sure. It sounds like this is just a helper method based on the call. I do that all the time. I'll typically set the method visibility to private or at least protected to keep it from being called accidentally in a rendering scenario.
I'm still relatively new to CakePHP, but I've been using the built-in counterCache in Cake 1.2 to track the number of hasMany records for a parent Model in one of my apps. Create a field in your parent Model to store the hasMany count, and enable counterCache in the $belongsTo property for the child Model, and you're good to go. It automatically updates the counterCache count field in the parent model whenever the # of "hasMany" records increases/decreases. I like this method of tracking as it keeps the controller a little cleaner if all you need is the count without any other conditions.
Docs: http://book.cakephp.org/view/816/counterCache-Cache-your-count
Also, I'm still new to MVC, but I think if you're going to gather the count via a private/protected controller method, you'd want to call it in the controller and then send the data to the view, not perform the actual method from the view, in this scenario.
Also - yes you can make a controller method for work that isn't going to render a view - BUT - in your case you should use counterCache / a Model function since you are either fetching / counting / manipulating actual data related to the Project model and it's relationship with the User model and current logged in User specifically.
When building out my controllers I tend to stick to methods that render a view or return data for an element called from requestAction. If the method is computational or setting up variables but doesn't require a template or isn't called from an element I move it to a component / helper / model / behavior. Combined with a docblock with #requestAction in the flags for introspection and I can get a list of regular actions, and data returning actions without worrying that a controller is full of other methods.

Categories