skip to Main Content

Learning the MVC model has been a bit of a journey. However, I find myself tripping up over small things every now and again such as if a controller can have a one to one relationship with a model or many controllers to one model, etc. Is there a universal pattern to which is the best abstraction or is it up to the needs and complexity of a program. If so, is it considered good practice to have a model validation validating data that enters in to user model.

2

Answers


  1. There is no standardized way to treat the level of abstraction, only best practices. Furthermore, best practices may vary depending on the framework or flavor of MVC.

    You can consider the following patterns:

    1. The User model contains the required validation logic, e.g. to ensure the userid field is never null and an initialized user object.

    2. Alternatively, you can have a generic Validation model, e.g. making sure the data contain only allowed characters etc. The User model inherits the Validation model and adds user-specific data fields to it

    The decisions on abstraction should be based on the need to couple/decouple and reuse various parts of the code.

    In Pattern 1, the validation logic is always kept together with data. You will never need to run the validation logic without the user data.

    Pattern 2 keeps the validation logic isolated, thus it can be reused for any model.

    Likely, there are many other patterns but discussing them in abstract terms is a bit difficult.

    Login or Signup to reply.
  2. In MVC, the model is supposed to represent your data, while controllers represent the actions that modify the data. Where you place your validation rules can very much be a choice, but I personally prefer keeping them in the Model, since they’re, in my opinion, part of your data definition.

    Here’s a laravel example of that:

    namespace AppModels;
    
    use IlluminateDatabaseEloquentModel;
    
    class User extends Model
    {
        protected $fillable = ['name']; // Define the fillable attributes
        
        public static $rules = [
            'name' => 'required|min:3|max:255', // Validation rules for the 'name' attribute
        ];
        
        public static function validate($data)
        {
            return validator($data, self::$rules);
        }
    }
    

    and in your controller you can call

    $validator = User::validate($data);
    
    if ($validator->fails()) {
        return redirect()->back()->withErrors($validator)->withInput();
    }
    

    In this case the validator is provided by laravel and would be considered a Service.

    As for controllers talking to other controllers, it is generally not considered good practice, since it breaks the separation of conern principle. Normlly you can address that by abstracting some of that logic into Services, which you can then inject into your controllers. If you hit a case where a controller needs to talk to another controller, you should question what the purpose of those two controllers is and if one controller wouldn’t be better.

    Generally models and controllers don’t have a one-to-one relationship and you shouldn’t try to couple them like that. A controller can handle and update multiple models, if the business logic for that makes sense. Try to think about them as compartments similar-purposed logic, instead of just "things that modify models"

    All of this is not really a prescription and real-world cases always differ from the ideallistic patterns that are prescribed as "good software", so don’t be afraid to bend the rules a little bit.

    If you give me an example of when you might need to do interaction between two controllers, I’d be more than happy to help you figure out a decent structure without model-to-model communication.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search