Best practice in CakePHP for call function in another controller - php

I have an controller attachment responsible for handling all uploads files. This controller uses a component to perform this control.
Now I have the following problem, I need call a function implemented in attachments controller from another controller, what is the best practice in this case? whereas:
It is not advised to call a function from a controller to another.
If I implement the function in my model this would have to use a component that is also not advised.

You don't. It's completely wrong and violating the MVC pattern.
Files represent a single entity in the system and should be handled as those (IMO) and in the model layer, not in the controller. You implement the validation and saving logic in a single model and access that model through associations from other places if you have too.
For example User hasOne Avatar, Gallery hasMany Image. Where the Avatar and Gallery association is your attachments or files table model.
I've written a plugin that does exactly the above and a little more
https://github.com/burzum/cakephp-file-storage
Use that or move your controller logic into a model. Controllers should be really really skinny and only have, well, controlling logic, they should never care about data handling or manipulation.

Related

Yii: Following strict MVC rules to ensure that all the business logic is in appropriate places

Sticking to MVC basics in Yii, I am trying to embed my business rules in the model class but facing problem in implementing it. The problem at hand is to stop the user from making duplicate entries and code the function in model class that checks if the entry already exists in table. I want to write a method in my model class which would query the sames model's underlying table and if the new business entity exists, it simply returns false. If I code this in controller, I can achieve the desired functionality but I want to keep this in model so that where ever the model is used, I can access the method and also stick to MVC basics which dictates Thin Controllers and Thick Models. Thanks in advance.
The best way would be to avoid the use of active record instances (at least) directly in the controller.
Instead you should create service-like structures, which contains the interaction between your CActiveRecord and CFormModel instances. This would let you better isolate the presentation layer (views, controllers and templates) from model layer.
Such services also would be able to hold (and sometimes, react upon) errors/exceptions thrown by CActiveRecord and CFormModel instances, that it utilizes.
Cross-site Request Forgery Prevention may be what you are looking for? unless your idea of 'duplicate entries' is directly related to your business model, in which case you can override the CActiveRecord.beforeSave() and put your logic in there, if this method returns false, the record won't be saved to the database.
If you use the later method, and you want to pass the error to the view and display to the user, you can always use the CModel.addError() method, in this case in your beforeSave method.
There is another option though, which is using custom validators.
which is more appropriate? depends on your business logic.

Do I need to create a Model for every Controller? What is the better practise?

Let's say I have a Model 'Retrieve.php' where I have a class named 'Retrieve' and it retrieves posts from a database. Then I have Controller in Index.php where I load that model, retrieve posts and pass it to view.
And now, I have one more page where I have to show those posts. Let's say Sidebar.php or something. And now again, I have to retrieve those posts. So, can I load 'Retrieve.php' once more, or I have to create one more model for Sidebar.php which extends 'Retrieve.php'? What is better practise?
And, in general, do I need for every controller create a new model in a good PHP MVC? If yes, probably Controller and Model should be named the same? Any more advices/comments?
Thank you.
In general, the model should represent a business entity and not a process. I.e., it should be a noun and not a verb. In your case, you want a model for a post, and the methods on that model will perform "the things you do with/to a post." The controller then describes what actions occur for a page. In this case, a controller for the /post page would retrieve a post and pass it to the view for rendering.
Only create the models you need. Remember, the whole point of MVC is that the models are decoupled from the views. This means it's perfectly fine to reuse whatever you need to get the job done. If you have multiple views which need access to the same data, just reuse the same model. Just be sure to give the models descriptive names so there's no confusion as to what they're supposed to represent.
You should only have one Model class for each data structure that that model represents. So if you have 5 Controllers that each access the same Model, you should still only ever have one Model class.
No --
Model should be what your application manages -- so instead of Retrieve, your model class should probably be Post (and maybe you have other Model classes for the nouns in your domain-- Thread, Author...)
The controllers should access the model classes they need to do their jobs; one model class could be used by several controllers, and one controller could use several model classes.

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
}
}

models using controllers?

is it usual to use controllers in models?
then you have to include the controller in the model?
Models should not be using controllers.
To clarify, using the MVC pattern, the user communicates with the controller which manipulates the model which dispatches its results to the view back to the user.
Image taken from The Model-View-Controller (MVC) Design Pattern for PHP
Update to Doug's response:
The most logical way to explain how the components work is by starting from the model, then going through the controller, and finally reaching the view. And "MCV" would not have been nearly as appealing a name to the ear as "MVC."
Taken from Chapter 1 of Beginning ASP.NET MVC 1.0 by Simone Chiaretta and Keyvan Nayyeri.
No it is not common. You should never have to use your controllers from your model.
If you feel the need to, it probably means code that is currently in your controller should live in a shared library, or actually be in the model to begin with.
It is of course proper to use a model from a controller.
Update
Code that doesn't directly relate to a specific database table/record (model), or doesn't directly respond to a user's action (controller), would be a good candidate for a utilities or library file.
This is more normal, and where you load it depends on if you are using a framework or not. If it just your custom app, you can just do a require_once in your model and use the utility methods from there.

How do MVC components fit together?

I've seen a number of examples of ways MVC components fit together on the web.
The Controller retrives data from the Model and passes it to the View
This seems a bit verbose and messy.
$model = new Model;
$view = new View;
$view->set('foo', $model->getFoo());
$view->display();
The Controller passes the Model to the View
What if the View needs data from multiple Models?
$model = new Model;
$view = new View($model);
$view->display(); //View takes what is needed from the Model
The Controller passes the View to the Model
$view = new View;
$model = new Model($view);
$view->display(); //Model has told the View what is needed
Which of these is the "best" way to go about things? If none, what is?
The Controller retrives data from the Model and passes it to the View
As you said it's verbose and messy. But that's the most appropriate solution with the philosophy of MVC.
The Controller passes the Model to the View
Seems valid too. However it'll require for the view to ask for some model method. Which is not really in the spirit of MVC. Your view should only render the datas that are provided to it, without caring about the context.
The Controller passes the View to the Model
Forget that one. Here it is messy.
The answer is self evident if you consider that the 'model' is the central artifact (potentially used across applications), and that a 'view' may (or may not) be aware of the specific model but it is (by definition) a 'view' of a (potentially abstract) model and again, potentially usable across applications. The 'controller' is managing interactions and is the most application specific element of the pattern, so it definitively needs to know about model and view details.
If the view is specific to a given model, you can use option 2.
If the view is for an abstract model (and you can use it to display info from a set of models), you use option 1.
Option 3 is simply wrong.
The answer to the original question is:
The Controller retrives data from the Model and passes it to the View
MVC is actually very neat and clean. Remember what it is addressing:
Code reuse (Models do not rely on controllers or views. Views do not rely on controllers or models. Controllers are app specific.)
Separation of Logic (For instance changing an authentication backend from MySQL to LDAP require 0 change to a view. Changing a view's layout requires 0 change to model. Changing the database table structure requires 0 change to the controller or view).
Now IF you want your forms to be automatically generated from a table structure - the views are now tied to the table (tightly coupled). A change in the table require a change in the view (albeit potentially automatically). This may take less code - but the view is no longer dependable from a code-reuse stand point.
Similarly your views (in MVC) should be nothing more than templates. There should be no logic - just variables. All the "logic", aka business rules, reside in the controller. The models know how to get data and keep it normalized. The views know how to display data. The controller knows when to use the data and which views to apply the data to.
MVC is a strict 3-tier architecture. A two tiered architecture is valid for some applications. For quick mashups and "getting crap done" a one tied architecture can be appropriate (but you don't get style points).
Hope this helps.
IMHO, option 2 (the Controller passes the model to the view) best maintains the proper decoupling and separation of concerns. If the view needs multiple models, the model passed in should be a composite data type that contains each model needed by the view. "Each model needed by the view" is usually different from your entity model in that it is flattened and streamlined for display, often called a ViewModel.
Option 1 (the Controller retrives data from the Model and passes it to the View) is quite similar to option 2, but I contend option 2 is preferable because it places less logic in the controller. In MVC, as much logic as possible should be in the model, leaving your controllers and views as simple as possible.
I tend to agree with the second one. MVC on the web can't really be implemented as it can in more stateful applications. Most web MVC implementations have you put your logic in your controllers and use the model for raw data access. I think the more correct way is to put your logic in your model. There is almost an implied 4th layer in that raw data access is done within the model, however the model is also responsible for giving that data meaning and updating the view.
The wikipedia article explains it pretty good.

Categories