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.
Related
Okay, so here's the deal. I'm working with a custom CMS, and I'd like for the code to be as optimized as possible. I've been reading/watching tuts/etc. like crazy about the repository pattern in general as well as specifically using it with Laravel's Eloquent. There are probably some really dumb questions/thoughts in here, but bear with me. :-) Sometimes there's no easy way to ask about terminology/best practices without looking silly.
As with many things, there are million ways I could "make it work"; my dilemma is essentially a matter of "best practice."
General Scenario/Question
Let's assume I am trying to get a Page for my CMS from the database. From what I can understand the typical way to set up the repository pattern with Eloquent is to have the following files:
Page.php -- the Eloquent Model
PageRepositoryInterface.php -- the "contract" for what should be in Page repo's
EloquentPageRepository.php -- the Page repository that can grab data via Eloquent
Easy enough. So I might use it this way. Assuming I have a getPageById method in EloquentPageRepository.php, I could just do something like this from my controller:
$page = $this->repo->getPageById();
Now my question arises: what type of data should getPageById() return? Some people recommend setting it up to return an Eloquent collection. Others say just a plain array or generic object.
Ideally I feel like my scenario would best lend itself to having EloquentPageRepository grab the data from Eloquent and actually return an instance of a custom Page class that I have. For example, something along the lines of this:
<?php namespace Acme\Repositories\EloquentPageRepository;
use Acme\...\PageObject as PageObject; // Better name than PageObject?
//...
class EloquentPageRepository implements PageRepositoryInterface {
// Omitting constructor, etc.
public function getPageById($id)
{
// Grab the row via Eloquent (obviously not stored in Page:: at
// this point. I'm just using it here for clarity and time's sake.
$page = Page::find($id);
// Now we have an Eloquent collection stored in $page, but I'd
// like to return the data inside an instance of my custom class.
$pageObj = new PageObject($page->title, $page->body);
return $pageObj;
}
}
To me, this seems good because it gives a consistent delivery format from repo to repo. It also allows me to perform some constructor logic on my pageObject. Finally, it allows me to have some custom methods on the PageObject (that are repository-agnostic).
It's similar to a collection, but I don't think it's exactly that. It's basically just an instance of a class that I'm immediately populating with my database info.
My questions, listed:
Is it considered bad practice to use a repo to stuff eloquent data into a specific object and return it?
I don't want to call my class "PageObject," because that's just lame. I'd way rather call it something like "PageCollection," except for the fact that it's not actually a collection. Is there actually a name for the way that I'm using this class? It's not a collection, it's a ...? I have no idea about this, I'm just searching for any input you have.
It whole depends on what you expect from the repository pattern. Are you using the repository pattern because in the future you're going to swith of data layer and needs a new repository. If you're using Eloquent as long as your cms live then you can return an eloquent object. If you want it very flexible then make a new page object(PageComposer as mentioned in the comments). This is one of the strengts of the repository pattern so I suggest you make a PageComposer class which you instantiate and return by the repository.
Normally you can call it Page because its a page and it ships some information of a page. But that name you've already give to the Eloquent model. You can consider changing the eloquent models name and call your return object Page.
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.
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
I’m fairly new to CodeIgniter and have a question. I’m a bit confused about Classes, Libraries and Objects.
Does CodeIgniter replace the normal PHP way of usings objects i.e. $var = new car(); with libraries i.e. $this->load->library('some_library'); $this->some_library->some_function(); ?
If both are valid, is there a difference? If so, what are the differences and when do I use one over the other? Which is more common/proper?
I am asking because I created a class, but I'm not certain what is the correct manner in which to instantiate it.
Thanks in advance
I am not familiar with CodeIgnitier. But familiar with other PHP frameworks. Most of frameworks use this way for performance improvements, registering things, executing certain events, and making things simpler for developer...
For example if you want to create class "car" with is somewhere in library directory you would have to include the file first before you can create object of that class (miltiple lines of code, more room for error). The framework will create the class and includes related files in 1 line of code (easier and safer).
Framework way also works as a factory. Instead of recreating an object, it will create object only once and every time you call the method again it will return the reference to existing object.
More things are happening behind the scenes when you use framework. Things are getting registered, etc...
CI doesn't replace class behavior per se, it simply adds functionality that allows access to custom libraries/models/views as singleton objects via the core object for simplicity.
Nothing is stopping you from creating (as I have in one of my projects) additional files with classes for non-singleton entities and require them in a model for further use. On hindsight, I should probably have used helpers for this.
What the loader ($this->load) class does, among other things, is it creates a single object of the specified class (model, library or view - not helpers though, see below) and attaches it as a property of the core class that is normally accessible via $this.
Helpers are a bit different. They are not attached, but instead simply 'read' into the global namespace from the point where they are loaded.
To answer your question, it would be more proper to use the loader class in instances where you don't need more than one instance of a class created. If you need 'entity' classes, your best CI-compliant bet would be to create them as helpers.
Given only this context, this looks like Inversion of Control (maybe I'm wrong, I haven't looked too closely at CodeIgniter).
You don't want to rely on the type car as in new car(). What if later you want to make $var a racecar? $var can still do the same things, but it is forced to be a car because you constructed it directly. Or what if you are testing this class, but car is some complex object which calls some external service. You want to test your logic, but don't care if the car service isn't working. So you should be able to change $var to actually load a mockcar. You can't do that if you do $var = new car().
What is Inversion of Control?
I need help in designing my PHP classes where I need to extend from multiple classes.
I have a general class, Pagination.php that does all sort of pagination and sorting. All other classes will use this for pagination.
To make my life easier, I made a class generator that generates a class from MySQL table. All the properties, getters, setters and common methods are created automatically, which really saves time and money.
As an example, class Staff_Base in Staff_Base.php is generated automatically from SQL table t_staff.
Since class Staff_Base is automatically generated from SQL table, any 'custom' methods / properties are located in another class that extends Staff_Base.php. (So that whenever a new field is added, I can simply regenerate Staff_Base class and overwrite in Staff_Base.php).
So I have class Staff.php that extends Staff_Base.php.
The problem is, Staff.php also needs to extend another class, Pagination.php.
(The current workaround is to put methods in Pagination.php into every class. This is really troublesome whenever I make changes to the pagination/sorting methods.)
How do I do this?
What is the best design pattern to achieve this?
I know common suggestions to restructure my classes, but I really think hard of other workaround/solution. Also, I may also need to extend other classes than Pagination.php.
Thanks!
Can you have your generated Staff_Base class inherit from Pagination? Or does Staff_Base already inherit from another base class (that you do not have control over)...
Sounds like either Doctrine or Propel, I do not recall which uses the *_Base class system.
My suggestion would be to rewrite pagination to be able to be used by your entity classes instead of requiring your entity classes to extend it.
So if I am reading what you wrote correctly, since you can't inherit from 2 classes you are duplicating paginate into every class you have.
Class stacking is a solution. One of the first things I googled.
I would recommend changing your Staff_Base.php generator to make that class extend Pagination by default. That way Staff extends Staff_Base, and Staff_Base extends Pagination. I think that's probably the cleanest (and most object-oriented) way of getting the results you want.
you cant, multiple inheritance is not supported in php, but if you do a google search on this topic you can find some workarounds...
It sounds like you're mixing things up here. A class (such as a Staff class) is used to represent a single entity. Eg:
$john = new Staff('John');
How exactly does the paging fit into this? Being page-able (paginatable?) sounds like a property of whatever it is that allows access to these Staff entities, not of the entity itself. That way, the way is clear for each type of Staff class you create to inherit from the base class.
So, what I believe would be the solution you need:
A Staff class (Staff_Base, and its graph of children)
A Staff Data Access Object (DAO\Staff would be a nice name, if you're using namespaces)
An Interface, to signal to the world that a DAO can be paged
Import to note is that there is no direct inheritance between the DAO class and the Staff class. You can still generate the Staff_Base class based on its properties in the database, and extend from there... as long as you don't include the actual data access in that class.
The code using this would then look something like this:
<?php
$staffDao = new DAO\Staff;
$staffMembers = $staffDao->getPagedResult($start, $amount);
?>
Edited to emphasize that the inheritance structure should be separate from the actual retrieval
Well, you might already know that PHP doesn't support multiple inheritance. One way around might be using Interfaces instead of superclasses, although, if the logic is identical for each implementing of the interface, this might become tedious. How about writing a code generator, that simply injects the methods to each class? You seem to already do that on the "common methods".
Oh, and using getters and setters (as they are used in e.g. Java) in PHP is considered not a good idea. Objects are slow as they are, so using public fields is considered the norm.
Edit: Then there's the __call()-hack, which could recognize the methods that actually reside in your other classes, and call them manually.