Ramos's avatar
Level 1

Doubt about MVC and Laravel

Hello! I'm very new in Laravel, started studying like 20 days ago. In a Udemy course, youtube tutorials and blogs teaching Laravel is common people ONLY use model to interact with the database, putting the logic in the Controllers and Route, what for me is strange (to don't say wrong, since I do not have enough knowledge in Laravel and ORM to judge). To train, I'm developing a application that, so far, receive a CSV file from the user and show it back to user. I would like to ask you guys if the way design my application is correct in terms of MVC and Laravel :)

How the project is design: There is a Upload.blade.php that contains a form to receive and send the file. Once send, the UploadFileController.php verify if the everything is Ok with the request and the file, if not send back to Upload.blade.php with error. (I get this on a blog post teaching how to send file with laravel) So far the logic and validation is in Controller, but I want to validate every CSV information and put this in a array of objects (encapsulation) and then send back to view, for example: there is a date in every row of the file that have de format mm/dd/aaaa and I need to put in aaaa/mm/dd (mysql format)

To achieve what I want, in the controller I pass the file content to ModelCSVtoObj.php that transform the CSV in a array using "str_getcsv", there is a method that get every row from the CSV, that now is a array, and fill a object from class ModelGastos.php, this object take care to encapsulation the data (date example), once a object is complete, it is added to a array, is this array that the Controller send back to the view, and I show the data using the get methods.

In short: Upload.blade.php -> UploadFileController.php -> ModelCSVtoObj.php -> ModelGastos.php

Below there all the code minus the view with form, since its not relevant, the comments are in Portuguese and English.

UploadFileController: Receive the CSV file and return a array of objects

class UploadFileController extends Controller {
public function upload() {
  // getting all of the post data
  $file = array('arquivo' => Input::file('arquivo'));
  // setting up rules
  $rules = array('arquivo' => 'required',); //mimes:jpeg,bmp,png and for max size max:10000
  // doing the validation, passing post data, rules and the messages
  $validator = Validator::make($file, $rules);
  if ($validator->fails()) {
    // send back to the page with the input data and errors
    return Redirect::to('upload')->withInput()->withErrors($validator);
  }
  else {
    // checking file is valid.
    if (Input::file('arquivo')->isValid()) {
      $destinationPath = 'uploads'; // upload path
      $extension = Input::file('arquivo')->getClientOriginalExtension(); // getting arquivo extension
      $fileName = rand(11111,99999).'.'.$extension; // renameing arquivo
      Input::file('arquivo')->move($destinationPath, $fileName); // uploading file to given path
      // sending back with message
      Session::flash('success', 'Upload successfully');
      //pega  o conteudo do arquivo csv // get CSV content
      $conteudoDoArquivo = File::get($destinationPath.'/'.$fileName);
      //Passa o conteudo do arquivo para um objeto que irá retornar uma lista de objetos
      //Pass the content of the file to a objeto, thar will return a array of objects
      $modelCSVtoObj = new ModelCSVtoObj($conteudoDoArquivo);      
      //Send the obj list to view     
      //return print_r($modelCSVtoObj->getListaObj());
      return view('pages.uploadOk', ['listaObjGastos' => $modelCSVtoObj->getListaObj()]);
    }
    else {
      // sending back with error message.
      Session::flash('error', 'uploaded file is not valid');
      return Redirect::to('upload');
    }
  }
}
}

ModelCSVtoObj: responsible to transform the data, with the help of ModelGastos

class ModelCSVtoObj 
{
    private $conteudo;
    private $listaObjetos;

    function __construct($conteudoArquivo)
    {
        //Transforma o CSV em um array // Transform the CSV file into a array
        $this->conteudo = str_getcsv($conteudoArquivo,",",'"',"\n") ;
    }
    /**
     * retorna o CSV como array | return the CSV like a array
     * @return array of string
     * */
    function getConteudoArray()
    {        
        return ($this->conteudo);
    }
        /**
     * retorna o CSV como array de objetos | return the CSV like a array of objetos
     * @return array of objects
     * */
    function getListaObj()
    {
        $this->arrayToObj($this->conteudo);
        return $this->listaObjetos;
    }

    private function arrayToObj ($array)
    {
        $cont = 0;
        $valores = [];
        //A cada 6 dados do array cria um novo obj e add ele na lista
        foreach ($array as $indice => $dado) 
        {
            $valores[] = $dado;
            if($cont < 5)
            { 
                $cont++;               
            }
            else
            {
                $cont = 0;
                $objGasto = new ModelGastos($valores);
                unset($valores);
                $this->listaObjetos[] = $objGasto;
            }
        }
    }
}

ModelGastos: Encapsulate the data, used to fill the array of objects in the ModelCSVtoObj

class ModelGastos
{
    private $data;
    private $dependenciaOrigem;
    private $Histórico;
    private $dataBalencete;
    private $numeroDocumento;
    private $valor;

    function __construct($arrayDados)
    {
        $this->_setData($arrayDados[0]);
        $this->_setDependenciaOrigem($arrayDados[1]);
        $this->_setHistórico($arrayDados[2]);
        $this->_setDataBalencete($arrayDados[3]);
        $this->_setNumeroDocumento($arrayDados[4]);
        $this->_setValor($arrayDados[5]);
    }
/*Getters and Setters*/
Uploadok.blade.php: show
 the data
@extends('layouts.master')
@section('title')
  Dados do arquivo
@endsection
@section('content')
@if ($listaObjGastos)
   @foreach($listaObjGastos as $gasto)
      {{  $gasto->getData() }}
      {{  $gasto->getHistórico() }}
      {{  $gasto->getDependenciaOrigem() }}
      {{  $gasto->getdataBalencete() }}
      {{  $gasto->getNumeroDocumento() }}
      {{  $gasto->getValor()}}
    @endforeach
@endif
@endsection
0 likes
3 replies
Ramos's avatar
Level 1

Anyone? I really want know if this is the correct way, since I'm starting with MVC frameworks.

ricardovigatti's avatar

@Ramos, i don't want say this is wrong, cause actually it is not... BUT, your controller is holding a lot of responsibilites, don't you think?

I don't understand the relation between those models either. Of course that one of them should be the real Model, the other, i don't know, maybe a helper or a librarie.

I can help you in portuguese if you want, but to improve this you will need better knowledges about some layers that are available to you implement. I'm talking about Services, Validations, Helpers, Libraries, etc etc etc.

Nowadays the MVC approach has evolved and has a lot of variations.

Ramos's avatar
Level 1

@ricardovigatti Thank you for answering! I believe you are Brazilian, like me :) I have interest in your help in portuguese, but I think this post in english is important, others people may have the same doubt.

Answering yours questions: 1- I do believe the controller is doing more than it should, but, as I said, the tutorials I find so far put all the logic, validation and SQL (eloquent in this case) in the controllers, letting the model empty, using it just to interact with the database, what I did was take the logic and putting in models. Do you suggest something? create more controllers?. I'm using 3 controllers in this system, but this one continue the same.

2- ModelGastos helps ModelCSVtoObj to do what it needs, in this case it may be called a helper, but I don't the difference between a model and a helper, yet.

In college I learn that MVC work with 3 layers and did some examples in Java desktop, but the more i try to understand MVC in web framework, more confuse a get :( This post endorse your argument about the variation in modern MVC: http://stackoverflow.com/questions/7621832/architecture-more-suitable-for-web-apps-than-mvc/7622038#7622038

The lessons here in laracast, explain how correct work in MVC, considering the way Laravel works?

Please or to participate in this conversation.