DEV Community

David Llop
David Llop

Posted on • Originally published at davidllop.com on

1 2

Adding View models to a Laravel project

Since the beggining of 2017 I started to experiment with different kind of codes and patterns I didn't used before.

One of that changes came in November when I was developing the code of this other blog. I saw that I was duplicating a lot of code inside my controllers on the methods for create and edit a resource, in which I use the same blade file.

Some data of that view depends on the model I'm editing or creating. For example, if it's an existing record the title should be Edit post: {$post->title} instead of Create a post. That logic applies to the form action and form method too.

I created a main FormViewModel, and every view model dedicated to a form extends it.

abstract class FormViewModel
{

    public $model;
    public $title;
    public $action;
    public $method;

    public function __construct(Model $model)
    {
        $this->model = $model;

        $this->setTitle();

        $this->setAction();

        $this->setMethod();
    }
}

This view models are forced to declare the methods called on the constructor

protected abstract function setTitle();

protected abstract function setAction();

protected abstract function setMethod();

This is an implementation of the setTitle method in the CategoryDetailViewModel:

protected function setTitle()
{
    $this->title = $this->model->exists
        ? "Edit Category: {$this->model->name}"
        : "Create Category";
}

They can also add more logic in their own constructor, like the PostDetailViewModel:

public function __construct(Post $post)
{
    parent::__construct($post);

    $this->published_at = $this->model->exists
        ? $this->model->published_at->format('Y-m-d\TH:i')
        : Carbon::now()->format('Y-m-d\TH:i');

    $this->categories = Category::select('id', 'name')->get();
}

Using the view models is very easy, the controller only needs to pass this object to the view

public function edit(Theme $theme)
{
    return view('backend.themes.edit', [
        'view' => new ThemeDetailViewModel($theme)
    ]);
}

and the view use the object properties and methods

@section('content')
    <h1>{{ $view->title }}</h1>

    <form method="POST" action="{{ $view->action }}">
        {{ method_field($view->method) }}
        {{ csrf_field() }}
        ...
    </form>
@endsection

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay