Giter Club home page Giter Club logo

laravel-elements's Introduction

Latest Version on Packagist Total Downloads Build Status StyleCI

Elements

Elements is an Eloquent-like model wrapper based on the Entity--Attribute--Value model with powerful additional features that lets developers forget about database schemas, migrations, pivot tables, foreign keys and validation and focus on what matters - functionality.

Design Principals

  • Take schema declaration and value type checking away from the database layer.
  • Have fluent, expressive, editable schema declarations in code instead of migrations.
  • Provide strong typing checking for attributes.
  • Support locales, versioning, searching and validation.
  • Facilitate and eloquent-like syntax where possible.
  • Allow binding to models with optional two-way synchronisation.
  • Give much better exception handling options to developers.
  • Not interfere with any existing application setup.

What is EAV?

Entity–attribute–value model (EAV) is a data model to encode, in a space-efficient manner, entities where the number of attributes (properties, parameters) that can be used to describe them is potentially vast, but the number that will actually apply to a given entity is relatively modest.

-- Wikipedia

Installation

Via Composer

$ composer require click/elements  

Laravel 5.5+

Sit back and relax. You've done too much already. The package will auto-register after composer runs. ⛵️

Laravel 5.4 & below

Add this to your config/app.php file under providers.

Click\Elements\ElementsServiceProvider::class,

If you want to use the Elements facade then add this to your config/app.php file under aliases.

'Elements' => Click\Elements\Facades\Elements::class,

Usage

Creating Element Types

$ php artisan make:element MyElement

A fresh element class will be dropped somewhere like app\Elements\MyElement.php looking something like this.

<?php  
  
namespace App\Elements;  
  
use Click\Elements\Element;
use Click\Elements\Exceptions\PropertyKeyInvalidException;
use Click\Elements\Schemas\ElementSchema;
  
class MyElement extends Element  
{  
    /**  
     * Define the schema for the MyElement element.  
     *  
     * @param Schema $schema  
     * @return void  
     */  
    public function getDefinition(ElementSchema $schema)  
    {  
        //$schema->string('title');  
        //$schema->boolean('inStock');  
        //$schema->integer('quantity');  
        //$schema->double('price');  
        //$schema->text('description');  
        //$schema->array('tags');  
        //$schema->json('settings');  
        //$schema->relation('author');  
        //$schema->timestamp('shippedAt');  
    }  
}  

You can generate elements for use with two-way binding by specifying a model class when using the make:element command.

$ php artisan make:element MyElement --model=App\\MyModel

Using Elements in your Application

Elements try to replicate the functionality of Eloquent models where possible to make the developer experience as familiar as possible. A custom query builder is provided which allows you to query properties and relationships as you'd expect.

<?php

class Author extends Element
{
    public function getDefinition(ElementSchema $schema)  
    {  
        $schema->string('name')->validation([
            'min' => '3',
            'exists:users,name'
        ]);
    }
}

class Book extends Element
{
    public function getDefinition(ElementSchema $schema)  
    {  
        $schema->string('title')->validation('required');
        $schema->integer('published')->validation('required');
        $schema->relation('author')->validation('required');
    }
}

Creating new elements is much the same as Eloquent models, but assigning relationships is a little different.

<?php

$author = Author::create([
    'name' => 'Neal Stephenson'
]);

$book = Book::create([
    'title' => 'Snow Crash',
    'published' => 1992,
    'author' => $author
]);

Fetching elements is quite similar to Eloquent models too, but querying relationships is a little different.

<?php

// Get all elements
$books = Book::all();

// Eager load a relation property
$books = Book::with('author')->get();

// Where property
$books = Book::where('published', '>', 1991)->get();

// Where relation property
$books = Book::where('author.name', 'like', '%neal%')->get();

Two-way Binding

You can enable an optional two-way binding to Eloquent models. Simply define a getModel() method and $syncToModel and $syncFromModel attributes on your element to have changes to either the element or model be replicated to the other.

<?php

use App\MyModel;
  
class MyElement extends Element  
{  
    use TwoWayBinding;
    
    // Update the model when the element is updated
    protected $syncToModel = true;

    // Update the element when the model is updated
    protected $syncFromModel = true;
  
    public function getModel()  
    {  
        return MyModel::class;  
    }  
}  

This behaviour is dependent on eloquent events being triggered on both your own and the internal element models to function property.

A call to YourModel::delete() for example will not trigger any related elements to delete. See deleting models in the Laravel documentation for more info.

You can specify the mappings between model attributes and element properties by defining mapForModel() and mapForElement() methods on your element.

<?php

class MyElement extends Element  
{
    public static function mapForModel(Element $element)
    {
        return [
            'model_attribute' => $element->elementProperty
        ];
    }
    
    public static function mapForElement(MyModel $model)
    {
        return [
            'elementProperty' => $model->model_attribute
        ];
    }
}  

Elements use a strict type system so make sure to cast each attribute to the expected type before assigning it to the property.

Bring your own data

You likely have existing data in your application that you want to synchronise. To do this, create element classes for models you want to import, defining mappings in the mapForElement() method described above, and then run the import command to create elements from your models.

$ php artisan elements:import

Change log

Please see the changelog for more information on what has changed recently.

Testing

$ composer install && vendor/bin/phpunit  

Contributing

Please see contributing.md for details and a todolist.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

Proprietary. Please see the license file for more information.

laravel-elements's People

Contributors

adamdburton avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.