Skip to content

Instantly share code, notes, and snippets.

@arleighdickerson
Last active February 10, 2017 07:57
Show Gist options
  • Save arleighdickerson/ede810e8d2f000fcbf42 to your computer and use it in GitHub Desktop.
Save arleighdickerson/ede810e8d2f000fcbf42 to your computer and use it in GitHub Desktop.
Yii2 behavior to link a filesystem resource to an ActiveRecord instance
<?php
namespace common\models;
use yii\base\Behavior;
use yii\db\ActiveRecord;
use yii\web\UploadedFile;
/**
* @author: Arleigh Dickerson
*/
class FileSystemResource extends Behavior {
public $path;
public $attributeName;
private $file;
public function init() {
parent::init();
assert($this -> path != null);
assert($this -> attributeName != null);
}
public function events() {
return [
ActiveRecord::EVENT_AFTER_INSERT => 'afterSave',
ActiveRecord::EVENT_AFTER_UPDATE => 'afterSave',
ActiveRecord::EVENT_AFTER_DELETE => 'afterDelete', ];
}
public function afterSave($event) {
$this -> file = UploadedFile::getInstance($this -> owner, $this->attributeName);
if ($this -> file != null) {
$this->deleteFile();
$filename = $this -> path . $this -> owner -> id . '.' . $this -> file -> extension;
$this -> file -> saveAs($filename);
}
}
public function afterDelete($event) {
$this->deleteFile();
}
private function findFile() {
$files = glob($this -> path . $this -> owner -> id . '.*');
foreach ($files as $file) {
return $file;
}
return null;
}
private function deleteFile(){
$file = $this -> findFile();
if ($file != null) {
unlink($this -> file);
}
}
public function canGetProperty($name, $checkVars = true) {
return $name == $this -> attributeName || parent::canGetProperty($name, $checkVars);
}
public function canSetProperty($name, $checkVars = true){
return $name == $this -> attributeName || parent::canSetProperty($name, $checkVars);
}
public function __get($name) {
return $name == $this -> attributeName ? $this -> findFile() : parent::__get($name);
}
public function __set($name, $value) {
if ($name == $this -> attributeName) {
$this -> file = $value;
} else {
parent::__set($name, $value);
}
}
}
@arleighdickerson
Copy link
Author

I wrote this because I didn't want to deal with avatars as BLOBs in the database. Usage :
In ActiveRecord subclass:
class MyActiveRecordSubclass extends ActiveRecord {
//...//
public function behaviors() {
return [[
'class' => FileSystemResource::className(),
'path' => '/path/to/storage/dir/',
'attributeName' => 'whatevs']];
}
//...//
}
$model = new MyActiveRecordSubclass;
//....
$model->whatevs; //return the file or null if no file found

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment