8

When using Laravel's Eloquent ORM, I can't seem to set the $hidden and $visible properties on my Model dynamically.

Example 1: This works:

class User extends Eloquent {
   $this->visible = array('field_name');

   function read() 
   {
      return User::all();
   }
}

Example 2: Setting the visible property on the Eloquent Class dynamically, doesn't work:

class User extends Eloquent {
   function read($visible = array('field_name'))
   {
      $this->visible = $visible; // Also tried: $this->setVisible($visible);

      return User::all();
   }
}

Example 3: Solution that works on the Model itself, but not on eagerly loaded Models:

class User extends Eloquent {
   function read($visible = array('field_name'))
   {
      $users = User::all();

      return $users->get()->each(function($row) use ($visible) {
         $row->setVisible($visible);
      });
   }
}

In order to set the $visible property dynamically on Eagerly Loaded Models, I don't see another solution than to get Example 2 to work. But how?

Ronald Hulshof
  • 1,986
  • 16
  • 22
  • I am having the same problem.. Were you ever able to find a solution? – ipengineer Jun 07 '13 at 22:49
  • 1
    I just worked around this by doing a ->select() on the methods inside my model. http://stackoverflow.com/questions/16994253/laravel-eager-loading-load-only-specific-columns – ipengineer Jun 09 '13 at 03:21
  • When working with manyToMany relationships, that solution will require you to select the relational columns. If you don't, the query will fail. It's expected behavior, but not desired in my case. – Ronald Hulshof Jun 11 '13 at 11:14
  • Is `Project` another Eloquent model? Are you attempting to [build a relationship](http://laravel.com/docs/eloquent#relationships) between User and Project? – fideloper Jul 09 '13 at 16:14
  • @fideloper This was just a typo. It's fixed in my original answer. It's not another Model. – Ronald Hulshof Oct 09 '13 at 14:42
  • in Example 1: the declaration should look like this: protected $visible = ['field_name']; – Yevgeniy Afanasyev Jul 11 '16 at 01:00

3 Answers3

2

As $visible is set on an instance level (i.e. it's not a static variable shared between all models of the same type), no - there's no better way to do this.

Andreas
  • 7,991
  • 2
  • 28
  • 37
2

This is something I invent for this purpose:

  use Illuminate\Database\Eloquent\Model;

  /*
   * trait allows to use a single method:
   *      getSerialized
   * this function works as the following method:
   *      Illuminate\Database\Query\Builder::get(), 
   * and also returns the collection
   * but accepts a parameter of an array type
   * like that
   *      $records = Table1::getSerialized([
   *               'appends' => ['calc_field1', 'calc_field2'],
   *               'hidden' => ['field1', 'field2', 'field3'],
   *               'visible' => ['id', 'name', 'calc_field1', 'calc_field2'],
   *           ]);
   * 
   * the returned collection accords with params 
   * read more in Laravel documentation
   *      https://laravel.com/docs/5.1/eloquent-serialization
   */

  trait Serialization
  {
  // scope filters ---------------------------------------------------------         
      private static $staticAppends;
      private static $staticHidden;
      private static $staticVisible;

      public function __construct(array $attributes = []){
          parent::__construct($attributes);
          if (isset(self::$staticAppends)){
              $this->appends = self::$staticAppends;
          }
          if (isset(self::$staticHidden)){
              $this->hidden = self::$staticHidden;
          }
          if (isset(self::$staticVisible)){
              $this->visible = self::$staticVisible;
          }

      }

      public function scopeGetSerialized($query, array $params){

          if (isset(self::$staticAppends)){
              $staticAppends = self::$staticAppends;
          } else {
              $staticAppends = [];
          }
          if (isset(self::$staticHidden)){
              $staticHidden = self::$staticHidden;
          } else {
              $staticHidden = [];
          }
          if (isset(self::$staticVisible)){
              $staticVisible = self::$staticVisible;
          }else {
              $staticVisible = [];
          }

          if (isset($params['appends'])){
              self::$staticAppends = $params['appends'];
          }
          if (isset($params['hidden'])){
              self::$staticHidden =  $params['hidden'];
          }
          if (isset($params['visible'])){
              self::$staticVisible =  $params['visible'];
          }

          $res = $query->get();

          self::$staticAppends = $staticAppends;
          self::$staticHidden = $staticHidden;
          self::$staticVisible = $staticVisible;
          return $res;
      }
  }
Yevgeniy Afanasyev
  • 37,872
  • 26
  • 173
  • 191
0

You can try to only select those properties from the query directly if you are intending to only use those attributes.

User::select(['id', 'field_name_1'])->get();
nelson6e65
  • 917
  • 11
  • 14