mdcass / support
A set of helpers and classes to aid with package development within Laravel. Inspired by Laravel's Eloquent Model functionality amongst other things.
This package's canonical repository appears to be gone and the package has been frozen as a result.
Requires
- maatwebsite/excel: ^2.1
- nesbot/carbon: ~1.18
- respect/validation: ^1.1
Requires (Dev)
- fzaninotto/faker: ^1.6
- phpunit/phpunit: 4.*
- vladahejda/phpunit-assert-exception: ^1.0
This package is not auto-updated.
Last update: 2020-11-08 18:38:56 UTC
README
Overview
A set of helpers and classes to aid with package development within Laravel. Inspired by Laravel's Eloquent Model functionality amongst other things.
- Setting Attributes
- Filling Attribtes
- Attributes By Array Path
- toArray Method
- Set By Chainable Method
- Accessors And Mutators
- Attribute Casting
- Collecting Aggregate Values
- Attribute Validation
Installation
Installation instructions are for Laravel 5.3
Require the library
composer require mdcass/support
Add the Service Provider to the providers
list in config/app.php
// config/app.php 'providers' => [ ... /* * Third Party Service Providers */ Mdcass\Support\SupportServiceProvider::class ]
Base Class
Use the base class by extending your own class to add richer functionality (much mimcked from the Eloquent model, but more lightweight)
Setting Attributes
class Example extends Mdcass\Support\Base {}
Setting attributes is standard, however none existent attributes will return null
instead of throwing an exception
$class = new Example(); $class->new_attribute = 'Hello there.'; echo $class->new_attribute; // Hello there. echo $class->non_existent_attribute; // null
Filling Attributes
You may mass assign attributes on a class either when instantiating, or later on
$class = new Example(['numeric_value' => 1, 'array_value' => ['hi', 'there']]); $class->numeric_value; // 1 $newClass = new Example; $newClass->fill(['numeric_value' => 1, 'array_value' => ['hi', 'there']]); $newClass->array_value; // ['hi', 'there']
Attributes By Array Path
The class with conveniently get
and set
array values on attributes where the key is a period .
delimited path
$class = new Example; $class->{'path.to.attribute'} = 'hello'; $class->toArray(); // ['path' => ['to' => ['attribute' => 'hello']]]; $class->path['to']; // ['attribute' => 'hello'] $class->{'path.to.attribute'}; // hello
Beware that this functionality cannot currently be toggled, meaning you should not use periods
.
in your attribute keys unless you want this functionality
toArray
Method
For debugging, the class comes with a toArray
method
$class = new Example(['numeric_value' => 1, 'array_value' => ['hi', 'there']); $class->another_attribute = 'hello'; $class->toArray(); // ['numeric_value' => 1, 'array_value' => ['hi', 'there'], 'another_attribute' => 'hello']
If an attribute is an object which also implements the
Base
class, it'stoArray
method will be called in a recursive fashion
Set By Chainable Method
You may define attributes which can be set by a chainable method. List the attribute names in the $set_by_method
property on the class. Attributes should be snake_case
whereas the method being called would be camel_case
.
/** * @property string $connection * @property string $db_table */ class MethodSettingExample extends Mdcass\Support\Base { protected $set_by_method = [ 'connection', 'db_table', ]; } $class = new MethodSettingExample; $class->connection('mysql')->dbTable('tbl_name'); $class->toArray(); // ['connection' => 'mysql', 'db_table' => 'tbl_name']
Any mutators defined for the attribute will be applied
Accessors And Mutators
Accessors and Mutators allow you to alter attributes when getting or setting them. This functionality is similar to Laravel's Eloquent functionality.
Defining An Accessor
To define an accessor, create a getFooAttribute
method on your model where Foo
is the "studly" cased name of the attribute. The stored value is passed to the accessor:
class AccessorExample extends Mdcass\Support\Base { /** * Get the first name attribute * * @param string $value * @return string */ public function getFirstNameAttribute($value) { return ucfirst($value); } } $class = new AccessorExample; $class->first_name = 'mike'; echo $class->first_name; // Mike
Accessors are applied when using the
toArray
method
Defining A Mutator
To define a mutator, create a setFooAttribute
method on your model where Foo
is the "studly" cased name of the attribute. This will be called when setting the value. Note that you should set the value on the attributes
property of the class:
class MutatorExample extends Mdcass\Support\Base { /** * Multiply the value by 10 when setting * * @param integer */ public function setMultiplierAttribute($value) { $this->attributes['multiplier'] = $value * 10; } } $class = new MutatorExample; $class->multiplier = 1; echo $class->multiplier; // 10
Attribute Casting
You can have the model convert attributes to common data types by listing them in the $casts
property, where the key is the name of the attribute and the value is the type: integer
, float
, string
, boolean
, date
, timestamp
. A Carbon
instance is returned for Dates.
class CastingExample extends Mdcass\Support\Base { protected $casts = [ 'is_boolean' => 'boolean', ]; } $class = new CastingExample; $class->is_boolean = 1; $class->is_boolean // true
Set a default value by either filling the class on instantiation, or in the $attributes
property:
class CastingExample extends Mdcass\Support\Base { protected $attributes = [ 'some_date' => '2016-01-03' ]; protected $casts = [ 'some_date' => 'date', ]; } $class = new CastingExample; $class->some_date // Carbon class $class->some_date->toDateString() // 2016-01-03
Collecting Aggregate Values
You can use the Traits\AggregateAttributes
trait to have attributes collect an aggregate of the values set on it. Use the trait along with an $aggregate_attributes
array property which lists the attriutes (as the key) and the type of aggregates. The available types are distinct
, sum
, and min_max
.
class AggregateExample extends Mdcass\Support\Base { use Mdcass\Support\Traits\AggregateAttributes; protected $aggregate_attributes = [ 'i_am_distinct' => 'distinct', 'i_will_be_summed' => 'sum', 'i_will_be_minmax' => 'min_max' ]; } $class = new AggregateTestModel; $class->i_am_distinct = 'a'; $class->i_am_distinct = 'b'; $class->i_am_distinct = 'a'; var_dump($class->i_am_distinct); // ['a', 'b'] $class->i_will_be_summed = 1; $class->i_will_be_summed = 2; $class->i_will_be_summed = 3; var_dump($class->i_will_be_summed); // 6 $class->i_will_be_minmax = 1; $class->i_will_be_minmax = 2; $class->i_will_be_minmax = 3; var_dump($class->i_will_be_minmax); // ['min' => 1, 'max' => 3]
Attribute Validation
You can have the class automatically validate an attribute value when it is set using the Respect/Validation library. An exception will be thrown if the validation fails.
Use the Traits\Validation
trait on your class. Use the $rules
property to list the attributes (as the key) then a pipe delimited string of validation rules. The following example works with the fill
method too.
class ValidationExample extends Mdcass\Support\Base { use Mdcass\Support\Traits\Validation; protected $rules = [ 'numeric_attr' => 'numeric', 'boolean_attr' => 'not_false_val' ]; } $class = new ValidationExample; try { $class->numeric_attr = 'string'; } catch(Respect\Validation\Exceptions\NestedValidationException $exception) { var_dump($exception->getMessages()); // ['"string" must be numeric'] }
The value under validation is the value taken after attribute casting and accessors have been applied
You can make the validation passive (not thrown an exception) and instead use the isValid()
method, along with the errors()
method to fetch messages. Simply set the $active_validation
property to false
class ValidationExample extends Mdcass\Support\Base { use Mdcass\Support\Traits\Validation; protected $active_validation = false; protected $rules = [ 'numeric_attr' => 'required|numeric', 'in_attr' => 'in:a,b,c' ]; } $class = new ValidationExample; $class->fill(['numeric_attr' => 'string', 'in_attr' => 'b']); if(!$class->isValid()) var_dump($class->classValidationMessages()); // ['"string" must be numeric']
Required Attributes
You must add the required
rule to the beginning of the rule string should an attribute be required - otherwise, a null
or empty value will pass validation. The first Validation example class above doesn't have the required
rule whereas the second does - the first class's numeric_attr
would validate as true
if the value was null
or empty, but will validate the other rules if a value is set.
Negating Attributes
Prepend a rule with not_
to negate a rule, an example of which is in the first example above not_false_val
.
Rules
The full rule reference can be found in the Respect/Validation documentation. Where rules in their documentation are camelCase
, snake_case
is used for this class (to ensure consistency with options like appending not_
to a rule).
Mocking Excel Files
The package comes with a shorthand function for creating Excel files. The target storage path is set in the Laravel-publishable config support-testing.php
(which defaults to the parent Laravel installation's storage_path
).
The columns are Faker
methods which populate the rows.
file_faker('test.xls', [ [ [ 'name' => 'First Sheet', 'columns' => ['date', 'company', 'catchPhrase', 'email', 'randomDigit', 'randomFloat'], 'rows' => 10 ], [ 'name' => 'Second Sheet', 'columns' => ['date', 'company', 'catchPhrase', 'email', 'randomDigit', 'randomFloat'], 'rows' => 10 ], [ 'name' => 'Empty Sheet', 'columns' => ['date', 'company', 'catchPhrase', 'email', 'randomDigit', 'randomFloat'], 'rows' => 0 ] ] ]);
This section of the documentation is to be developed as tests have greater coverage
Contributing
Testing
You must add the following package to the parent Laravel application for testing:
$ composer require vladahejda/phpunit-assert-exception --dev
Package testing follows this article. To test:
$ cd /path/to/package/mdcass/file-validator
$ path/to/parent-laravel-app/vendor/bin/phpunit