robclancy / presenter

Decorate your objects using presenters. Primarily to keep presentation logic out of your models.
MIT License
345 stars 38 forks source link

convert array of user presenter to json #18

Closed newtonianb closed 10 years ago

newtonianb commented 11 years ago

I'm trying to encode my user object to json so I can pass it to my javascript variable. The problem since it is getting converted to a UserPresenter in my view I'm having some issues.

For one user I can just do $user->getObject() and that get's properly encoded in my view however I have a problem when it's a collection or array of users (essentiall UserPresenters in the view), how would i do it in a clean way?

For one user I do $user->getObject()

$user = User::first();
$users = User::all();

<script>
var obj = {
    user: <?php echo $user->getObject(); ?>,
}
</script>

result

{"id":1,"first_name":"A","last_name":"A","birthday":"1970-02-12","gender":"M","username":"aa","email":"a@a.com","permissions":null,"activated":true,"activated_at":null}

However how do I do it if it's a collection of users?

$users = User::all();

<script>
var obj = {
    users:<?php echo $users; ?>,
}
</script>

result

users: [{},{}];

This is the only way I got it working but it's so nasty

<script>
var obj = {
    users: [<?php for($i = 0; $i < count($users); $i++) { echo $users[$i]->getObject(); if ($i + 1 < count($users)) { echo ','; } } ?>]
}
</script>

result

users: [{"id":1,"first_name":"A","last_name":"A","birthday":"1970-02-12","gender":"M","username":"aa","email":"a@a.com","permissions":null,"activated":true,"activated_at":null},{"id":2,"first_name":"b","last_name":"b","birthday":"1982-01-10","gender":"M","username":"bb","email":"b@b.com"}]
robclancy commented 11 years ago

Make yourself a base presenter and have it implement Illuminate\Support\Contracts\ArrayableInterface and make toArray() call $this->object->toArray(). Then you will just have to do echo $users;

So...

<?php namespace WhateverNamespace;

use Robbo\Presenter\Presenter;
use Illuminate\Support\Contracts\ArrayableInterface;

class Base extends Presenter implements ArrayableInterface {

    public function toArray()
    {
        // Should probably do some checks here for array, arrayable interface etc
        return $this->object->toArray();
    }
}

See if that works. Also don't close this issue, when I get time I will add in toJson, toArray and __toString, this will be my reminder.

newtonianb commented 11 years ago

Fantastic! That worked for the array of users thank you very much! Question though, why do I still have to do user: <?php echo $user->getObject(); ?>, for the one user? If I don't do getObject() I get. Object of class UserPresenter could not be converted to string

robclancy commented 11 years ago

For that one to work you need to implement __toString and toJson.

__toString() needs to simply call toJson() and toJson() needs to call $this->object->toJson()

newtonianb commented 11 years ago

Did I mention that you rock! Thank you

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

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

  public function toArray() {
    // Should probably do some checks here for array, arrayable interface etc
    return $this->object->toArray();
  }
hotmeteor commented 10 years ago

I'm trying to output JSON and include my presenter values, and I'm using these methods with a base presenter, but no dice. Does this still work with the latest version?