new controller in oo php - php

I have a practical doubt ,
I am using OO php , and i am new to it. I am using zend framework to be clear.
I am writing controllers(class) and actions(methods) with in it say PatientMapper.php which has all single mysql table related actions and Patient.php which has all setter and getter functions.
I get a doubt that when should i write a new controller.
Should i write a controller for all the actions on a single mysql table .
or a single controller for all actions related to a module.

As opposed to the previous answers, I would say that your controller should not be related to your DB.
Controllers don't handle business logic, your models do.
Besides that, you can write a controller for each entities.
User is an entity, which can be wrapped in a controller, even if it depends on several tables.
If your controller is getting bigger and bigger, you can switch to module (Zend Framework terminology) and create an User module, which has an Account controller, etc...

I think you should write controller for single mysql table, because if your application will grow up you can end with few thousand line controllers.

A controller groups actions that conceptually belong together somehow. The controller might use one specific model class (which is not necessarily a database accessing class) only, but it may also use many of them.
Important is, that the controller should not contain the logic of the model classes. The sole responsibility of a controller is to receive and delegate the input for a specific interaction you allow users to do with your application to the model. And in webbased MVC, it is usually also responsible to update the View according to the result of the operation.
The most important distinction one has to understand in MVC is that M should be able to live on it's own while V and C belong together. V and C form just the UI to your application and they should not do anything beside that. Basically, your M is your application, while your VC just sits on top of it. Should really be M|VC imho
With that said, if you feel your application can get away with a single Controller, then use a single appController. But once you find yourself adding actions that could conceptually fit into a separate controller, then add a new controller. If your application is a simple CRUD app, then have one controller per database table. If it does something else, then give it something that fits the scenario.

IMHO I would suggest a action for each mysql table related action
for maintainability. These would be ligtweight actions that just call your model for that table

#gordon - Yeah my application is a CRUD application. SO i need to create a model for each table..This is the most accepted way rite. And yeah i am bit clear abt controllers..
i have a page where in i need data from 3 tables. So i will need to call all 3 model methods to get the data rite...
I have a small doubt...i use code like this at the beginning of the beginning of class .and this was written by other developer....i am using it.. i am finding it difficult to use joins ,bcos this is locking the DB..any help on how to use joins over here
protected $_dbTable;
public function setDbTable($dbTable)
{
if (is_string($dbTable)) {
$dbTable = new $dbTable();
}
if (!$dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception('Invalid table data gateway provided');
}
$this->_dbTable = $dbTable;
return $this;
}
public function getDbTable()
{
if (null === $this->_dbTable) {
$this->setDbTable('Application_Model_DbTable_Appointment');
}
return $this->_dbTable;
}
this is the select part..not able to use join
$select = $this->getDbTable()->select()
->from("patient_appointment",array('pa_pd_patient_id',
'DATE_FORMAT(pa_datetime,"%h:%i %p") as pa_time','pa_datetime','pa_um_id'
,'pa_created_date','pa_mode','pa_type'))
->where('date(pa_datetime) = ?', $date)
->where('pa_pd_patient_id = ?', $patientId)
->order('time(pa_datetime)');
$resultSet = $this->getDbTable()->fetchAll($select);

Related

Where to put not Eloquent related SQL queries

I use Eloquent to implement my models. It has a lot of methods that makes working with models much easier. However, in some cases I have to implement functionality that is accessing the database, but doesn't return an Eloquent model.
For example, imagine a common User model. Eloquent helps me a lot in CRUD operations for the User model, but what if I have to implement a method that returns some statistics about users (ex. how many total users, how many active users, etc.).
Where should I implement this functionality? In the Eloquent model, as a public static function, (e.g. User::getStats()), or should have a different class for this.
It seems a little bit unnatural to have these methods on a Eloquent model, because they are not Eloquent related.
It's really up to you, but it's a good idea to decide on a convention and stick to it.
My rule of thumb is this:
if it's related to a single item that is normally represented by an Eloquent model, do it as a public static method on that model. For example, in my current project, I have a Contract model. I needed a method that would generate a contract ID string (for compatibility with legacy systems) for new contracts. This is related to a single item (a contract) but for technical reasons needed to be generated separately from the Eloquent model (ie. it was based on a separate database with a different connection). So I created a public static method: public static function generateContractIdentifier($id, $salesRep). If you're using a repository for access to your database, you could put it there.
If it's more general (ie. not tied to an instance of the Eloquent model), I put it into a separate library. For example, in the same application I have a queue for processing items for printing (an industrial process). The application has a dashboard and I needed to show the current queue status for management. For this I created a ProcessStatus library and implemented a method: public function getStatus() which runs a query and provides the results as an array for display in a view. This is not related to any particular item in the queue, so I put it in a separate library.
As always, it depends on your project and what role the user plays in it.
But basically, no, I don't think the logic for building reports belongs on the user model. While it may be related to the user, regarding the SOLID-principle the User class should only have one responsibility, which in this case is to handle the User entity.
This contains getting and setting properties on an instance, in a simple project it's probably also fine to define some scopes on the model, e.g. to select only active users, like User::getActive();
But as your project grows, you should consider using more specific classes.
For instance, you could abstract the Eloquent functionality into a User-Repository. So now you have a handler for operations on the entitiy itself, like
$userRepo->getAll();
$userRepo->getActive();
$userRepo->getInactive();
and a handler for a User instance:
$user->getName();
$user->setStatus();
Creating reports and statistics is yet a completely different topic. So you could have something like a UserReportBuilder oder UserStatisticsService:
$userStats->getMostActive();
$userStats->getRegistrationsPerDay();
A simple example:
// UserRepository:
class UserRepository
{
protected $model = $model;
public function __construct($model)
{
// you pass in an instance of the actual Eloquent model
// so you have the whole power of eloquent in here
$this->model = $model;
}
public function getActive()
{
// this returns a collection of models
return $this->model->where('status', 'active')->get();
}
}
$userRepo = new UserRepo(new User);
And that's pretty much it. You can still work with Eloquent, but you have separated the functionality in parts with a clewar responsibility. So your UserStats class would only be resposible for building user statistics:
class UserStats
{
// You could pass in the Repository through the constructor
// or just use the Eloquent model directly
public function getRegistrationsPerDay()
{
return User::groupBy('day')->get(
[
DB::raw('DATE(created_at) as day'),
DB::raw('count(*) as registration_count')
]
);
}
}
The User instance or the UserStats-builder do not need to know how to fetch all users, and the User instance or the UserRepository do not need to know how to calculate registrations per day, so it makes sense to split that functionality into separate, independent parts that do exactly one thing.
I think you get the idea and I hope it makes sense. Maybe you should make yourself more familiar with the SOLID-principles and try to keep them in mind when you get stuck on problems like that.

Laravel 4 Models, how to use them

I've been looking at Laravel for awhile and I decided to finally pick it up. It's my first time using a PHP framework and I'm having some trouble grasping the purpose of the models.
I've been reading a lot of newbie guides and this is pretty much all that is in their model (Laravel wise),
class Model extends Eloquent {
}
And then in their controller they do something like this,
$model = new Model;
$model->text = "text";
$model->save();
I'm no expert at the MVC pattern (probably the biggest newbie out there) but I thought the whole point (or at least a small point) was to separate a lot of actions. And that the model was supposed to be responsible of handling everything DB-wise. So in a way, this seems wrong to me or at least not the best practice.
But if you start setting up a bunch of functions you could run into the issue of having one model for every table. Which again, doesn't seem right. So you have to make the model, in a way, ambiguous. In the sense that it can take any actions against any table?
It all just seems really confusing to me at the moment.
You are going to need a model for evey table, because there are other things related to models that cannot be shared, like column names and validation, but if you think you are repeating yourself, you can create a BaseModel and add all methods or even overload Eloquent methods in it:
class BaseModel extends Eloquent {
public function whatever() {
}
public function save(array $options = []) {
// do what you need to do
parent::save();
}
}
Then create your models using it:
class Order extends BaseModel {
}
But you don't need much on a model, if your models and tables names follows Laravel pattern (in this case the table name would be 'orders'), then you just need this simple declaration to have a model working for your table.
Edit:
Controllers are meant to transfer data from a model to a view, but they should not know too much about your data, almost everything about them should lies in your models ("Fat models, skinny controllers"), so they need to know just enough to have "control".
class OrdersController extends BaseController {
public function process()
{
$order = Order::find( Input::get('orderId') )->process();
return View::make('orders.showProcessedOrder')->with('order',$order);
}
}
Models are a wrapper around your database tables. Your database tables are the real-world things you are making your application about. Models allow you to use your programming language for CRUD'ing (creating, reading, updating or deleting) data. OOP is all about classes and objects, and converting things like incoming HTTP requests and data storage into that form.
Your question is a good one. When you learn how to make Web applications, having a three-tiered web app - a presentation layer, a business-logic layer and data-storage layer with data stored in a relational database - works great, and it makes no doggone sense to add an extra layer of database-related stuff in the code.
And, like Antonio wrote, in MVC programming, "fat models, skinny controllers" is what you're working towards. The controller ideally should just be a couple of lines of code that pass the incoming request to the correct model where it could be validated, added to the database, etc. (But it is easiest to put that in the controller while you're first learning/figuring MVC out.)

How should a model be structured in MVC? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I am just getting a grasp on the MVC framework and I often wonder how much code should go in the model. I tend to have a data access class that has methods like this:
public function CheckUsername($connection, $username)
{
try
{
$data = array();
$data['Username'] = $username;
//// SQL
$sql = "SELECT Username FROM" . $this->usersTableName . " WHERE Username = :Username";
//// Execute statement
return $this->ExecuteObject($connection, $sql, $data);
}
catch(Exception $e)
{
throw $e;
}
}
My models tend to be an entity class that is mapped to the database table.
Should the model object have all the database mapped properties as well as the code above or is it OK to separate that code out that actually does the database work?
Will I end up having four layers?
Disclaimer: the following is a description of how I understand MVC-like patterns in the context of PHP-based web applications. All the external links that are used in the content are there to explain terms and concepts, and not to imply my own credibility on the subject.
The first thing that I must clear up is: the model is a layer.
Second: there is a difference between classical MVC and what we use in web development. Here's a bit of an older answer I wrote, which briefly describes how they are different.
What a model is NOT:
The model is not a class or any single object. It is a very common mistake to make (I did too, though the original answer was written when I began to learn otherwise), because most frameworks perpetuate this misconception.
Neither is it an Object-Relational Mapping technique (ORM) nor an abstraction of database tables. Anyone who tells you otherwise is most likely trying to 'sell' another brand-new ORM or a whole framework.
What a model is:
In proper MVC adaptation, the M contains all the domain business logic and the Model Layer is mostly made from three types of structures:
Domain Objects
A domain object is a logical container of purely domain information; it usually represents a logical entity in the problem domain space. Commonly referred to as business logic.
This would be where you define how to validate data before sending an invoice, or to compute the total cost of an order. At the same time, Domain Objects are completely unaware of storage - neither from where (SQL database, REST API, text file, etc.) nor even if they get saved or retrieved.
Data Mappers
These objects are only responsible for the storage. If you store information in a database, this would be where the SQL lives. Or maybe you use an XML file to store data, and your Data Mappers are parsing from and to XML files.
Services
You can think of them as "higher level Domain Objects", but instead of business logic, Services are responsible for interaction between Domain Objects and Mappers. These structures end up creating a "public" interface for interacting with the domain business logic. You can avoid them, but at the penalty of leaking some domain logic into Controllers.
There is a related answer to this subject in the ACL implementation question - it might be useful.
The communication between the model layer and other parts of the MVC triad should happen only through Services. The clear separation has a few additional benefits:
it helps to enforce the single responsibility principle (SRP)
provides additional 'wiggle room' in case the logic changes
keeps the controller as simple as possible
gives a clear blueprint, if you ever need an external API
How to interact with a model?
Prerequisites: watch lectures "Global State and Singletons" and "Don't Look For Things!" from the Clean Code Talks.
Gaining access to service instances
For both the View and Controller instances (what you could call: "UI layer") to have access these services, there are two general approaches:
You can inject the required services in the constructors of your views and controllers directly, preferably using a DI container.
Using a factory for services as a mandatory dependency for all of your views and controllers.
As you might suspect, the DI container is a lot more elegant solution (while not being the easiest for a beginner). The two libraries, that I recommend considering for this functionality would be Syfmony's standalone DependencyInjection component or Auryn.
Both the solutions using a factory and a DI container would let you also share the instances of various servers to be shared between the selected controller and view for a given request-response cycle.
Alteration of model's state
Now that you can access to the model layer in the controllers, you need to start actually using them:
public function postLogin(Request $request)
{
$email = $request->get('email');
$identity = $this->identification->findIdentityByEmailAddress($email);
$this->identification->loginWithPassword(
$identity,
$request->get('password')
);
}
Your controllers have a very clear task: take the user input and, based on this input, change the current state of business logic. In this example the states that are changed between are "anonymous user" and "logged in user".
Controller is not responsible for validating user's input, because that is part of business rules and controller is definitely not calling SQL queries, like what you would see here or here (please don't hate on them, they are misguided, not evil).
Showing user the state-change.
Ok, user has logged in (or failed). Now what? Said user is still unaware of it. So you need to actually produce a response and that is the responsibility of a view.
public function postLogin()
{
$path = '/login';
if ($this->identification->isUserLoggedIn()) {
$path = '/dashboard';
}
return new RedirectResponse($path);
}
In this case, the view produced one of two possible responses, based on the current state of model layer. For a different use-case you would have the view picking different templates to render, based on something like "current selected of article" .
The presentation layer can actually get quite elaborate, as described here: Understanding MVC Views in PHP.
But I am just making a REST API!
Of course, there are situations, when this is a overkill.
MVC is just a concrete solution for Separation of Concerns principle. MVC separates user interface from the business logic, and it in the UI it separated handling of user input and the presentation. This is crucial. While often people describe it as a "triad", it's not actually made up from three independent parts. The structure is more like this:
It means, that, when your presentation layer's logic is close to none-existent, the pragmatic approach is to keep them as single layer. It also can substantially simplify some aspects of model layer.
Using this approach the login example (for an API) can be written as:
public function postLogin(Request $request)
{
$email = $request->get('email');
$data = [
'status' => 'ok',
];
try {
$identity = $this->identification->findIdentityByEmailAddress($email);
$token = $this->identification->loginWithPassword(
$identity,
$request->get('password')
);
} catch (FailedIdentification $exception) {
$data = [
'status' => 'error',
'message' => 'Login failed!',
]
}
return new JsonResponse($data);
}
While this is not sustainable, when you have complicate logic for rendering a response body, this simplification is very useful for more trivial scenarios. But be warned, this approach will become a nightmare, when attempting to use in large codebases with complex presentation logic.
How to build the model?
Since there is not a single "Model" class (as explained above), you really do not "build the model". Instead you start from making Services, which are able to perform certain methods. And then implement Domain Objects and Mappers.
An example of a service method:
In the both approaches above there was this login method for the identification service. What would it actually look like. I am using a slightly modified version of the same functionality from a library, that I wrote .. because I am lazy:
public function loginWithPassword(Identity $identity, string $password): string
{
if ($identity->matchPassword($password) === false) {
$this->logWrongPasswordNotice($identity, [
'email' => $identity->getEmailAddress(),
'key' => $password, // this is the wrong password
]);
throw new PasswordMismatch;
}
$identity->setPassword($password);
$this->updateIdentityOnUse($identity);
$cookie = $this->createCookieIdentity($identity);
$this->logger->info('login successful', [
'input' => [
'email' => $identity->getEmailAddress(),
],
'user' => [
'account' => $identity->getAccountId(),
'identity' => $identity->getId(),
],
]);
return $cookie->getToken();
}
As you can see, at this level of abstraction, there is no indication of where the data was fetched from. It might be a database, but it also might be just a mock object for testing purposes. Even the data mappers, that are actually used for it, are hidden away in the private methods of this service.
private function changeIdentityStatus(Entity\Identity $identity, int $status)
{
$identity->setStatus($status);
$identity->setLastUsed(time());
$mapper = $this->mapperFactory->create(Mapper\Identity::class);
$mapper->store($identity);
}
Ways of creating mappers
To implement an abstraction of persistence, on the most flexible approaches is to create custom data mappers.
From: PoEAA book
In practice they are implemented for interaction with specific classes or superclasses. Lets say you have Customer and Admin in your code (both inheriting from a User superclass). Both would probably end up having a separate matching mapper, since they contain different fields. But you will also end up with shared and commonly used operations. For example: updating the "last seen online" time. And instead of making the existing mappers more convoluted, the more pragmatic approach is to have a general "User Mapper", which only update that timestamp.
Some additional comments:
Database tables and model
While sometimes there is a direct 1:1:1 relationship between a database table, Domain Object, and Mapper, in larger projects it might be less common than you expect:
Information used by a single Domain Object might be mapped from different tables, while the object itself has no persistence in the database.
Example: if you are generating a monthly report. This would collect information from different of tables, but there is no magical MonthlyReport table in the database.
A single Mapper can affect multiple tables.
Example: when you are storing data from the User object, this Domain Object could contain collection of other domain objects - Group instances. If you alter them and store the User, the Data Mapper will have to update and/or insert entries in multiple tables.
Data from a single Domain Object is stored in more than one table.
Example: in large systems (think: a medium-sized social network), it might be pragmatic to store user authentication data and often-accessed data separately from larger chunks of content, which is rarely required. In that case you might still have a single User class, but the information it contains would depend of whether full details were fetched.
For every Domain Object there can be more than one mapper
Example: you have a news site with a shared codebased for both public-facing and the management software. But, while both interfaces use the same Article class, the management needs a lot more info populated in it. In this case you would have two separate mappers: "internal" and "external". Each performing different queries, or even use different databases (as in master or slave).
A view is not a template
View instances in MVC (if you are not using the MVP variation of the pattern) are responsible for the presentational logic. This means that each View will usually juggle at least a few templates. It acquires data from the Model Layer and then, based on the received information, chooses a template and sets values.
One of the benefits you gain from this is re-usability. If you create a ListView class, then, with well-written code, you can have the same class handing the presentation of user-list and comments below an article. Because they both have the same presentation logic. You just switch templates.
You can use either native PHP templates or use some third-party templating engine. There also might be some third-party libraries, which are able to fully replace View instances.
What about the old version of the answer?
The only major change is that, what is called Model in the old version, is actually a Service. The rest of the "library analogy" keeps up pretty well.
The only flaw that I see is that this would be a really strange library, because it would return you information from the book, but not let you touch the book itself, because otherwise the abstraction would start to "leak". I might have to think of a more fitting analogy.
What is the relationship between View and Controller instances?
The MVC structure is composed of two layers: ui and model. The main structures in the UI layer are views and controller.
When you are dealing with websites that use MVC design pattern, the best way is to have 1:1 relation between views and controllers. Each view represents a whole page in your website and it has a dedicated controller to handle all the incoming requests for that particular view.
For example, to represent an opened article, you would have \Application\Controller\Document and \Application\View\Document. This would contain all the main functionality for UI layer, when it comes to dealing with articles (of course you might have some XHR components that are not directly related to articles).
Everything that is business logic belongs in a model, whether it is a database query, calculations, a REST call, etc.
You can have the data access in the model itself, the MVC pattern doesn't restrict you from doing that. You can sugar coat it with services, mappers and what not, but the actual definition of a model is a layer that handles business logic, nothing more, nothing less. It can be a class, a function, or a complete module with a gazillion objects if that's what you want.
It's always easier to have a separate object that actually executes the database queries instead of having them being executed in the model directly: this will especially come in handy when unit testing (because of the easiness of injecting a mock database dependency in your model):
class Database {
protected $_conn;
public function __construct($connection) {
$this->_conn = $connection;
}
public function ExecuteObject($sql, $data) {
// stuff
}
}
abstract class Model {
protected $_db;
public function __construct(Database $db) {
$this->_db = $db;
}
}
class User extends Model {
public function CheckUsername($username) {
// ...
$sql = "SELECT Username FROM" . $this->usersTableName . " WHERE ...";
return $this->_db->ExecuteObject($sql, $data);
}
}
$db = new Database($conn);
$model = new User($db);
$model->CheckUsername('foo');
Also, in PHP, you rarely need to catch/rethrow exceptions because the backtrace is preserved, especially in a case like your example. Just let the exception be thrown and catch it in the controller instead.
In Web-"MVC" you can do whatever you please.
The original concept (1) described the model as the business logic. It should represent the application state and enforce some data consistency. That approach is often described as "fat model".
Most PHP frameworks follow a more shallow approach, where the model is just a database interface. But at the very least these models should still validate the incoming data and relations.
Either way, you're not very far off if you separate the SQL stuff or database calls into another layer. This way you only need to concern yourself with the real data/behaviour, not with the actual storage API. (It's however unreasonable to overdo it. You'll e.g. never be able to replace a database backend with a filestorage if that wasn't designed ahead.)
More oftenly most of the applications will have data,display and processing part and we just put all those in the letters M,V and C.
Model(M)-->Has the attributes that holds state of application and it dont know any thing about V and C.
View(V)-->Has displaying format for the application and and only knows about how-to-digest model on it and does not bother about C.
Controller(C)---->Has processing part of application and acts as wiring between M and V and it depends on both M,V unlike M and V.
Altogether there is separation of concern between each.
In future any change or enhancements can be added very easily.
In my case I have a database class that handle all the direct database interaction such as querying, fetching, and such. So if I had to change my database from MySQL to PostgreSQL there won't be any problem. So adding that extra layer can be useful.
Each table can have its own class and have its specific methods, but to actually get the data, it lets the database class handle it:
File Database.php
class Database {
private static $connection;
private static $current_query;
...
public static function query($sql) {
if (!self::$connection){
self::open_connection();
}
self::$current_query = $sql;
$result = mysql_query($sql,self::$connection);
if (!$result){
self::close_connection();
// throw custom error
// The query failed for some reason. here is query :: self::$current_query
$error = new Error(2,"There is an Error in the query.\n<b>Query:</b>\n{$sql}\n");
$error->handleError();
}
return $result;
}
....
public static function find_by_sql($sql){
if (!is_string($sql))
return false;
$result_set = self::query($sql);
$obj_arr = array();
while ($row = self::fetch_array($result_set))
{
$obj_arr[] = self::instantiate($row);
}
return $obj_arr;
}
}
Table object classL
class DomainPeer extends Database {
public static function getDomainInfoList() {
$sql = 'SELECT ';
$sql .='d.`id`,';
$sql .='d.`name`,';
$sql .='d.`shortName`,';
$sql .='d.`created_at`,';
$sql .='d.`updated_at`,';
$sql .='count(q.id) as queries ';
$sql .='FROM `domains` d ';
$sql .='LEFT JOIN queries q on q.domainId = d.id ';
$sql .='GROUP BY d.id';
return self::find_by_sql($sql);
}
....
}
I hope this example helps you create a good structure.

Zend framework: what is the right place to validate user input?

I want to add a user in users table via link like '/index/adduser/id/7' .
Question
Should I validate user input inside 'adduserAction' function inside controller or somewhere inside model file? I've put files containing database related functions inside 'models' directory. Suppose a user is added to a table via 'id'. This id is sent via 'get'. And finally its added to table by 'AddUser' function (inside model file). Then I should validate this 'id' inside 'adduserAction' or 'AddUser'.? Scalability-wise, would it be better to do it inside 'AddUser'?
There's a popular believe / paradigm that states:
Thin controllers, fat models.
What this means, is that your controller should only be responsible for doing the bare minimum to make sure actions change the state of models and serve the right view in return. With this in mind, the validation should occur in your models. But... hold on for a minute. Models aren't necceseraly 1 tiered layers.
I believe among .NET programmers the following setup (or something similar) is a pretty common practice (if the scale of the project validates it):
Controller
-> ServiceLayer
-> Repository
-> DataObject
And I'm starting too like this setup more and more. Moreover, I believe this setup is very doable in a Zend Framework environment too.
The term Model is somewhat of a vague term. In the above you could consider the three last layers as your Model layer. What the three layers represent is the following:
ServiceLayer:
Responsible for business logic. In other words: retrieving Dataobjects (Models) from the repository, tying Models together, AND validating Models before storing them, mailing a user, etc..
Repository:
Some type of persistence mechanism (like a Database), that serves DataObjects to the service layer, and stores DataObjects back in the persistence mechanism (after the service layer validated them)
DataObject:
You might consider this the actual Models. Preferably DataObjects have common interfaces (independant of the Repository that is), so that Repositories are interchangeable. In other words, when the repository changes from a database to an XML file from some webservice, the DataObject still has the same interface the service layer and ultimately the view can work with.
Hope this makes sense. This is basically my understanding of a more layered MVC setup right now. If anybody feels I have things mixed up please feel free to correct me.
Please keep in mind though, that not all projects dignify such a layered setup. In smaller projects you could perhaps do with just a 1 layered Model layer. In that case, validating should still be the Model's responsiblity. The controller should be thin (just for tying Model state and Views together through actions).
I would say put the validation in your model. You can then keep your validation rules in a central location. How should your controller know the exact length of a valid user name? That is model territory. Your controller can ask the model if a user name length is correct or not sure, but the rule itself needs to be in your model. In my controller I would do something like this:
$model = new Model;
$model->loadFromArray(something to get post);
if (!$model->isValid()) { forward back to form }
$model->save();
the ideal solution is to use validation inside your forms - i.e. appending it to your zend_form_elements - see http://framework.zend.com/manual/en/zend.form.elements.html
I'd do it in the Controller, not the Model. IMHO that's the better place because then the sanitized data is secure to use in the controller already. That's a good thing for comparing things, etc., even before the data is actually saved.
I know it's already answered, but I remember the "younger me" combing the web for some choice resources on sites like this and would like to share my research and what I do here. I do the following:
I use forms to do input validation
and filtering Do my validation inside
models
I have a validation method
which proxies the form validation
method.
This validation method can called upon
internally by model methods or externally
by the controller or view.
Here's a quick example:
//UserModel
class Default_Model_User
{
protected $_form;
public function getForm()
{
if(!isset($this->_form)) {
$this->_form = new Default_Model_Form_User();
}
}
public function validate($data)
{
if($result = $this->getForm()->isValid($data)) {
// if you have custom validation conditions outside of the form, then you
// can do the validation here also.
if($data['controller_entered'] == 'some value') {
$result = false;
}
}
return $result;
}
public function saveUser($data)
{
if($result = $this->validate($data)) {
// do something.
}
return $result;
}
}
If you haven't read it already, be sure to check out the Surviving The Deepend book freely available on the following URL:
http://www.survivethedeepend.com/zendframeworkbook/en/1.0
This chapter is specific to your dilema:
http://www.survivethedeepend.com/zendframeworkbook/en/1.0/implementing.the.domain.model.entries.and.authors#id1491270
You will no doubt run into other issues as you progress through... It may help to check out the comments on my blog post regarding the model layer where I cover this issue: http://www.rvdavid.net/my-zend-framework-model-layer-part-service-part-orm/
Hope this helps someone out.

Accessing CodeIgniter Models in Other Models

It used to be that within a CodeIgniter model you couldn't access another model.
$this->load->model('bar');
$this->bar->something();
Is this still valid, or have they changed it?
Those are some VERY long answers for a simple question.
Short answer: This is now fully supported. Cross-load away if you feel like it!
I strongly disagree with the notion that a "model" should only encapsulate a database table with simple CRUD operations. As noted in the Wikipedia article:
http://en.wikipedia.org/wiki/Model-view-controller#As_a_design_pattern
...that application layer is intended to do more than simply act as a single database table abstraction. Think about the meaning of the word "controller" -- it should act more as a director rather than being the entire application in and of itself. A "model" is a place for business logic. Most large scale applications in fact hold much of their business logic in the database itself (in the form of triggers, stored procedures, foreign keys, etc.).
I think the misunderstanding of what a "model" is is partly caused by the same (over-)hype of "MVC", without carrying with it much understanding of the concepts themselves. Kinda like how empty "AJAX" is, or even more easy, "Web 2.0". For better or worse, plenty of script kiddies have jumped on the MVC wagon, and since the simple howtos and example scenarios don't do much more than tell you to put your database code in the "model", the misuse of that layer as only a database abstraction has become commonplace. Now you read posts all over the Internet calling it "unpure", "dirty", "hackish" to put any business logic in a model. That's WRONG. Misinformed.
The easy example is to think about foreign keys: even if you only want your "model" to be a database model, if you want to be "pure", "correct" or what have you, you really should be enforcing referential integrity therein. Thanks to the lack of real foreign key support in MySQL for many years, web applications grew up without anyone worrying about referential integrity at all. Fits the script kiddie lifestyle I guess. Anyhow, for even this simplified view of a model to be able to maintain foreign key validity, a model then has to work with others (or, especially if a framework like CodeIgniter does not let you do so, you have to write queries to other tables, sometimes duplicating queries elsewhere - THAT is bad style).
Therefore, I believe this to be a shortcoming of CodeIgniter. I understand that it might not be an easy fix, but it's certainly a disappointing oversight.
So what I did was take the example code above and abstract it into a helper so that I now have a function that works almost identically to the normal $this->load->model() functionality. Here it is (put it into a helper that is auto-loaded and you can use it in any model):
/**
*
* Allow models to use other models
*
* This is a substitute for the inability to load models
* inside of other models in CodeIgniter. Call it like
* this:
*
* $salaries = model_load_model('salary');
* ...
* $salary = $salaries->get_salary($employee_id);
*
* #param string $model_name The name of the model that is to be loaded
*
* #return object The requested model object
*
*/
function model_load_model($model_name)
{
$CI =& get_instance();
$CI->load->model($model_name);
return $CI->$model_name;
}
It's possible, but not ideal and considered bad and more for "quick fix" than ideal or pure implementation.
class Location extends Model{
public function get($ID){
// Get main CI object handle and load model
$CI =& get_instance();
$CI->load->model('LocationType');
// Call new model functions using handle to main CI object
$CI->LocationType->setID($result->LocationTypeID);
$CI->LocationType->setTitle($result->TypeTitle);
$this->_locationType = $CI->LocationType;
//Other Stuff
}
}
Anytime you're using the main CI object like this is probably a bad idea. Try to re-think your layout and just pass data to/from your controller to the models.
http://codeigniter.com/forums/viewthread/69833/
You can load models from models as Phil Sturgeon says, but you have to be careful of dependencies if you load the models in the model constructor: if model A uses model B and model B uses model A, when you try to load one or the other, you'll go into an infinite loop.
In situations like this in Code Igniter I prefer one of two posiibilities:
1) Have model's attribute and setter like this:
class X extends Model {
var $Y_model;
public function setY($Y) {
$this->Y_model = $Y;
}
public function doItRightNow($a,$b) {
$list = $this->Y_model->getSomeList($a,$b);
// ...
}
// ...
}
And then use this setter before other methods to give an instance of other model so it can be used by methods.
$this->load->model('X');
$this->load->model('Y');
$this->X->setY($this->Y);
$this->X->doItRightNow($something,$somethingElse);
2) To have a parameter in method by which I will give an other model instance from controller.
class X extends Model {
public function doItRightNow($a,$b,$Y_model) {
$list = $Y_model->getSomeList($a,$b);
// ...
}
// ...
}
And use it like this:
$this->load->model('X');
$this->load->model('Y');
$this->X->doItRightNow($something,$somethingElse,$this->Y);
I think that these are more clean possibilities.
Which way to use depends on how many methods need to access other model. If there are one or two it might be better to give it as a method parameter. If more - I think it's better to have a class attribute and setter.
And in elegant way you can give one model or another depending on some condition - if they both partially implement same interface with the same kind of data returned (it's rarely useful, but it can be sometimes).
I think it's generally better the write libraries that access the models and then include the libraries in your model if need be.
For instance, if you needed to check if someone is authorized to go through with a certain CRUD action, you might want to include whatever authentication library you are using (its probably auto-included in most cases). You wouldn't necessarily want to access the model directly--it just seems dirty and improper.
I think the preferred way is to do what you need to do in your controller and pass the results from one model's method(s), if need be, to your other model's method(s).
Regardless, I can't see why it wouldn't be possible to include one model into another, per se. I don't think you can do it with the syntax you are showing, though. You would have to do it some other convoluted way. In any case, IMO, it's bad practice to include a model directly into another model.
In CI 2.0 you can just call one model directly from another.
Better to create a helper function instead of calling the function from another model so that it can be used in 2 models at a time and code can be reused.

Categories