John Main Logo

John Main

Code. Design. Hosting. Maintenance.

25
Jul '18

I know I know. Rely too much on traits and you’re asking for trouble. But when used correctly, for self-contained bolt-on functionality they really can be fantastic and save loads of time.

There only condition for this logic is that any record with which you are using this must have a ‘logo’ field. Yeah I know I could have done a more advanced version with a separate logo table and a polymorphic relationship, but it’s not like a standard system will have 2 dozen records that all require logos against them so I’ve kept it simple.

I’ve used the word ‘logo’ here, but it’s a generic image storing trait and could be used for anything. You’ll also notice an optional config option of ‘app.directory.logo’, which, if provided, will be used as a relative path below the application’s public folder, otherwise ‘/logos’ will be used.

This assumes that you have an image referenced as ‘logo_file’ in your request and have triggered a save on the parent record.

namespace App\Trt;
trait Logo
{
/**
* Custom boot method
*/
public static function bootLogo()
{
/*
* Trigger on save
*/
static::saved(function ($record) {
try {
if(request()->hasFile('logo_file') && request()->file('logo_file')->isValid()) {
$logo_file = request()->file('logo_file');
$logo_folder = public_path(config('app.directory.logo', '/logos'));
if(is_dir($logo_folder) && is_writable($logo_folder)) {
//Prepending the record ID to ensure uniqueness
//Could also prepend parent record type / sanitised model name if it's to be used for multiple records
$file_name = $record->id . '_' . $logo_file->getClientOriginalName();
$record->clearLogo(false);
if($logo_file->move($logo_folder, $file_name)) {
$record->logo = $file_name;
//Direct update here so we don't trigger any callbacks
\DB::table($record->getTable())->where('id', $record->id)->update(['logo' => $file_name]);
}
}
else {
\Log::error('Logo folder is not writable ' . $logo_folder);
}
}
elseif(request()->clear_logo) {
$record->clearLogo();
}
}
catch(\Exception $e) {
}
});
/*
* Trigger on delete
*/
static::deleting(function ($record) {
$record->clearLogo(false);
});
}
/**
* Check for logo
* @return boolean
*/
public function hasLogo() {
return ($this->logo && is_file($this->logoPath()));
}
/**
* Logo URL
* @return string|false
*/
public function logoURL() {
return $this->logo ? url(config('app.directory.logo', '/logos') . '/' . $this->logo) : false;
}
/**
* Logo Path
* @return string|false
*/
public function logoPath() {
return $this->logo ? public_path(config('app.directory.logo', '/logos') . '/' . $this->logo) : false;
}
/**
* Clear Logo
* @param boolean [$save=true] Save
* @return boolean
*/
public function clearLogo($save = true) {
if($this->logo) {
if($this->hasLogo())
unlink($this->logoPath());
$this->logo = null;
if($save)
$this->save();
return true;
}
return false;
}
}

And that’s it!