Using multiple database tables in CakePHP - php

In my application, i have many methods that my controllers use commonly.
At first i copied them to controllers, then i found out that i must put them in AppController.
So i. reach those methods from derived controllers by "$this->commonmethod"
The methods that i put into AppController creates different types of data,
so i need to put them to 4-5 different tables in my database.
Most of the tables don't have a relation between each other.
But most of my controllers will use that tables to fetch related data for them.
(I checked the examples in cookbook, there are examples about Blogging,
category and tags. Where tables have relation between them)
Should i put my common controller code into a Plugin or Component? Or what would be the decision criteria?
Is it possible to use multiple database tables from a controller or a component?
Do Datasources or behaviours are suitable for this case.
Thank you in advance

It's hard to say what the best approach would be, given we don't know much about the database structure, what the controller methods do, and how they are used.
But one of your questions is very straightforward:
Is it possible to use multiple database tables from a controller or a component?
Yes, that is possible. Just create a model for each table (use public $useTable = 'tablename if cake cannot detect the table name automatically from your model names). Then, in AppController (considering your code will stay there), use this:
public $uses = array('List', 'all', 'models', 'you', 'need');

Best way is (if possible) to redesign the database, because in cakephp a good database design resolve half of your problems. If this is not possible then second one is use Components and using this component you can you multiple database tables.

Related

Where to put custom SQL code in CakePHP 3?

I'm building an application in CakePHP 3. It uses a number of legacy databases which are not built in the Cake conventions.
I do not want to use any of the ORM features Cake provides, as it's more tedious to set up all the relations than just write "Raw SQL". We are also not going to make any changes to the database structures, so the ORM is a non-starter. So I'm going to write raw SQL queries for everything.
However, I'm not sure where this code would be put. I've read https://book.cakephp.org/3.0/en/orm/database-basics.html#running-select-statements but it doesn't say where you actually put that code.
I don't want to put my queries in a controller ideally since that defeats the purpose of MVC.
All I really need is one Model where I can put all my queries in different functions and reference them in my Controller(s).
In Cake 2.x it was easy to just create a model under app/Model/ then load it (loadModel) where needed in controller(s). But with the new Cake 3.x Table and Entity spaces, I'm not sure how this fits in?
I've also read up on Modelless Forms but don't think they're right either. For example the initial page of the application shows a list of chemicals which is just a SELECT statement - it doesn't involve forms or user input at all at this stage.
Obviously there will also be situations where I need to pass data from a Controller to the Model, e.g. queries based on user input.
As mentioned in the comments, I would suggest to not ditch the ORM, it has so many benefits, you'll most probably regret it in the long run.
Setting up the tables shouldn't be a big deal, you could bake everything, and do the refactoring with for example an IDE that does the dirty work of renaming references and filenames, and then set up the rules and associations manually, which might be a little tedious, but overally pretty simple, as there shouldn't really be much more to configure with respect to the database schema, than the foreign keys, and possibly the association property names (which might require updating possible entities #property annotations too) - maybe here and there also conditions and stuff, but oh well.
That being said, for the sake of completeness, you can always create any logic you want, anywhere you want. CakePHP is just PHP, so you could simply create a class somewhere in say the Model namespace (which is a natural fit for model related logic), and use it like any other class wherever needed.
// src/Model/SomeModelRelatedClass.php
namespace App\Model;
class SomeModelRelatedClass
{
public function queryTheDatabase()
{
// ...
}
}
$inst = new \App\Model\SomeModelRelatedClass();
$results = $inst->queryTheDatabase();
See also
Cookbook > Database Access & ORM > Associations - Linking Tables Together > BelongsTo Associations

Where do SQL queries belong in a MVC project?

I have read a book about MVC last week and a general one about design patterns, but I'm still confused as to where SQL queries belong in my code: the model or in the controller?
Let's take a very simple example, where you have a /popular page that will print the 5 most popular stories on a website.
In your model, you would have a class for prepared staments, and a class for assisting in the creation of the SELECT query. In your view, you'd have the HTML elements that display the /popular page.
Where does the query "SELECT most popular stories LIMIT 5" belong to? Is that something a controller class should ask, taking query methods from the model and passing to the view, or should the query be declared instead on a model class related to the /popular page?
Is the distinction even relevant? Would placing that query on the controller or the model be both considered professional ways to build a MVC?
Thank you. It seems most people get stuck understanding what to place on controllers
Edit: thanks for help everyone. Unfortunately as a new account I can't upvote any helpful posts yet
Usually (based on my experiences with MVC frameworks) the model layer takes care of database-related stuff in MVC.
Consider following approach:
Create abstract class which covers all the DB operations (selects, updates, etc). Each table would be a PHP class extending such class. You can then define DB table name in for instance private field, constructor or depending on model name.
Each controller (or the single controller) would load desired model, and use its methods to fetch data as associative arrays or objects, delete the data, change it.
After all DB operations have been done, controller returns view and passes data as its parameters.
Note that models are great place to put all the validation rules, and some helper methods due to the fact that they can be easily tested in PHPUnit.

Using a single flexible model

A quick question this time about the M in Mvc.(using codeigniter, but the question is general)
Suppose I have several models that are responsible for accessing several tables in my database, Is it frowned upon making one flexible model that can deal with everything?
specifically in php-codeigniter, for example:
$this->MY_model->getByID($table,$ID)
So this example code can be used to get by ID of any table I want thus saving me time and I'm able to reuse most of my model code.
This of course can be expanded further
$this->MY_model->update($table,$info) as an example.
So my question is, If all of the above is okay, Where is the 'limit' to such operations? Naturally we wouldn't want something really specific in this type of model, like this method:
$this->MY_model->getAllActiveUsers()
My basic approach is this:
Any method that can be used in more than one table should be used in the extended model.
Any method that should be used in only one table, should be in it's own model.
Just to be clear i'm not looking for an opinion, But rather wondering what's the standard approach to these issues.(for example, imagine an application with 50 models, should CRUD be written for all 50 of them?)
Thanks in advance!
What you are mulling about is pretty standard operation for most Codeigniter developers. If you are going to be doing a lot of CRUD in the DB, then it makes sense to add a set of generic CRUD methods to your base MY_model and then extend it. If you do a search on Google...you'll likely get results for 100s of people who have setup their own base models including CRUD and other common methods used by most Codeigniter projects...here are just a couple:
https://github.com/jamierumbelow/codeigniter-base-model
https://github.com/jenssegers/CodeIgniter-My-Model
should CRUD be written for all 50 of them?
No. You would extend your base model and use it's generic CRUD methods where they make sense and just override certain properties (table name). Then, if you needed something more specific you could create additional, more granular methods in your new model as you suggested.

Why do I need a Application_Model_User and Application_Model_DbTable_User in Zend?

Is there any point in having both? I followed a Zend tutorial which told me to create a user model but can't I just model the user in the DB model class?
Thanks
It's part and parcel of the concept of "separation of concerns" http://en.wikipedia.org/wiki/Separation_of_concerns
Your model class takes care of business logic, validation, variable manipulation etc and your db model class should just handle dealing with the database, that way if you need to replace the db model it wont affect the main model as much, and if you replace the main model it wont affect the db model as long as the right parameters are passed into it.
Yes, you can model your user in Application_Model_DbTable_User (DbTable class) and it will work fine as long as all of the data you need is in that one table.
At some point you will likely start working with objects that should be represented in more then one table. This is when you will discover the need for a different way to do things.
A better simple example of where a mapper and domain object might matter:
The mp3 file.
At it simplest a single music file should probably be represented by at least 3 db tables:
album: a table representing the album the song comes from
artist: the artist that recorded the song
track: the information about the track itself
each artist can have multiple albums, each album will have one artist and will have multiple tracks, each track will belong to one album and one artist (different versions will be different tracks).
As you can see the database stucture of even a simple mp3 collection can become very complex very quickly. In most cases even a simple user record will spread across multiple tables depending upon how much and what kind of data is being persisted.
For some help in understanding how and why to implement mappers and models I found these resources very helpful.
Building a Domain Model, covers what a domain model is and how to build one in PHP.
Adding Mappers to a Domain Model, adds mapper function to the same domain model.
Survive the Deepend, A Zend Framework starter that focuses on models and testing.
The first two links are done in plain PHP but are still very helpful.

Codeigniter 2 models

I've to fetch data from different web services + my own database and combining these data before displaying in the site.
What's the best method for doing this? I prefer writing separate models for web services and database. How can I organize the model classes of different data sources in different folders?
I may add more webservices later.
EDIT: I am Really sorry, as my example below will not work, as you cannot have equally named models. You should prefix them in the subdirectories as well, like:
webservice1/ws1_products
webservice2/ws2_products
db/db_products
products
That way you will load them as
$this->load->model('webservice1/ws1_products');
$this->load->model('webservice2/ws2_products');
$this->load->model('db/db_products');
$this->load->model('products');
And use as
$x = $this->ws1_products->getAll();
$x = $this->ws2_products->getAll();
$x = $this->db_products->getAll();
$x = $this->products->getAll(); // combined result
End of edit.
To separate them in different folders simply put them in subfolders in models directory, then use common syntax $this->load->model('web_service1/products');.
I don't know the best method, as it is a matter of preference, but if I were you, I would separate them as you said in two different models and made a third one, that would combine them to one result.
So if you have to get products from 2 different services and your database, I would make 4 models:
webservice1/products
webservice2/products
db/products
products // the model that combines them to one result
That way you would have to make only one request from the controller, to the products model.
I usually do one model file per data source. Be it a DB table, web service, etc.
For combining data from 2 or more models before rendering I like to do it in the controller if there is business logic involved. If not I do it right in the model (you can now load one model from another in CI2)

Categories