Thanks to visit codestin.com
Credit goes to github.com

Skip to content

jarektkaczyk/eloquence

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sofa/Eloquence

Build Status Code Quality Downloads

Useful extensions for the Eloquent ORM.

🚧 WIP currently available extensions: Mappable and Formattable. For the time being, package does not follow semver.

If you want to know more about new extensions you can check our Roadmap!

Table of Contents

Team Members

Requirements

  • This package requires PHP 5.4+

Getting Started

  1. Require the package in your composer.json:

        "require": {
            ...
            "sofa/eloquence": "~0.3@dev",
            ...
        },
    
    
  2. Add Eloquence trait to the model - it's entry point for other extensions and is required for them to work.

  3. Add other traits, that you want to use.

Mappable

Define mappings on the protected $maps variable like bellow. Use this extension in order to map your 1-1 relations AND/OR simple column aliasing (eg. if you work with legacy DB with fields like FIELD_01 or somereallyBad_and_long_name - inspired by @treythomas123)

<?php namespace App;

use Sofa\Eloquence\Eloquence; // base trait
use Sofa\Eloquence\Mappable; // extension trait
use Sofa\Eloquence\Contracts\Mappable as MappableContract; // interface

class User extends \Eloquent implements MappableContract {

    use Eloquence, Mappable;

    protected $maps = [
      // implicit relation mapping:
      'profile' => ['first_name', 'last_name'],

      // explicit relation mapping:
      'picture' => 'profile.picture_path',

      // simple alias
      'dev_friendly_name' => 'badlynamedcolumn',
    ];

    public function profile()
    {
      return $this->belongsTo(Profile::class);
    }

You can also add mapped attributes to the array representation of your model, just like any accessor:

    protected $maps = [
      'picture' => 'profile.picture_path'
    ];

    protected $appends = ['picture'];

You can get, as well as set, mapped attributes:

$user->profile->first_name; // 'Jarek Tkaczyk'
$user->first_name = 'John Doe';

$user->profile->first_name; // 'John Doe'

// remember to save related model in order to persist the changes:
$user->profile->save();
// or simply use push:
$user->push();

You can also query the mappings:

// simple alias
User::where('dev_friendly_name', 'some_value')->toSql();
// select * from users where badlynamedcolumn = 'some_value'

// relation mapping
User::where('first_name', 'Romain Lanz')->toSql(); // uses whereHas
// select * from users where (
//   select count(*) from profiles
//    where users.profile_id = profiles.id and first_name = 'Romain Lanz'
// ) >= 1

Explicit vs. Implicit mappings

Mappable offers 2 ways of defining mappings for your convenience.

Let's compare equivalent mappings:

// Assuming User belongsTo Profile
// and Profile hasOne Picture
// profiles table: id, first_name, last_name
// pictures table: id, profile_id, path


// User model
// explicit
protected $maps = [
  'first_name'   => 'profile.first_name',   // $user->first_name
  'last_name'    => 'profile.last_name',    // $user->last_name
  'picture_path' => 'profile.picture.path', // $user->picture_path
];

// implicit
protected $maps = [
  'profile'         => ['first_name', 'last_name'], // $user->first_name / ->last_name
  'profile.picture' => ['path'],                    // $user->path
];

As you can notice, behaviour is just the same. However, there is slight difference - explicit mapping offers more flexibility, in that you can define custom key for mapped value (picture_path), while with implicit mapping you have to use real attribute name defined in the related model (path).

Mappings work also with form model binding.

Important: Mind that each mapping call requires the relation to be loaded, so you may need to use eager loading in order to avoid n+1 query issue.

Formattable

Define format on the protected $formats variable like bellow.

<?php namespace App;

use Sofa\Eloquence\Eloquence; // base trait
use Sofa\Eloquence\Formattable; // extension trait

class User extends \Eloquent {

    use Eloquence, Formattable;

    protected $formats = [
        // internal or global functions
        'first_name' => 'strtolower|ucwords',
        'last_name'  => ['strtolower', 'ucwords'],

        // static methods
        'slug'       => 'Illuminate\Support\Str::slug',

        // instance methods
        'short_name' => 'clip',

        // passing additional parameters
        'substring'  => 'substr:0,5',
    ];

    public function clip($string)
    {
      return substr($string, 0, 12) . '...';
    }
}
$user->first_name = 'john';
$user->first_name; // 'John'

$user->last_name = 'doe';
$user->last_name; // 'Doe'

$user->slug = 'Awesome package!';
$user->slug; // 'awesome-package'

$user->short_name = 'I\'m really too long for this attribute!';
$user->short_name; // 'I\'m really t...'

$user->substring = 'shorten me to 5 letters';
$user->substring; // 'short'

Mixing extensions

Feel free to mix the extensions, however mind that the order of including traits matters.

<?php namespace App;

use Sofa\Eloquence\Eloquence; // base trait
use Sofa\Eloquence\Mappable; // extension trait
use Sofa\Eloquence\Formattable; // extension trait
use Sofa\Eloquence\Contracts\Mappable as MappableContract; // interface

class User extends \Eloquent implements MappableContract {

    use Eloquence, 
    Mappable, Formattable; // order of these traits matters!

    protected $maps = [
      'picture' => 'profile.picture_path',
    ];

    protected $formats = [
      'picture' => 'strtolower',
    ];

    public function profile()
    {
      return $this->belongsTo(Profile::class);
    }
    // ...
}
$user = User::first();
$user->picture; // some/path/to/file.jpg
$user->picture = 'Path/To/Another/file.JPG'; // value formatted then mapped
$user->profile->picture_path; // path/to/another/file.jpg

Roadmap

  • Set relations on an array. (e.g. protected $relations = ['profile' => 'has_one'];)

...and much more to come soon!

About

Extensions for the Eloquent ORM

Resources

License

Stars

Watchers

Forks

Sponsor this project

  •  

Packages

No packages published

Contributors 12

Languages