I am building a CRM using a framework (codeigniter) for the first time and I am having trouble determining where a certain module should go while maintaining the MVC methodology. The module automatically generates a new user (when a new company is created) and emails the log in details out to the supplied email address.
I am familiar with the idea of skinny controllers and fat models but to compile all the information needed the module must request data from several different tables as well as inserting data into several tables.
The scenarios I have considered so far:
The logic is in the model where most of the information comes from.
Create a totally new model that deals with just this module and the multiple tables required.
Place the logic in the controller that deals with creating a company.
Create a new library or helper and call the module when it is needed.
Skinny controllers and fat models seem to suggest that one or two are the right options but I was lead to believe that a model should only deal with one table in the database.
What is the right approach to ensure adherence with MVC?
Codeigniter allows you to be flexible with your MVC approach. So the answer is which option is:
Easiest for you (or your team) to understand
Easiest to code maintain
Easiest for someone else to understand
There's no point putting your code into a library, if you dont have any other libraries and dont understand libraries. Same as if all your models are "fat", but only point to one table, do you want this model to be the only one that also points to 4 other tables?
Personally, if this "logic" only ever happens in one place, then I would place it into the controller, and call the 4x models you need to do each bit of the code.
If this "logic" occurs in multiple places, I would place it into a library and call it when needed.
Related
I am currently looking to redesign a feature on my web application.
The web application utilizes Yii (version 1) for the back-end.
In this instance I have a model and controller. The model is used to store all the userTracking data and is appropriately a userTracking model however the actual logic for the model is in a controller called UserController. I have a function called actionTrackUser($id) which is used to implement various tracking logic for a particular user and create a model for that user.
I however now need to extrapolate this functionality from the UserController to a seperate trackingController which will implement tracking for various models.
I need to be able to utilize this functionality however in the new controller and old controller. I was wondering as to the best approach for this in Yii 1 that implements MVC correctly. I thought about making a trackingModel and having the userTracking model extend that but then I would have a lot of business logic in a model in order to use it in two places.
I am fairly new to MVC and Yii so I was wondering as to the best approach to take here?
I have purposely left code out of this question as it is more a theoretical question regarding the implementation of such functionality in Yii.
Any help is appreciated.
Thanks!
I am not sure that there may be a 'best' approach. However, you need to choose an approach that works best for you. Be guided by what will work for your situation, and what will make manageable code for you and others in the future.
There is nothing wrong with your current userTracking model and controller. You state that the "actual logic for the model is in a controller." You may want to relook at that to move appropriate data management, constraints and validation rules to the model at least.
You can move functions to a separate trackingController and still use the userTracking model. There is no rules that says you have to have a matching model and controller set, and it is quite possible for a controller to manage more that one model at a time.
I generally start with activeRecord models, which map against data stores (database tables in most cases). I use corresponding Form models to reflect forms that are markedly different from activeRecord models, and I use domain models to reflect complex business objects that are feature rich, and reflect lots of runtime attributes (like calculated fields) and state data (like publish state, which are calculated from other fields - for example a user could have validation status, paid status, active status, account level and so on that all work together to indicate what activity is possible for the user).
I'm trying to understand the MVC pattern in Phalcon.
In my current application I only need ONE template file for each table. The template contains the datagrid, the SQL statement for the SELECT, the form, add/edit/delete-buttons, a search box and all things necessary to interact with the database, like connection information (of course using includes as much as possible to prevent duplicate code). (I wrote my own complex framework, which converts xml-templates into a complete HTML-page, including all generated Javascript-code and CSS, without any PHP needed for the business logic. Instead of having specific PHP classes for each table in the database, I only use standard operation-scripts and database-classes that can do everything). I'm trying to comply more with web standards though, so I'm investigating alternatives.
I tried the INVO example of Phalcon and noticed that the Companies-page needs a Companies model, a CompaniesController, a CompaniesForm and 4 different views. To me, compared to my single file template now, having so many different files is too confusing.
I agree that separating the presentation from the business logic makes sense, but I can't really understand why the model and controller need to be in separate classes. This only seems to make things more complicated. And it seems many people already are having trouble deciding what should be in the model and what should be in the controller anyway. For example validation sometimes is put in the model if it requires business logic, but otherwise in the controller, which seems quite complex.
I work in a small team only, so 'separation of concerns' (apart from the presentation and business logic) is not really the most important thing for us.
If I decide not to use separate model and controller classes,
what problems could I expect?
Phalcon's Phalcon\Mvc\Model class, which your models are supposed to extend, is designed to provide an object-oriented way of interacting with the database. For example, if your table is Shopping_Cart then you'd name your class ShoppingCart. If your table has a column "id" then you'd define a property in your class public $id;.
Phalcon also gives you methods like initialize() and beforeValidationOnCreate(). I will admit these methods can be very confusing regarding how they work and when they're ran and why you'd ever want to call it in the first place.
The initialize() is quite self-explanatory and is called whenever your class is initiated. Here you can do things like setSource if your table is named differently than your class or call methods like belongsTo and hasMany to define its relationship with other tables.
Relationship are useful since it makes it easy to do something like search for a product in a user's cart, then using the id, you'd get a reference to the Accounts table and finally grab the username of the seller of the item in the buyer's cart.
I mean, sure, you could do separate queries for this kind of stuff, but if you define the table relationships in the very beginning, why not?
In terms of what's the point of defining a dedicated model for each table in the database, you can define your own custom methods for managing the model. For example you might want to define a public function updateItemsInCart($productId,$quantity) method in your ShoppingCart class. Then the idea is whenever you need to interact with the ShoppingCart, you simply call this method and let the Model worry about the business logic. This is instead of writing some complex update query which would also work.
Yes, you can put this kind of stuff in your controller. But there's also a DRY (Don't Repeat Yourself) principle. The purpose of MVC is separation of concerns. So why follow MVC in the first place if you don't want a dedicated Models section? Well, perhaps you don't need one. Not every application requires a model. For example this code doesn't use any: https://github.com/phalcon/blog
Personally, after using Phalcon's Model structure for a while, I've started disliking their 1-tier approach to Models. I prefer multi-tier models more in the direction of entities, services, and repositories. You can find such code over here:
https://github.com/phalcon/mvc/tree/master/multiple-service-layer-model/apps/models
But such can become overkill very quickly and hard to manage due to using too much abstraction. A solution somewhere between the two is usually feasible.
But honestly, there's nothing wrong with using Phalcon's built-in database adapter for your queries. If you come across a query very difficult to write, nobody said that every one of your models needs to extend Phalcon\Mvc\Model. It's still perfectly sound logic to write something like:
$pdo = \Phalcon\DI::getDefault()->getDb()->prepare($sql);
foreach($params as $key => &$val)
{
$pdo->bindParam($key,$val);
}
$pdo->setFetchMode(PDO::FETCH_OBJ);
$pdo->execute();
$results=$pdo->fetchAll();
The models are very flexible, there's no "best" way to arrange them. The "whatever works" approach is fine. As well as the "I want my models to have a method for each operation I could possibly ever want".
I will admit that the invo and vokuro half-functional examples (built for demo purposes only) aren't so great for picking up good model designing habits. I'd advise finding a piece of software which is actually used in a serious manner, like the code for the forums: https://github.com/phalcon/forum/tree/master/app/models
Phalcon is still rather new of a framework to find good role models out there.
As you mention, regarding having all the models in one file, this is perfectly fine. Do note, as mentioned before, using setSource within initialize, you can name your classes differently than the table they're working on. You can also take advantage of namespaces and have the classes match the table names. You can take this a step further and create a single class for creating all your tables dynamically using setSource. That's assuming you want to use Phalcon's database adapter. There's nothing wrong with writing your own code on top of PDO or using another framework's database adapter out there.
As you say, separation of concerns isn't so important to you on a small team, so you can get away without a models directory. If it's any help, you could use something like what I wrote for your database adapter: http://pastie.org/10631358
then you'd toss that in your app/library directory. Load the component in your config like so:
$di->set('easySQL', function(){
return new EasySQL();
});
Then in your Basemodel you'd put:
public function easyQuery($sql,$params=array())
{
return $this->di->getEasySQL()->prepare($sql,$params)->execute()->fetchAll();
}
Finally, from a model, you can do something as simple as:
$this->easyQuery($sqlString,array(':id'=>$id));
Or define the function globally so your controllers can also use it, etc.
There's other ways to do it. Hopefully my "EasySQL" component brings you closer to your goal. Depending on your needs, maybe my "EasySQL" component is just the long way of writing:
$query = new \Phalcon\Mvc\Model\Query($sql, $di);
$matches=$query->execute($params);
If not, perhaps you're looking for something more in the direction of
$matches=MyModel::query()->where(...)->orderBy(...)->limit(...)->execute();
Which is perfectly fine.
Model, View and Controller were designed to separate each process.
Not just Phalcon uses this kind of approach, almost PHP Frameworks today uses that approach.
The Model should be the place where you're saving or updating things, it should not rely on other components but the database table itself (ONLY!), and you're just passing some boolean(if CRUD is done) or a database record query.
You could do that using your Controller, however if you'll be creating multiple controllers and you're doing the same process, it is much better to use 1 function from your model to call and to pass-in your data.
Also, Controllers supposed to be the script in the middle, it should be the one to dispatch every request, when saving records, when you need to use Model, if you need things to queue, you need to call some events, and lastly to respond using json response or showing your template adapter (volt).
We've shorten the word M-V-C, but in reality, we're processing these:
HTTP Request -> Services Loaded (including error handlers) -> The Router -> (Route Parser) -> (Dispatch to specified Controller) -> The Controller -> (Respond using JSON or Template Adapter | Call a Model | Call ACL | Call Event | Queue | API Request | etc....) -> end.
Overview: I am building a CMS using PHP, and I am trying to implement this using MVC. I am trying to extend my code using this structure, as it represents an accurate representation of MVC and it is quite straightforward. To communicate with my database I use Domain Objects and Data Mappers.
Questions:
Is it really necessary to have a 1:1:1 mapping between a model, a view, and a controller?
Example: For a blog system, when displaying a blog entry page I would create a controller called DisplayEntryController, and a View called DisplayEntryView. The view would get its information from the BlogMapper class (which communicates with the DB to retrieve the current blog entry) and a CommentMapper class (which communicates with the DB to retrieve the comments for the current blog entry). Is this good practice, considering that view works with 2 model objects? If not what is the alternative? If yes, how can this be implemented in a generic way?
Can multiple controllers handle one page? For the example above, would it be possible to have a DisplayEntryController and a CommentController handling the relevant parts of a page displaying the blog entry? If yes, how would the 2 controllers coordinate?
Thank you in advance. Examples will be greatly appreciated.
Most PHP MVC implementations I've seen on the web use the page approach to organise their MVC. E.g. for the Home page, you have one view, one controller and one model. Routing for 1:1:1 mapping in MVC is straightforward, as you can enforce the location and naming of your MVC components, and when a request for the Home page comes it automatically looks for the following classes: HomeView HomeController and HomeModel.
This obviously doesn't work well in larger projects. How should routing be handled to support routing to multiple models (DataMappers), multiple views, without creating an overcomplicated router or adding a complex dependency injection layer?
Example: As discussed above, when displaying a blog entry you display
the blog entry code and the comment section. To achieve this, it
communicates with two DataMappers, the one which gets the blog entry,
and the one which returns the comments for the blog. How can the view
be assigned to work with these two datamappers to get the data from
the DB?
There is no requirement to have a 1:1 mapping of the model, controller and view.
MVC works of a concept of a tiered approach to handling your application, with each tier being handled by 'agents' to implement the way they see fit. To explain this further, consider the following scenario.
Assume you process data, then hand them over to someone to store. You don't care where they store it and how they store the data, as long as the information is available again when you need it. You can happily go about processing your data, and then say to them for example 'This is project data for Client X, store it,' and later say 'Can you give me the project data for Client X.'
SO MVC works on this approach, whether the data storage guys dump all data together or pack them away is not important to you. However, what is important is the interface between the two parties when sending and retrieving. For example, you could decide to store the information as either Client data, or Project Data, or both.
Likewise, you could have agents collecting data and handling it to you to process. You don't care how many interfaces they use (for example, phone, web, email, mobile devices), but you care about what data they hand you. (Of course a rule might dictate that only web information must be handled). So the interfaces for collecting data might be different.
Therefore, each agent can use the most efficient method (and even combine or split them) to get the system working in their side, and therefore there is no mapping of the data.
i'm new to Yii, still learning and loving it a lot. So the thing is that i have to build a product retrieval system, which is based on Amazon web services.
First i have created the necessary tables to hold the information about the products. Then i've created the model class using the awesome Gii. After that i generated the CRUD using Gii again. Now i'm kinda stuck. So Gii provides a form to let the users populate the tables with the necessary info. Now in my system/app i have no need for a form input, for any of the main tables that would hold the product information. The tables should auto populate with data gathered from Amazon API. Only a few tables can have form related to the input fields.
So can anyone please guide me in the right direction, on how would i start implementing the functionality. Should i remove this code from the corresponding view and write the functionality in the Controller class.
<div class="row">
<?php echo $form->labelEx($model,'type_id'); ?>
<?php echo $form->textField($model,'type_id'); ?>
<?php echo $form->error($model,'type_id'); ?>
</div>
Or should i generate a separate view files. Right now i can't seem to find any headway. How to start ? What should be the workflow sequence for a typical application built using Yii. Where would i put the business logic? Of course i know that the business logic should always reside within the Controller class as per the MVC paradigm. But should i write all of the application logic in a single controller class.
I've read about modules and components. But the dilemma i'm facing is that i don't know when is the right time to separate the necessary logic into its respective modules or components.
I'm already following the Web Application Developement with Yii and PHP 2nd Edition, and i admit that its a fantastic book. I've read it two times till now. But i'm getting stuck when i get down to build my projects. Just don't know where to start. My application would not follow a similar flow diagram like the book example.
I just want to adhere to the conventions that are set in Yii. I've heard in many places that once you get used to the conventions in Yii your productivity increases hundred folds. So what are the best practices ?
Say::
1) What are the conventions when building an automated/real time system ?
2) How to initialize the specific controller logic sequence
3) How to get the most benefit from the CRUD/Model/Module system already built by Gii ?
With the Gii code generation I try to delete anything that isn't being used. It makes maintenance harder if left in and you can always add it later if required.
Controllers do not need to be related to a table. If anything they should be related to an area of functionality (eg RestApiController or ReportController).
You should keep your controllers as thin as possible. It makes unit testing easier if appropriate logic is in the models. See the last paragraph of the Yii best practices documentation http://www.yiiframework.com/doc/guide/1.1/en/basics.best-practices
Personally I think the Gii CRUD generation is only good for admin level configuration. For example you need to know your database design/relationships to be able to create your data correctly. For a normal user it can be to complex and not very user friendly.
I've been considering adding a Service Layer to my Yii projects. This is where all your wiring up of business logic goes.
I've starting using Codeigniter for a project recently (few months ago) but its getting a little out of hand with a bunch of models that need to interact with each other and I was wondering if I should be creating a library instead?
In my case, I have a user action that happens when you win a game and it would get logged in my user_model but I also want it to get put in my events_model?
Should something like this that affects multiple models become a library?
I know it should NOT be in the controller because I'd have to reuse this trigger in multiple controllers (might not make sense for the provided example but does for my application).
Libraries are meant to provide reusable functionality for your application, while models in the MVC architecture represent the data logic in or the actual data used by your application.
So to answer your question, you can implement a library that handles updating of multiple models. Just ensure that things like database inserts are handled by your models themselves, as that is business logic more than application logic.
You could leave your models modularised as they are and write your logic in libraries, this way you can access mutilple models though a single function in a library, without making your controllers untidy by loading multiple models and having none-interface orientated logic mingled in with interface logic.