Scope of creating AR model instance - php

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.

Related

PHP MVC - Calling view functions from model, or controller?

After reading a fair few posts on Stack, and also some material recommended to me on line, the MVC pattern is quite open to interpretation, so please don't answer with another explanation. Thanks!
I'm reaching the end of designing my own PHP MVC now, and have two possible ways to move forward with the views.
But first, my controllers are currently quite dumb, not containing any classes and simply call public methods from the suitable models, and render the appropriate view.
Views are included as necessary, so naturally the objects are available to them via the constructors, along with all the methods (inc delete/update etc).
My first option is to get data using something like this in the view
foreach($object->fetchData() as $data)
and then looping through the results. However some people do not agree with this, and have suggested that such methods should be excluded from the view. Instead it has been recommended that I assign this to a variable in the constructor, and then use this variable in the view
//constructor
$fetched_data = $object->fetchData()
// view
foreach($featched_data as $data)
I don't like this very much, as it seams messy and unnecessary.
With all my critical methods being made available to the view, could this be considered a problem?
So here's the question. Do I keep it how it is, and create new methods in the MODEL for rendering data (as above) OR can I create a class in the constructor, extend the model into it, protect the critical functions in the model, and then create my read only public methods in the CONSTRCUTOR?
Thanks!
I would create a class in the constructor. Not only would extending the model be a much safer approach, but it'd also minimize the calling of functions in the views. Am assuming you'll have several views, it's much easier to get access the constructor data than calling method functions each time in each view.
You can add classes to your controllers that will call the method functions and pass the data directly into the views, instead of clustering your constructor or bootstrap.

In Symfony2, what folder do I save a multi entity class in?

I am new to Symfony2 and I am not sure where I should save a class that updated multiple tables(entities).
From reading documentation and tutorials it says I should not put any other tables reference within the entity class; I could put it within the controller class, but again many people have said this class should be as simple as possible and not include business logic; Not in repositories, because these are used for query data and not for update or inserting.
Is there a standard folder structure where another type of class for working with multiple entities(tables) should be saved? Should the business logic really be stored in the controller classes?
Symfony2 is very flexible in this regard.
You're right, entities are for one "table" only.
I would suggest you look into Services, as they are a good way to move your code from a controller to a separate class. You basically call your service and use the functions it provides. This will slim your controller down.

How do I track models using other models?

From time to time one of my models will need to call another. What's the best way to track this?
I was using an array in the base class of each model, so that if Model A called Model B more than once, the second and successive calls would return the existing instance, rather than loading a new one.
While this works fine for simple cases, I can see it has limitations. For example, take the case where Model A loads Model B and Model C; then Model C needs access to Model B (or even A) - it will load the class again!
I suspect that I need a coordinating object, external to the model classes, which acts as a repository. What patterns should I be looking at?
BTW, I am using PHP.
EDIT: Another consideration is that my views may call model methods directly too. In these cases it would make sense to serve up an already instantiated model, rather than a new one...
Thanks!
Take a look at the observer pattern thats used in such case.
Its easy .. each model have a list with listeners and when something happens it says to all Listeners hey something happend

Global model initialization in Kohana

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.

Should I use App::import('Model', ...) or ClassRegistry(...)?

Because of other answers (like this), I'm just wanting to clarify what should be used in CakePHP 1.3.
Specifically, I have a situation that calls for a Model to depend on another, so from a method in that Model I'd like to load another, do some stuff with the info, etc.
The documentation for the App Class says:
In previous versions there were different functions for loading a needed class based on the type of class you wanted to load. These functions have been deprecated, all class and library loading should be done through App::import() now.
I'm assuming this covers the use of ClassRegistry, etc, but I just want to it to be clear, and certain:
Should I use App::import('Model', ...) to utilize one Model from another, or something else? If something else, what?
It appears that, even two years since 2008, the best method is to use ClassRegistry::init(), despite the cited documentation.
This is made evident in the actual API/documentation for the specific classes/methods.
App::import()
Finds classes based on $name or specific file(s) to search. Calling App::import() will not construct any classes contained in the files. It will only find and require() the file.
ClassRegistry::init()
Loads a class, registers the object in the registry and returns instance of the object.
Examples Simple Use: Get a Post model instance ClassRegistry::init('Post');
As you can see, even the API Documentation points out examples of using ClassRegistry to load models, instantiating them for you, as opposed to App::import (which does much less), and despite the changed wording in the CakePHP "Book" documentation.
If you can relate the models then the best way is to Dynamically bind the relations using
$this->bindModel("hasOne" => array("Model2")).
If you can't relate the model and you want to use the second model in just one occurrence then you can use
ClassRegistry::init('Model2')->find('allThatIWant');
if you want to use it in several occurrence then you must try
$this->model2 = & ClassRegistry::init('Model2')
$this->model2->find('allThatIWant');
As of 2.6.x of course it is ClassRegistry::init() still.
There is a major difference. App::import will just include/require it. On the other hand ClassRegistry::init() will instantiate it and fetch you a fully loaded object of the model.
So to say, for example you loaded a model in beforeFilter of your AppController. You add some custom properties to it using $this->Model->__something. Now you do call ClassRegistry::init('Model') somewhere where you do not have $controller object available, for example, in a behavior. The object returned by ClassRegistry::init('Model') will have your custom property $this->Model->__something in tact.
Btw, $controller->loadModel() seems the ideal way to load model where you have a $controller object available, for example in your components.
$this->loadModel('model name') will do unless u need it for the entire controller, Then just define the relationship in the model such as hasone, belongsto... and call $this->model->model2.

Categories