Use Trait to override attributesToArray on Model

Posted 4 months ago by newSequence

I am attempting to override the attributesToArray method on Model.php for use in a trait I am using on another model, lets call it sale.php. I am doing this to decrypt attributes when converting to json. Essentially using a version of the encryptabletraits class that is floating around.

use Illuminate\Support\Facades\Crypt;
use Illuminate\Contracts\Encryption\DecryptException;

trait EncryptableTrait
{

  public function getAttribute($key)
  {
    $value = parent::getAttribute($key);
    if (in_array($key, $this->encryptable) && (!is_null($value))) {
        $value = Crypt::decrypt($value);
    }

    return $value;
  }

  public function setAttribute($key, $value)
  {
    if (in_array($key, $this->encryptable)) {
        $value = Crypt::encrypt($value);
    }

    return parent::setAttribute($key, $value);
  }

  public function attributesToArray() 
  {

    $attributes = parent::attributesToArray();

    foreach($this->getEncryptable() as $key) {

        if(array_key_exists($key, $attributes)) {
            try {
                $attributes[$key] = Crypt::decrypt($attributes[$key]);
            }
            catch(DecryptException  $e)
            {
                continue;
            }

        }
    }
    return $attributes;
  }

  protected function getEncryptable() {
    return property_exists($this, 'encryptable') ? $this->encryptable : [];
  }
}

Then in the sale class I use it like so:

class Sale extends SaleBase
{
   use EncryptableTrait;

   //these are just examples
   protected $encryptable = [
    'credit_card',
    'credit_card_pin'
   ];
   //lots of other stuff here
}

The issue is that attributesToArray in the trait is never called the Model method is; but if I pull that function out of the trait and place it directly in the sale class, it works. The sale class inheritance is probably stacked 5 or 6 classes deep before getting to the base Model class.

attributesToArray is not defined anywhere in sale or indeed anywhere else except in the trait and the base Model class.

How do I get it to work while keeping it in the trait? I don't want to put the attributesToArray function in Sale becuase I want to reuse the trait in other classes.

The getAttribute and setAttribute methods work from the trait without issue.

Please sign in or create an account to participate in this conversation.