I have built a small PHP MVC framework and just want to clarify the best way to get data from one model into another. For example:
I have a Users_model that contains a method called get_users().
I also have Communications_model that needs to get specific or all user data and as such needs to access the get_users() method from the Users_model.
Is it best practice to:
a) Instantiate the Users_model in a controller and pass the data from the get_users() method into the Communications_model?
b) Instantiate the Users_model inside the Communications_model and run get_users() from there, so it can be accessed directly?
c) Another way?
Many thanks for any help.
It depends of your motive behind this.
If you want effect on result, then using well know library, like Doctrine etc. should be your choice.
If you want to learn design patterns, then you should get read about ActiveRecord or DataMapper + Repository patterns. Then implements both and check out.
If you want your code, this way - ORM should represent relations of data, then you should ask what it more important? If you menage communication (bus, train), then user can be there assigned and getting users from communication is OK. If user have communication (like car), then relation is reversed.
All depends, what is you motive behind this. Using library, like Doctrine, could you help you running you application. If you want learn design patterns, then check out both options to get some experience.
What you call "users model" is a repository. And what you call "communication model" looks like a service.
Your communication service should have the user repository passed in constructor as a dependency.
I honestly think, that a huge part of your confusion is that you try to call all of those things "models". Those classes are not part of the same layer. You migth find this answer to be useful.
All are possible ways but what I usually do is, whenever there is any function that I think would be reused a number of times by a number of objects, I declare it as static.
It would save the effort of playing with object declaration and would be easily accessible by ClassName::function();
Again, it's a design choice, usually objects are declared right there in the controller and used as per the need but just to save declaration of objects again and again I follow the approach of declaring function static.
The simple principle here is using the __construct() (constructor) to build the object with the relevant properties from the Database. The User Model will have a static function (therefore accessible through any scope) to create an array of instanced objects by simply passing the model data through a new self() which returns the instance.
The concept is you end up with an array of User_Model instances each being a build of the Database columns to properties. All that's left is to create the Database Model and the functions to retrieve the columns and data.
class Communications_Model {
private $_all_users;
public function getUsers() {
$this->_all_users = Users_Model::loadAllUsers();
}
}
class Users_Model {
private $_example_property;
public function __construct($user_id) {
$data = SomeDatabaseModel::getConnection()->loadUserFromDatabase((int)$user_id);
$this->_example_property = $data['example_column'];
}
public static function loadAllUsers() {
$users = array();
foreach(SomeDataModel::getConnection()->loadAllUsers() as $data) {
$users[] = new self($data['user_id']);
}
return $users;
}
}
Of course, now, you have a $_all_users; property that has an array of instanced User Models containing the data.
I'm confused to why can't I access the relationship I setup if I use this code:
$products = new Products();
If I use this, I can access my laravel relationship columns.
$products = Products::all();
What's the difference?
In your first example you are instantiating a regular php object, in the second example you are allowing laravel to instantiate the object. In such a case you are actually calling a named constructor that will utilize a static boot() method that is taking care of a lot of the heavy lifting under the hood.
I'm trying to decide on something, where to put database logic, in the controller or model when using the eloquent orm.
In a controller I have the following method:
public function postAdd(){
$amodel=new myModel();
$amodel->name=Input::get('name');
$amodel->save();
$id=$amodel->id;
}
Which is how the guides say to use it however should this logic not go inside a method on the model rather than in the controller? I know the above still provides abstraction from the database but the bit that I'm unsure of is how reusable it then becomes... or not as the case maybe.
Would it therefore be a better option to do the following:
public function postAdd(){
$amodel=new myModel();
$id = $amodel->addPost(Input::get('name'));
}
So I pass along information to a method on the model which does the work. This allows it to be reused and the model method changed if required without updating many lines of code?
The answer might simply be 'yes, do it like you've suggested' in which case great but I'd be interested on the standard practice when using an ORM like this.
A controller's sole responsibility is handling and delegating UI requests to the Model. That's why it should be skinny. It should only contain code necessary for what it's responsible for. So thats why you should move your code to the model, or, even better and more Laravel-like solution is to use repositories in this case. (link)
I'm using Doctrine 1.2. I'd like to execute a Doctrine_Query that, instead of returning a Doctrine_Collection will return a class of my choosing. That is, something like
$o = Doctrine_Query::create()
->from('Foo')
->execute();
$o; //instance of Doctrine_Collection
will normally return a generic Doctrine_Collection object. Instead I'd like it to return a Foo_Collection object, which I define elsewhere
class Foo_Collection extends Doctrine_Collection
{
public function soSomethingSpecificToAFooObject()
{
}
}
which will allow me to logically group functionality.
Is this possible? From my reading and poking at the code base this would seem to have something to do with hydrators, but I haven't been able to a manual page or tutorial that covers what I'm after.
Im pretty sure you can just add the following to your Record's setUp or construct methods (the table should be available in either one construct is run before setUp i think though):
$this->_table->setAttribute(Doctrine_Core::ATTR_COLLECTION_CLASS, 'Foo_Collection');
You can also set this globally on the Doctrine_Connection if you needed to extend Doctrine_Collection and use a different class throughout all models.
I'm starting with CodeIgniter and after several hours diving in Google I'm a bit confused.
Let's try to explain my question with a easy example: I have a table 'car' with the fields 'name' and 'color'. Therefore I want to have a php class Car, so that my code could look finally like this:
$car = new Car('BMW', 'red'); //new $car Object
$car->save(); //this will make an SQL insert to the table 'car'
//Lets query all cars
$cars = Car::get_all();
//cars will be an array of Car objects, (not a set of rows!)
Therefore, I am looking for something pretty similar to what you have in RubyOnRails or Django (Python). I need to handle all kind of relationships, and to be able of write code in a true OOP+MVC way.
These are my failed approaches to get it:
Using an external ORM (DataMapper, Doctrine, AcidCrud...)
They either requires too many settings, or they handle relationships in a poor way.
Using CodeIgniter classes (to extend the CodeIgniter's Model class)
class Car extends Model{
public function Car($name='',$color='')
{
$this->name = $name;
$this->color = $color;
parent::Model();
}
public function save()
{
$data = array(
'name' => $this->name ,
'color' => $this->color
);
$this->db->insert('cars' $data);
}
And so on... Problem with this approach is that if a do a var_dump() of a $car object, I see that it contains a lot of stuff from the CodeIgniter, such as the objects CI_Config, CI_Input, CI_Benchmark, etc. Therefore I think this is not a good solution, because each object of my class Car, it will contain a lot of repeated data, (it will have a poor performance!), isn't it?
Not using the CodeIgniter's models
I could make my models without extending them from CodeIgniter's Model class, and then using the regular PHP5 constructor (__construct() instead of function Car()), but problem in this case is: how I access to the $db object to make querys using the CodeIgniter's ActiveRecord? and, how I load the models (its classes) within the controllers?
You probably want something like this:
class Cars {
//List all neccessary vars here
function __construct() {
//get instance of Codeigniter Object and load database library
$this->obj =& get_instance();
$this->obj->load->database();
}
//You can now list methods like so:
function selectCar($name, $color) {
$this->obj->db->select('color')->from('car')->where('color', $color);
$query = $this->obj->db->get();
switch ($query->num_rows()) {
case 0:
return false;
break;
default:
return $query->result();
break;
}
}
Hope that helps!
Try with Doctrine, is a great ORM and can be easily integrated in CodeIgniter.
take a look the the codeigniter wiki page for ORM
http://codeigniter.com/wiki/ORM/
For future Googlers, here is a tutorial I wrote up about how to integrate CodeIgniter 2 with Doctrine 2.
Let me know if you have any issues.
I had good luck with using Propel with codeigniter.
check out GAS ORM it sounds pretty good, handy and easy to use.
some features of this ORM implementation for CodeIgniter:
Supported databases : cubrid, mssql, mysql, oci8, odbc, postgre, sqlite, sqlsrv. (including PDO, if you keep sync with CI repo)
Support multiple database connections.
Support multiple relationships.
Support composite keys (for key that define relationships).
Auto-create models from database tables and vice versa.
Auto-synchronize models-tables by creating migrations file.
Per-request caching.
Self-referential and adjacency column/data (hierarchical data).
Eager Loading to maximize your relationship queries (for performance manner).
Various finder methods (can chained with most of CI AR) and aggregates.
Validation and auto-mapping input collection with minimal setup.
Hooks points to control over your model.
Extensions to share your common function/library across your model.
Transactions and other CI AR goodness.
Included phpunit test suite to ensure most of API consistency.
there is one form with spark support -> so it's easy to install
What you want to do is create a library that extends the ActiveRecord class. Some people are ahead of you:
http://codeigniter.com/wiki/ActiveRecord_Class/
good mods in the thread, here:
http://codeigniter.com/forums/viewthread/101987/
If you're looking for ORM methods that are general to your app, just extend the ActiveRecord class. For my application, knowing the structure of a table allows me to scaffold (auto-generate) forms, and do other mapping. I do API-to-API mapping, so I include a GetStructure() method in MyActiveRecord and build other things from there.
(RoR snickering can bugger off now)
Edit: while I am a fan of the scope and power of Doctrine, I think it's demand for command-line usage places it beyond the spirit of CI. What's right for you is what's right for you, but if I'm going to use Doctrine, I might as well use Symfony, right? Or RoR, for that matter, right?? See where I'm gong with this? Right tool for the right time.
I used CodeIgniter with Propel and they really mixed well. I've used like that for a while and got a few webapps working that way. Since I found a few awful ways to do it ( some included modifiying Apache's configuration!!). I decided to publish a blog post on how to do it. You can read it here.
Hope I can help!
I think php-activerecord is a very good drop-in ORM. I've used it with the Slim Framework a few times and I think it would be a great alternative to using CI's native model class. Here is some sample code and the link:
$post = new Post();
$post->title = 'My first blog post!!';
$post->author_id = 5;
$post->save();
PHP ActiveRecord
i know this is quite old, but for those who are just using codeigniter now and wannt to use an orm with it can use this tutorial to integrate propel with codeigniter
http://llanalewis.blogspot.com/2013/06/installing-propel-in-codeigniter.html