Skip to content

Instantly share code, notes, and snippets.

@artygrand
Last active May 29, 2017 10:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save artygrand/1bbca0a8f091a17b4fcc18cd83cbda8b to your computer and use it in GitHub Desktop.
Save artygrand/1bbca0a8f091a17b4fcc18cd83cbda8b to your computer and use it in GitHub Desktop.
Repo - entity - fields
<?php
namespace Module\Entity\Models;
use Sydes\Database;
use Sydes\PDO;
class Repository
{
/** @var PDO */
protected $db;
/** @var Entity */
protected $model;
/** @var PDO */
protected $result;
public function __construct(Database $db)
{
$this->db = $db;
}
/**
* @param string $model Model name
* @return $this
*/
public function forModel($model)
{
$this->model = model($model);
$this->db = $this->db->connection($this->model->getConnection());
return $this;
}
/**
* @return Entity
*/
public function getModel()
{
return $this->model;
}
/**
* Creates table from entity fields
*/
public function makeTable()
{
$table = $this->model->getTable();
$fields = $this->model->getFields();
if ($this->model->hasLocalized()) {
$cols = [
"entity_id INTEGER NOT NULL REFERENCES {$table}(id) ON DELETE CASCADE",
'locale TEXT NOT NULL',
];
foreach ($this->model->getLocalized() as $col) {
$cols[] = $fields[$col]->getSchema();
unset($fields[$col]);
}
$cols[] = 'UNIQUE (entity_id, locale)';
$this->db->exec("CREATE TABLE {$table}_localized (\n".implode(",\n", $cols)."\n)");
}
$cols = [
$this->model->getPk().' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT',
];
foreach ($fields as $field) {
$cols[] = $field->getSchema();
}
if ($this->model->usesTimestamps()) {
$cols[] = 'created_at INTEGER';
$cols[] = 'updated_at INTEGER';
}
$this->db->exec("CREATE TABLE {$table} (\n".implode(",\n", $cols)."\n)");
if ($this->model->usesEav()) {
$this->db->exec("CREATE TABLE {$table}_eav (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
entity_id INTEGER NOT NULL REFERENCES {$table}(id) ON DELETE CASCADE,
key TEXT NOT NULL,
value TEXT,
UNIQUE (entity_id, key)\n)");
}
}
/**
* Removes table for this entity
*/
public function dropTable()
{
$table = $this->model->getTable();
if ($this->model->hasLocalized()) {
$this->db->drop($table.'_localized');
}
if ($this->model->usesEav()) {
$this->db->drop($table.'_eav');
}
$this->db->drop($table);
}
/**
* @param mixed $criteria
* @param array $cols
* @param array $opts
* @return $this
*/
public function find($criteria, array $cols = ['*'], $opts = [])
{
if (is_numeric($criteria)) {
$criteria = ['id', $criteria];
}
// если $criterion[0] не поле и не мета, искать id в локализованных или еав
// найдя id
// или иначе, получить данные со всех таблиц
$this->result = $this->db->select($this->model->getTable(), $cols, $criteria, $opts);
return $this;
}
public function first()
{
$model = clone $this->model;
$item = $this->result->first();
return $model->fill($item)->withProps($item);
}
public function all()
{
$results = [];
foreach ($this->result->all() as $item) {
$model = clone $this->model;
$results[] = $model->fill($item)->withProps($item);
}
return $results;
}
public function save(Entity $entity)
{
}
public function destroy(Entity $entity)
{
}
public function __call($name, $args) {
if (substr($name, 0, 6) == 'findBy') {
$field = strtolower(substr($name, 6));
if (!isset($args[1])) {
$args[1] = ['*'];
}
return $this->find([$field, $args[0]], $args[1]);
}
throw new \InvalidArgumentException('Wrong method '.$name);
}
}
<?php
namespace Module\Entity\Models;
use Module\Fields\Plugin\Fields\FieldInterface;
abstract class Entity
{
protected $connection = 'site';
protected $table;
protected $primaryKey = 'id';
protected $timestamps = true;
protected $eav = false;
protected $localized = [];
protected $fields = [];
protected $attributes = [];
protected $data = [];
/**
* Entity constructor.
*
* @param array $attrs
*/
public function __construct(array $attrs = [])
{
$this->fill($attrs);
}
/**
* @param array $attrs
* @return $this
*/
public static function create(array $attrs)
{
return new static($attrs);
}
/**
* @param array $attrs
* @return $this
*/
public function fill(array $attrs)
{
foreach (array_intersect_key($attrs, $this->fields) as $key => $value) {
$this->data[$key] = $value;
}
return $this;
}
/**
* @param array $props
* @return $this
*/
public function withProps(array $props)
{
foreach (array_intersect_key($props, [
$this->primaryKey => 1,
'status' => 1,
'created_at' => 1,
'updated_at' => 1,
]) as $key => $value) {
$this->data[$key] = $value;
}
return $this;
}
/**
* @param string $name
* @return FieldInterface
*/
public function getField($name)
{
if (!isset($this->attributes[$name])) {
$this->initField($name);
}
return $this->attributes[$name];
}
/**
* @param string $name
*/
protected function initField($name)
{
$class = app('formFields')[$this->fields[$name]['type']];
$this->attributes[$name] = new $class($name, $this->data[$name], $this->fields[$name]['settings']);
}
/**
* @return array
*/
public function toArray()
{
return $this->data;
}
/**
* @return string
*/
public function getTable()
{
if ($this->table) {
return $this->table;
} else {
$name = get_class($this);
return snake_case(($pos = strrpos($name, '\\')) ? substr($name, $pos + 1) : $name).'s';
}
}
/**
* @param mixed $table
*/
public function setTable($table)
{
$this->table = $table;
}
/**
* @return array
*/
public function getFields()
{
return $this->fields;
}
/**
* @param array $fields
*/
public function setFields($fields)
{
$this->fields = $fields;
}
/**
* @return string
*/
public function getConnection()
{
return $this->connection;
}
/**
* @param string $name
*/
public function setConnection($name)
{
$this->connection = $name;
}
/**
* @return bool
*/
public function usesTimestamps()
{
return $this->timestamps;
}
/**
* @return string
*/
public function getPk()
{
return $this->primaryKey;
}
/**
* @return bool
*/
public function usesEav()
{
return $this->eav;
}
/**
* @return bool
*/
public function hasLocalized()
{
return !empty($this->localized);
}
/**
* @return array
*/
public function getLocalized()
{
return $this->localized;
}
/**
* @param string $key
* @return FieldInterface
*/
public function __get($key)
{
return $this->getField($key)->render();
}
/**
* @param string $key
* @param mixed $value
*/
public function __set($key, $value)
{
$this->getField($key)->set($value);
}
/**
* @param string $key
* @return bool
*/
public function __isset($key)
{
return array_key_exists($key, $this->attributes);
}
/**
* @param string $key
*/
public function __unset($key)
{
$this->getField($key)->set('');
}
}
<?php
namespace Module\Test;
use Module\Entity\Models\Repository;
use Sydes\Route;
class Controller
{
public static function routes(Route $r)
{
$r->get('/admin/test', 'Test@index');
}
public function install(Repository $repo)
{
$repo->forModel('Test')->makeTable();
}
public function uninstall(Repository $repo)
{
$repo->forModel('Test')->dropTable();
}
public function index(Repository $repo)
{
$tests = $repo->forModel('Test')->find(['code', 'between', ['2', '4']])->all();
$d = document([
'content' => view('test/list', compact('tests')),
]);
return $d;
}
}
<?php
namespace Module\Test\Models;
use Module\Entity\Models\Entity;
class Test extends Entity
{
protected $fields = [
'code' => [
'type' => 'Text',
'settings' => [
'label' => 'test code',
'required' => true,
],
'position' => 1,
],
'name' => [
'type' => 'Text',
'settings' => [
'label' => 'test_name',
'required' => true,
],
'position' => 3,
],
'data' => [
'type' => 'Text',
'settings' => [
'label' => 'test_data',
'rows' => 12,
'required' => true,
],
'position' => 2,
],
];
protected $eav = true;
protected $localized = [
'name',
'data',
];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment