Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

dpelto's avatar

Controller code vs Model

In an older framework I had a model that made the calls to the database. Model code like

    public function getSeries()
    {

        return $this->db->select("SELECT * FROM series ORDER BY seriesname");
    }

The controller calls the model something like

$data['series'] = $seriesModel->getSeries();

Then the view code.

Being new to Laravel I am starting out with the query builder instead of eloquent. I am just confused with what code goes in the model and what code goes in the controller.
0 likes
3 replies
Tray2's avatar
Tray2
Best Answer
Level 73

It depends like everything else.

I usually only place these in my model.

  • Eloquent relationsjops
  • Get Attributes
  • Set Attributes
class Genre extends Model
{
    public function setGenreAttribute($value)
    {
        $this->attributes['genre'] = ucwords(strtolower($value));
    }

    public function books()
    {
        return $this->hasMany(BookView::class);
    }
}

And keep my eloquent and my validations inside my controllers.

class GenresController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth')->except(['index', 'show']);
    }

    protected function validateGenre(Request $request, $validationRules = [])
    {
        $rules = array_merge([
            'genre' => 'required|unique:genres,genre'
        ], $validationRules);

        $request->validate($rules);
    }

    public function index()
    {
        $genres = Genre::orderBy('genre')->get();
        return view('genres.index', compact('genres'));
    }

    public function show($id)
    {
        $genre = Genre::findOrFail($id);
        return view('genres.show', compact('genre'));
    }

    public function edit($id)
    {
        $genre = Genre::findOrFail($id);
        return view('genres.edit')->with(['genre' => $genre]);
    }

    public function create()
    {
        return view('genres.create');
    }

    public function store(Request $request)
    {
        $this->validateGenre($request);
        $genre = new Genre();
        $genre->genre = $request->genre;
        $genre->save();
        return redirect('/genres')->with('status', $genre->genre . ' successfully added.');
    }

    public function update(Genre $genre, Request $request)
    {
        $this->validateGenre($request, ['id' => 'required|exists:genres']);
        $genre->genre = $request->genre;
        $genre->update();
        return redirect('/genres')->with('status', $genre->genre . ' successfully updated.');
    }

    public function destroy(Genre $genre)
    {
        $genre->delete();
        return redirect('/genres')->with('status', $genre->genre . ' successfully deleted.');
    }
}

It's more a matter of taste in most situations at least for me. If I would have some really complex eloquent or raw SQL i would most likely push it to the model or in the case of the raw SQL push it into a database view. The good thing about the database view is that I can keep my eloquent clean and simple.

By doing this with five tables

            DB::statement(
                "CREATE OR REPLACE VIEW book_views AS
                SELECT a.id author_id, 
                    b.id book_id, 
                    CONCAT(a.last_name, ', ', a.first_name) author_name,
                    b.title,
                    (SELECT ROUND(AVG(s.score), 1) FROM scores s WHERE s.book_id = b.id) rating,
                    b.series,
                    b.part,
                    b.released,
                    g.id genre_id,
                    g.genre,
                    f.id format_id,
                    f.format,
                    CASE series
                        WHEN 'Standalone' THEN b.released
                        ELSE (SELECT MIN(bi.released) FROM books bi WHERE bi.series = b.series) 
                    END series_started
                FROM authors a,
                    books b,
                    genres g,
                    formats f
                WHERE a.id = b.author_id
                AND   b.genre_id = g.id
                AND   b.format_id = f.id"
            );

I can still use a pretty simple eloquent query in my controller

    public function index()
    {
        $books = BookView::orderBy('author_name')
                         ->orderBy('series_started')
                         ->orderBy('part')
                         ->orderBy('released')
                         ->orderBy('title')
                         ->get();
        return view('books.index')->with('books', $books);
    }

However like I said before it's a matter of your preference or in worst case a matter of coding convention used by the company you are working for..

dpelto's avatar

Tray2, I have used views, but it's been a while. What I meant, do I put the actual query builder query in a model and do a return like

public function getSeries()
    {
        return DB::table('series')->get();
    }

and from a controller call it like

$data['series'] = $this->Series->getSeries();

So far laravel models don't look like database models I'm used to. The code above is simplified, of course the actual query has where, orderby, etc. I am attempting to get a grasp of query builder. So far it looks easy. I am not sure where to put the code is my problem.

Your example

    public function books()
    {
        return $this->hasMany(BookView::class);
    }

I have never used anything like that. I know it's eloquent from looking over the laravel documentation.

Tray2's avatar

When I said view I meant a database view

create or replace view some_views as
select something from sometable

This is a eloquent relationship

public function books()
    {
        return $this->hasMany(BookView::class);
    }

Where in my case I connect the genres table with the book_views view. By doing that I can call

$booksOfGenre = $genre->books();

And get all the books that has a certain genre.

So if I do this in my controller

public function show($id)
    {
        $genre = Genre::findOrFail($id);
        return view('genres.show', compact('genre'));
    }

I can then in my view (not database view) do this

@foreach($genre->books as $book)
    {{$book->title}}
@endforeach

Please or to participate in this conversation.