Symfony2 when should I create a new controller? - php

I'm currently using Symfony2 and and I'm trying to divide my code into different controller (like an Ajax Controller, a User Controller etc...) but I don't really know when I should use a create a new One.
For example my DefaultController is starting to be quite big (~800 lines) and I was wondering if having a too long controller could impact the website's performance? (Longer loading time...)
And, if it does, when should I split the controller into smaller ones ?

I would say that you should group your actions by which operate on the same data (entities) or operate within a well defined responsibility. E.g. UserController for users, PostController for blog posts, etc. This means that if you want to create an action which role is different than the rest of the actions, put it in a separate controller.
Symfony is caching almost everything so I don't think that huge controllers would cause an impact to the perfomance but if you have a thousands lines long controller, I'm not sure that it does only one thing.
The controller's size can be a warning sign too for the misplaced queries and business logic. You should separate QueryBuilder calls into Repository classes and other logic to services and event handlers. You can save more lines by using annotations instead of PHP code.

I think it's a good idea to start with a controller for each relevant model, with a CRUD structure.
Of course it depends on your needs, but if you have a model "Post", you probably will need a PostController with CRUD routes and methods, like : index (/posts), new, update, create, delete...
Depending what you need you can delete or add some method relative to a
Post from this base structure.
Try to detect what is realy relative to a specific model in your defaultController and create a controller for it.
Good luck.

What #riska and #Yoann said all holds true.
In addition, I prefer not to create separate controller if I'm sure that it hold only that one method. In that case, I just put it into DefaultController.

From my experience, controllers are the part of UI layer. If you care a lot about keeping your controllers small, let me give you the best scenario you can make what a controller must do:
1.Call the appropriate service
2.Return the response
That is 2 lines of code for each controller action, or you can even make it in one line.
Like person above said, controllers are usually separated by what type of entities / services they operate on. If you for example have an entity - lets say User, the following actions are most likely to be in there: createAction, editAction, removeAction, registerAction, activateAction, loginAction, logoutAction and so on...
It does not have any impact on performance if your controllers are thin or fat. The code will be executed in the similar flow, and all classes are being cached in the production environment.

Related

Advantages of Multiple Controllers over Single Controller in MVC?

I'm developing a laravel app and would like to know some best practices.
As an example, I'm thinking about creating multiple controllers instead of writing more than 10 methods in a single controller.
I would like to know what are or( if there are any ) advantages other than code readability.
My main concern is that how does it affect when there are more files to compile by the PHP compiler.
Since I'm using a framework is it going to compile all the files or only the file requested by web.php
Some insight would be great!
If the 10 methods you have in a controller are all related, then keep them in that controller. If you have a FruitController with methods related to performing actions on types of Fruit, but you also include some methods for performing actions on Vegetables, move the Vegetable methods to a new controller.
Consider encapsulation when composing your files.
In general, avoid making files for the sake of it. If it makes sense to create a new file as the logic you intend to place inside that file has no other existing home, then fine, otherwise add your logic to an existing file.
I'm not sure splitting related code into separate files increases readability, large files can be readable as long as the code is well formatted and consistent (amongst other things). Check out this book on clean code if you're interested.
What you will get though is a decrease in productivity and maintainability by having to flick through and maintain several files that are all related.
There is no advantage of using multiple controllers instead of one controller, as long as it is related to one single model. You may say it increases readability, but this is better to unify them in one single controller which is associated with your model and try to pick expressive names for the methods. The main idea is to create one single controller associated with each of your models. Feel free to add as much as methods possible into your models to talk to your database and make queries and call those methods in the associated controller. Then you can trigger those controllers through the web.php routes to handle your data and pass them to the view layer.
When you create separate controller for particular functionality this is more readable for old and new developer.
Also please check this link
From laravel:
Instead of defining all of your request handling logic as Closures in route files, you
may wish to organize this behavior using Controller classes. Controllers can group
related request handling logic into a single class. Controllers are stored in the
app/Http/Controllers directory.
I recommend that you divide your logic into different controllers. For example you can place all your user logic into one controller userController.php:
Create User
Edit User
Delete User
Then create another controller to manage the logic for another controller like sending emails etc. In this way your logic is more organized, easy to work with and you can find and update your methods easier.

Why separate Model and Controller in MVC?

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.

What could I do to improve my MVC?

I'm thinking of re-working my MVC before I get to far along with it. At the moment it uses a sinle controller which takes the user input and determines the model. The model has maby differ methods which I call actions, because one is called automatically. The model loads its view file, which again holds many different methods. The model can set properties which can be used in the view. Then the controller calls th template classwhich parses the output for display.
Is this the bst way to do it?
Or should each different part (news, contact, about) have its own controller, which loads a specific model and view. Essentially, instead of grouping methods into a single file, it uses multipe files.
I'm kind of lost as to how I should do it.
Cheers
Start using a MVC that works and is well-known like in Symfony or Cake. From that you will decide:
what do to in your own, knowing the best practices;
to drop your own if you feel like you can save time by using theses.
If you are thinking of advancing your own MVC model, like #e-satis have said, you will need to experience what is happening in already developed systems. However, as based on my experience in designing MVC model and determining what is there in opensource community, I stick back to my own MVC for two good reasons. One reason is the flexibility of customization and the other is own MVC privacy.
I used the following approach for MVC design pattern.
A Router.php file identifying user-request urls. This router will be able to fetch controllers and include the file and call the controller default method.
The loaded controller is also able to load other controllers if required to function. This is done using a global method, where all controller Class will extend to a MainController Class which is able to call to other controllers.
I do use a global registry to set and get variables from one controller to the other.
The Models are used to get the Data from Table, and most of my Models will represent Database functions which includes CRUD (Create Read Update Delete). So that a controller can easily manipulate database table data using a model.
Naming conventions in all controller, models, and views is also important, if you want to system to be more intelligent to identify the required action knowing the file name.
I use the Views separately for each type of controller. And these views will be sent to a Master Template View file.
Same as models, the controller will be able to set Views to Master View.
There are other customizations which you can do, like applying security methods before calling a class, or after calling a class/controller/model/view etc.
This is done by the MainController, which it will always look into a folder with autoload class which states what files should be loaded before and after of different actions during the process of building the content and delivering the output.
MVC is not a small scale idea, but it is a design idea which can always be developed. There are so many PHP MVC open source frameworks to be found if you know how to search the major search engines like google.com
But I do advice you that, MVC is not a good solution if you are simply developing a small dynamic website, as it will consume more time in developing compared to developing small websites. MVC is ideal, if you have business logic and needs system automation in order to avoid most routine tasks of developing, and like that I would say MVC is most ideal for larger applications.
The model loads its view file
The Controller should act as a Mediator between the Model and the View.
The Model shouldn't be aware of the way the view renders it, and also the View shouldn't be aware of any kind of logic of the Model.
In theory, if your MVC is well structured, you should be able to represent the same Model with different types of Views (HTML, XML, JSON for example).
Build FrontController which parses request uri and decides which controller to load and which method to run. With .htaccess rewrite all request to index.php
//index.php
class FrontController{
function run(){
//parse request uri here /comment/new
//load controller comment
//run controllers method new and pass some request attributes
}
}
// ../controllers/comment.php
class Controller_Comment extends Controller{
function new($request){
//do stuff here
}
}

Way to bypass the controller in CodeIgniter?

I've been using the CodeIgniter framework for PHP and am enjoying it, but I notice that it seems to require a controller for every view. I'm wondering if there is a way to call a specific model from the view itself, rather than route through a controller. I understand that use of a controller is best practice in most cases, especially where the data from the model needs to be modified in some way, but I have cases where I just need to do a strict data pull to the view (which is loaded via ajax), and setting up a controller for that seems superfluous.
Any thoughts? Thanks in advance!
You're fundamentally misunderstanding MVC, at least as implemented in CI.
All URLs on your site (at least those that utilize the CI framework) are mapped to functions (methods) within controllers.
http://myCIsite.com/controller/method[/var1][/var2]...
It doesn't matter whether the URL is accessed via regular HTTP or via AJAX. This is always a one to one mapping. Because of this, you should think of the controller/method combination as the "web page". Do not think of the view as the web page.
Models and views are subordinate to controllers. The controller delegates specific responsibilities to them - database interaction for models, and page output to views.
Because models and views only serve to perform delegated responsibilities, their use is not required in any given controller/method. Help pages, for example, generally have no need to interact with a database, so there is no model utilized by the controller/method combination that serves a given help page. Likewise, form handlers frequently redirect to another page upon completion of processing. As such, there is no view corresponding to the form handler (but there is (likely) a view called from the controller/method in the redirected to page).
Furthermore, models and views do not necessarily correspond on a one to one basis with individual controllers/methods. Any given model can be loaded and used from within several controllers. Similarly, a controller could have a single monolithic view that is used by all methods, or each method could be assigned its own view. (Or, as I just said, a given controller/method could utilize no view at all.)
Finally, CI does not enforce strict MVC separation. You can interact with the database and echo HTML all from within the controller and CI will not complain. Nevertheless, this separation and delegation of responsibility is followed because logically separating the responsibilities makes the code easier to read and helps you follow the DRY principle in your coding.
The fundamental Understanding is that the "web page" corresponds to the controller/method. The view and model, when used, handle delegated responsibilities for the controller/method.
I'm wondering if there is a way to
call a specific model from the view
itself, rather than route through a
controller.
That's not possible as of what I know, the main abstract class of the CI controller imposes restriction to use a controller otherwise you will get a fatal error.
And actually what you say will break the best practice of MVC design pattern. You got to go to model through a controller not view.
I'm a bit confused as to exactly what you're trying to achieve. The controller's value, aside from just being a clean way to handle incoming requests, is to manage the interaction between the models and the views and to determine which views to load. It's also entirely reasonable to load model data directly from your views, but how did you get to your view in the first place?
I guess I'm just having a hard time seeing the context here..
To run a query via Ajax you still need to provide a URL / path in the javascript call. You can not get around the fact that a controller function has to "catch" this call; you can not map a url directly to a model. All you need is 3-4 lines of code in your controller.
Via URI routing you can map a URL to a different controller, so you don't "require a controller for every view". I always create a controller called "ajax" to handle those requests.
A basic ajax call with jquery can be something like this
$('#prod_img').load( "http://domain.com/ajax/get_img", {'color': 'blue', 'url_title': 'bla' } )
You can echo stuff in your controller, so rather than trying to bypass the controller you should be looking into how to do away with the views. This will actually be easy, you can load the db class in the controller just as you can in a model.
But if you really don't want to use MVC perhaps Codeigniter is not the framework for you.
You should read more into the principles of MVC.
Views are strictly for presentation of data, the model shouldn't communicate with views directly.
But still if that's what you want then just pass $this->db from the controller to the view and use it in the view.
Then again, this is NOT a good practice.

Which Code Should Go Where in MVC Structure

My problem is in somewhere between model and controller.Everything works perfect for me when I use MVC just for crud (create, read, update, delete).I have separate models for each database table .I access these models from controller , to crud them . For example , in contacts application,I have actions (create, read, update, delete) in controller(contact) to use model's (contact) methods (create, read, update, delete).
The problem starts when I try to do something more complicated. There are some complex processes which I do not know where should I put them.
For example , in registering user process. I can not just finish this process in user model because , I have to use other models too (sending mails , creating other records for user via other models) and do lots of complex validations via other models.
For example , in some complex searching processes , I have to access lots of models (articles, videos, images etc.)
Or, sometimes , I have to use apis to decide what I will do next or which database model I will use to record data
So where is the place to do this complicated processes. I do not want to do them in controllers , Because sometimes I should use these processes in other controllers too. And I do not want to put these process in models because , I use models as database access layers .May be I am wrong,I want to know . Thank you for your answer .
Just a short comment (no solution) AFAIK that is an eternal question - MVC is just a pattern, and as such, is in theory implementable cleanly. In practise, due to limitations set by available tools (such as programming language library contents and UI component interface design..) you have to make local decisions. The important thing is that you aim to separate these...and not have everything in one mess. I take my comment off the air and am left to see if someone has a "final solution".
For simple tasks I would write action helpers (e.g. sendNewsletter).
For sophistocated tasks I woud create services (eg. email, auth etc.).
In MVC, you should place those things in the model (for reuse reasons for one).
However, in HVMC, you could place them wherever (such as in a controller) and call the controllers from within your application.
I would make your controllers simple.
In many ways the model allows you to offload a lot of the complexity that would otherwise occlude your controller code. Its this division of complexity which will make your code more easily understood, and easier to maintain.
personally I try to keep my models resembling real world objects, not databases tables or rows. It makes it much easier if you have made things speak in more readable terms. A single real world object might involve 5 or 6 database tables... And it would be a rather large hassle to speak with 5 or 6 models, when all you want to do is turn on a switch, or pick a flower, or paint an icon, or send a message.
What's wrong with a controller using multiple models? Isn't the point of MVC to make the model reusable? In your first scenario, it's perfectly fine to send emails and manipulate other model objects from wherever the "register user" controller code is.
In regard to your second scenario, why can't SearchController use ArticleModel, ImageModel and VideoModel? It's fine to have a controller without a model. SearchController doesn't need a SearchModel class, it just uses the other model classes.
I'm trying not to get into a rant about MVC in web apps, but basically, IMHO the controller is just a high-level list of steps to complete an operation. As a rough example, the "register user" controller code should do each of the following steps in roughly one or two lines of code:
Validate the input
If not valid, redisplay the form with an error
Create the new UserModel object from the form input
Insert the new UserModel object into the database
Create/edit whatever other model objects are necessary
Send off an email to the new user
Display a "registration successful" page
How those steps are coded largely depends on whatever framework/architecture you're using.
Keep your controllers clean. For backend processing use Manager classes like MailManager etc..

Categories