Giter VIP home page Giter VIP logo

presenter's Introduction

Easy View Presenters

So you have those scenarios where a bit of logic needs to be performed before some data (likely from your entity) is displayed from the view.

  • Should that logic be hard-coded into the view? No.
  • Should we instead store the logic in the model? No again!

Instead, leverage view presenters. That's what they're for! This package provides one such implementation.

Install

Pull this package in through Composer.

{
    "require": {
        "laracasts/presenter": "0.1.*"
    }
}

Usage

The first step is to store your presenters somewhere - anywhere. These will be simple objects that do nothing more than format data, as required.

Here's an example of a presenter.

use Laracasts\Presenter\Presenter;

class UserPresenter extends Presenter {

    public function fullName()
    {
        return $this->first . ' ' . $this->last;
    }

    public function accountAge()
    {
        return $this->created_at->diffForHumans();
    }

}

Next, on your entity, pull in the Laracasts\Presenter\PresentableTrait trait, which will automatically instantiate your presenter class.

Here's an example - maybe a Laravel User model.

<?php

use Laracasts\Presenter\PresentableTrait;

class User extends \Eloquent {

    use PresentableTrait;

    protected $presenter = 'UserPresenter';

}

That's it! You're done. Now, within your view, you can do:

    <h1>Hello, {{ $user->present()->fullName }}</h1>

Notice how the call to the present() method (which will return your new or cached presenter object) also provides the benefit of making it perfectly clear where you must go, should you need to modify how a full name is displayed on the page.

Have fun!

Jeffrey @ https://laracasts.com

presenter's People

Contributors

grahamcampbell avatar imerfanahmed avatar jeffreyway avatar laravel-shift avatar michaeldyrynda avatar rdarcy1 avatar sdebacker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

presenter's Issues

Accepting improvements? (Better fallback to model's properties)

Since this is example code for a tutorial, I'm guessing you might be trying to keep the code matching what you did in the cast. However, if you are open to improvements, I'd love to submit a pull request for some or all of these features:

  1. If the presenter can't match the property requested to a property on the model, it should see if a snake case version of the property is available. $post->present()->createdAt would return $post->created_at. This allows us to use snake case in our database, but keep camel case in our view.
  2. Throw an exception if you try to access a property that is not a presenter method or a model property. Currently it just returns an empty string, which I don't think is the expected response.
  3. Allow the user to omit the () in ->present(). i.e. $post->present->created_at.

Presenters and Eloquent relationships

Hi ! Thanks for this package.

I have difficulties in using the presenters with an eloquent relationship.

Let me explain, when, for example I retrieve users and their profiles in this way:

Route::get('/', function() {
    $users = MyProject\Entities\User::take(10)->with('profile')->get();

    foreach ($users as $user) {
        echo $user->profile()->present()->fullName;
    }
});

I got an error: Call to undefined method Illuminate\Database\Query\Builder::present()

Am I missing something ?

Thanks !

column status cannot read

This is my Presenter

if($this->status == 'pending'){ 
     echo '<span class="label label-teal"><span class="ico-file"></span> PENDING</span>';
}

i can call others column like
$this->id
$this->employee_id

but when i called $this->status it give me an error

ErrorException (E_UNKNOWN) 
Undefined property: RequisitionPresenter::$status 

this is my table

                        $table->increments('id'); 
            $table->integer('employee_id');  
            $table->timestamps();
            $table->integer('created_by');
            $table->integer('updated_by'); 
            $table->string('status')->default('pending');
            $table->datetime('status_at');
            $table->integer('status_by');
            $table->text('status_notes'); 

Please set the $presenter property to your presenter path.

My Model :

<?php

namespace App\Models;
use App\Presenters\InventoryOutProductPresenter;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Laracasts\Presenter\PresentableTrait;

class InventoryOutProduct extends Model 
{
    use HasFactory,PresentableTrait;
    protected $presenter = InventoryOutProductPresenter::class;
   
}

My Presenter :

<?php
namespace App\Presenters;
use Laracasts\Presenter\Presenter;

class InventoryOutProductPresenter extends Presenter {

    public function product_text_format()
    {
        return $this->title.'('.$this->price_per_qty.')';
    }

}

Call : $model->present()->product_text_format;

Using Presenter with lists() method

I am attempting to use the Laracasts Presenter with the lists() method like so:

$physicians = Employee::physician()->get()->lists(<formattedName>, 'id');
// <formattedName> would be the column name of the employee's name.
// Since it is stored as first and last separately, I use the Laracasts Presenter to present the concatenated full name.

I have a namespaced Employee model, and a query scope to filter the query results. My issue is, without calling the present() method, I can't access my presenter method for formatting the name. I can not find a place to insert the present() method that makes the lists() method work properly. Has anyone done this before?

My current workaround was setting a custom getter on the model to get the concatenated full name that way, but I would like to use the presenter method I already wrote if that is possible.

Would you consider supporting DI for the presenters?

With many other presenter packages out there, I keep coming back to this one for its simplicity and flexibility (others seem to limit themselves to much more restricted use-cases).

Anyway, tried adding a service to a presenter constructor, since the service contains functionality used across a number of the presenter methods:

public function __construct($entity, protected OrderService $orderService)
{
    parent::__construct($entity);
}

This did not work, as the additional parameter was not being set in PresentableTrait:

$this->presenterInstance = new $this->presenter($this);

So this tried this in PresentableTrait instead, and it worked a treat:

$this->presenterInstance = app()->make($this->presenter, ['entity' => $this]); 

Now my order presenter class has $this->orderService at its disposal.

Now, I know I can extend the trait with this fix (or something similar - this is first draft to check viability) for myself, but is this something that could be useful for this package? It should be possible for it to work across all the supported Laravel versions.

Having to include $entity to pass up to the parent is, unfortunately, a little messy.

Traits instead of presenter

Why don't we rather use Traits for this?

Than we could have multiple "prester-traits" and it would still be nicely clean.

And it is very annoying to keep writing $model->present()->something.

Some help with namespaced entities

I have

composer.json
"autoload": {
        "psr-4": {
            "BMTracking\\": "app/BMTracking"
        }
    }
/app/BMTracking/Entities/Question.php
<?php namespace BMTracking\Entities;

use Laracasts\Presenter\PresentableTrait;

class Question extends \Eloquent {

    use PresentableTrait;

   /**
     * @var string
     */
    protected $presenter = 'BMTracking\Preseters\QuestionPresenter';
/app/BMTracking/Presenters/QuestionPresenter.php
<?php namespace BMTracking\Presenters;

use Laracasts\Presenter\Presenter;

class QuestionPresenter extends Presenter {

    public function company()
    {
        return $this->company->name;
    }

    public function group()
    {
        return $this->groups{$this->entity->for};
    }

    public function frequency()
    {
        return $this->frequencies{$this->entity->frequency};
    }

    public function type()
    {
        return $this->types{$this->entity->type};
    }

}

And I receive

Please set the $presenter property to your presenter path. (View: /app/views/questions/index.blade.php)

The view is a simple foreach

@foreach ($questions as $question)
            <tr>
                <td>{{ $question->text }}</td>
                <td>{{ $question->present()->company }}</td>
                <td>{{ $question->present()->group }}</td>
                <td>{{ $question->present()->for_id }}</td>
                <td>{{ $question->sort }}</td>
                <td>{{ $question->active }}</td>
                <td>{{ $question->present()->frequency }}</td>
                <td>{{ $question->present()->type }}</td>
            </tr>
        @endforeach

Whant am I doing wrong? How can I track if the presenter class is loaded?

Can't use function name in Presenter which is equal to the name of the property

It seems like something has changed with Laravel 5.

Currently I'm not able to use a function name which is equal to the name of the property.
So this is not working and I can't figure it out why

public function description()
{
    return $this->description;
}

This will throw an Undefined property: App\Presenter\ApplicationPresenter::$description

The only way I could get this to work is by using a different method name

public function getDescription()
{
    return $this->description;
}

or referencing the property like this

public function description()
{
    return $this->entity->description;
}

Am I doing something wrong or is this a bug in interaction with Laravel 5 ?

can't set method name as filed name?

I create

use Laracasts\Presenter\Presenter;

class StaffPresenter extends Presenter
{
    public function dob()
    {
        return $this->dob;
    }

}

I get error, but when i change method name it is ok.
I think that, it could do

presenter on cached data.

Hi there ,first big thanx for this super easy/handy package.

i currently have something like

public function Creation_time() {
    return $this->created_at->diffForHumans();
}

which works great but once i use

$posts = Post::remember('all', 60)->paginate(12);

i get this error

Call to a member function diffForHumans() on null

which i think its because am no longer making a request to the server so now the $this doesn't refer to anything + the result is within a key all (which is made so i can clear the Cache in case of new data),

so how can i make the presenter work with the above ?

problem with "->present()->.........."

I create Presenters folder in workbench..., and then i create StaffPresent and pull it to StaffModel via docs help.
But when i call ->present()->....., it show error
Please set the $presenter property to your presenter path.

Install instructions

I think the installation instructions for the Laravel 5 compatible versions need to change to reference 0.2.*
"laracasts/presenter": "0.2.*"

access to relationship model from presenter

Hi guys i don't know why but if inside the presenter class i try to access like a method on relationship model

$this->relations()->count()

i get an error message on method 'Call to undefined method'. Why ?

Model attributes

For some reason I am unable to have model attributes the same name as a presenter method.

Presenter Snippet

class AuthorPresenter extends Presenter
{
    /**
     * Returns the author's full name, if a pen name
     * is not set.
     *
     * @return string
     */
    public function pen_name()
    {
        if ($this->pen_name) {
            return $this->pen_name;
        }

        return $this->user->name;
    }
}

View Snippet

<div class="author">by {{ $book->author->present()->pen_name() }}</div>

Error Returned

Undefined property: AuthorPresenter::$pen_name

had to add $this->entity->attr

In my presenter, to access the wrapped object's attribute I had to do it like:
image
In the example you are just doing $this->attr.. but it throws an exception because the attribute doesnt exist in $this, but in $this->entity

Troubles pulling this in via Composer

Hello,

Love this package! Trouble is, it is annoying to pull in.

I have a blank Laravel app installed but I have to change my minimum-stability in my composer.json file to pull this package in as a dependency.

Problem with that is, it changes my Laravel version to the bleeding-edge version...

Can't I use the stable version of Laravel with this package?

Support for multiple presenters

I could imagine the present() method of the PresentableTrait accepting a parameter specifying the Presenter I want to use. I might have different Presenters for each Model for Ajax, Forms, Backend, Frontend etc.

Thoughts?

Can't install with Laravel 4.2

$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

Problem 1
- Conclusion: remove laravel/framework 4.2.x-dev
- laracasts/presenter 0.1.0 requires illuminate/support 4.1.* -> satisfiable by laravel/framework[4.1.x-dev], illuminate/support[4.1.x-dev, v4.1.0, v4.1.1, v4.1.10, v4.1.11, v4.1.12, v4.1.13, v4.1.14, v4.1.15, v4.1.16, v4.1.17, v4.1.18, v4.1.19, v4.1.2, v4.1.20, v4.1.21, v4.1.22, v4.1.23, v4.1.24, v4.1.25, v4.1.26, v4.1.27, v4.1.28, v4.1.3, v4.1.4, v4.1.5, v4.1.6, v4.1.7, v4.1.8, v4.1.9].

....

- don't install illuminate/support v4.1.9|don't install laravel/framework 4.2.x-dev
- Installation request for laravel/framework 4.2.* -> satisfiable by laravel/framework[4.2.x-dev].
- Installation request for laracasts/presenter 0.1.*@dev -> satisfiable by laracasts/presenter[0.1.0, 0.1.1, 0.1.2, 0.1.3].

Using a constructor in the Presenter Class

I have an Owner Model and an OwnerPresenter class. 'Standard' functionality os working fine. I am now trying to do something in a presenter part of which I will use in other presenters (but not all) so would like to utilise DI using a constructor in my Presenter Class. I get the following error:

Argument 1 passed to Owners\OwnerPresenter::__construct() must be an instance of Utilities\AddressBuilder, instance of Owners\Owner given, called in /home/vagrant/project1/vendor/laracasts/presenter/src/Laracasts/Presenter/PresentableTrait.php on line 29 and defined (View: /home/vagrant/project1/app/views/search.blade.php)

I have tried adding parent::_construct and parent::_construct($this->entity) but I am getting the same error.

I can see that there is a conflict with the constructors but struggling to work out how to solve it

Cannot use underscore for attributes

Hi,

I'm trying to do something like

$post->present()->created_at

I have a created_at function in my presenter class. But somehow it doesn't work. It works if I named my created_at as createdAt though.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.