Reputation: 21759
I am trying to program in MVC architecture.
So, I have one HTML form where user can insert, let's say, a movie. I have one controller for that (for adding that movie) and one view for the HTML form.
But I also want user to be able to edit that movie after he added it. So, he presses a button "Edit a movie" and he's redirected to the new URL and I have new controller and new view (it has the same form as when user adds the movie, but only now he sees values in inputs which he entered previously, I hope you understand what I mean) for this editing form.
Also, when I want to show how his movie looks like to other users, I once more time have new Controller and new View for that.
edit: I also have to validate what he enters. So, that validations should be in model? Because I validate twice, it doesn't seem right.
Is it correct thinking of MVC? Or what's the best approach for making this? Thanks.
Upvotes: 0
Views: 73
Reputation: 6638
Using a typical project layout for me, I might have something like the following:
Controllers
| |
| - MoviesController.php
|
Models
| |
| - Movie.php
Views
| |
| - Movies
| |- Create.php
| |- Edit.php
| - Partials
| |- _MovieForm.php
MoviesController
contains two actions - Create()
and Edit($id)
, which have their own views. I personally would have a third action as well, which handles the form submission from both actions:
public function Save()
{
//...snip...
}
Create()
simply loads the corresponding view. Edit()
is slightly different in that it retrieves an existing record from the database first, using our Model, before passing it to the view.
The two views have a nested "partial", which is a fragment of commonly used HTML - in this case, _MovieForm.php
, which has our form inputs (which are capable of displaying passed-in values).
The form also contains a hidden input field for our row id. This is only given a value when we call the Edit()
action.
The form submits to the Save()
method of MoviesController, which checks if we have a passed row id. If so, get our row from the database (again, represented by our Model), update the values, and call our Model's Save()
method.Model::Save()
runs our validation logic on our data and either saves to the database, or passes the data back along with our validation error message to the view.
Hope this helps :)
Upvotes: 1
Reputation: 31930
You got it almost right, but there is still some place to simplify it. Common thing is to create action functions inside of your controller which handle certain (surprise, surprise) actions user can do. Usually you'd have, for example, Article controller
with actions add
, remove
, edit
etc. This way you centralize actions for common entity of your application and prevent overflow of controllers. It's easier to maintain, easier to find if you want to change something asap and you will nicely follow DRY principle.
Another thing you could do is to create abstract base controller
for common stuff that's used in multiple controllers (dynamic loading of meta data from database comes in mind).
Having multiple views is fine. You don't have much of a choice anyway. But I'd recommend using some templating engine which would make your life easier and once again force you to not repeat yourself. Twig or Smarty would be perfect choice.
Validation logic should be located in model. Model
is responsible for most of the backend logic (data manipulation, its validation...). Controllers
just take requests, loads appropriate data from Models
and point you to proper View
. Don't get confused though, you usually end up validating your Models
inside Controller
(calling validate()
functions, for example).
Anyway, in the end, you'll find out there are quite many ways how to look at MVC pattern. Some people prefer "fat models" and "skinny controllers", some the other way around. Use whatever fits your needs and keep it simple!
If you want some studying materials, take a look at Symfony2 framework or CakePHP tutorials. There are some valuable information regarding this topic. Maybe you'll end up using one of them instead of reinventing the wheel :)
Upvotes: 1
Reputation: 511
No, it is overly complicated.
You do not need different controller for another action you want to make on something. Eg. if you have a controller for creating a movie, you do not need separate controller for editing it. You need separate action, not controller.
Basically you should employ DRY (Don't-Repeat-Yourself) rule for that. If view only differs by the values and form
's action, just use one view for both actions (create & edit). View should generate similar code for both actions - one will have no form fields filled, with form
's action set to eg. "movies/create
" and the second one will have prepopulated form fields with form
's action set to eg. "movies/<movie_ID_here>/update
" (naming convention is up to you).
Validation should be in model, but as additional help for the users you can validate it also on the client side, using JavaScript or HTML5 (depending what you want), so they do not need to submit the form to know they forgot about something.
Upvotes: 1