The given solution does not work when using a package that does a lot of the work after you define the with()
relations like datatables
here is a solution that works for any model.
<?php
namespace App\Database;
trait Appendable {
static protected $static_appends = [];
static protected $static_replace_appends = null;
/**
* set a static appends array to add to or replace the existing appends array..
* replace => totally replaces the existing models appends array at time of calling getArrayableAppends
* add => merges and then makes unique. when getArrayableAppends is called. also merges with the existing static_appends array
*
* @param $appendsArray
* @param bool $replaceExisting
*/
public static function setStaticAppends($appendsArray, $replaceExisting = true)
{
if($replaceExisting) {
static::$static_replace_appends = true;
static::$static_appends = array_unique($appendsArray);
} else {
static::$static_replace_appends = false;
static::$static_appends = array_unique(array_merge(static::$static_appends,$appendsArray));
}
}
/**
* Get all of the appendable values that are arrayable.
*
* @return array
*/
protected function getArrayableAppends()
{
if(!is_null(static::$static_replace_appends)) {
if(static::$static_replace_appends) {
$this->appends = array_unique(array_merge(static::$static_appends,$this->appends??[]));
} else {
$this->appends = static::$static_appends;
}
}
return parent::getArrayableAppends();
}
}
then you can just apply the trait to any model
<?php
namespace App\Database;
abstract class Company
{
use Appendable;
}
then call the static method BEFORE you use the relationship
<?php
$replaceCurrentAppendsArray = true;
// this will remove the original appends by replacing with empty array
\App\Database\Company::setStaticAppends([],$replaceCurrentAppendsArray);
$replaceCurrentAppendsArray = true;
// this will remove the original appends by replacing with smaller array
\App\Database\Company::setStaticAppends(['thumbnail_url'],$replaceCurrentAppendsArray);
$replaceCurrentAppendsArray = FALSE;
// this will add to the original appends by providing an additional array element
\App\Database\Company::setStaticAppends(['my_other_attribute'],$replaceCurrentAppendsArray);
this will allow you to override the appends array provided on the model even if another package is going to be loading the model. Like yajra/laravel-datatable
where my issue was and brought me to this page which inspired a more dynamic solution.
This is similar to Stefan's second approach, but this is more dynamic so you do not have to create additional model extensions to accomplish the overrides.
You could take a similar approach to override the HidesAttribute
trait as well.
This is perfect! Big thanks for writing this. Here's how I used it:
I need to get competitor details linked to a User, but there are loads of stats details that are pulled using custom attributes that I don't normally want in the appends array. They're only useful on the profile page because they will slow down other queries where I just want the basic competitor info.
So, when I eager load the competitor relationship on the user profile request, I needed to specify that I want the stats too... bingo!
UserController.php
Competitor.php