An open API service indexing awesome lists of open source software.

https://github.com/ryanwinchester/plasm

Schema and Changeset Validation for PHP
https://github.com/ryanwinchester/plasm

changeset php validation

Last synced: 12 months ago
JSON representation

Schema and Changeset Validation for PHP

Awesome Lists containing this project

README

          

# Plasm

[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/ryanwinchester/plasm/master/LICENSE)
[![Build Status](https://travis-ci.org/ryanwinchester/plasm.svg?branch=master)](https://travis-ci.org/ryanwinchester/plasm)
[![codecov](https://img.shields.io/codecov/c/github/ryanwinchester/plasm.svg)](https://codecov.io/gh/ryanwinchester/plasm)
[![Code Climate](https://codeclimate.com/github/ryanwinchester/plasm/badges/gpa.svg)](https://codeclimate.com/github/ryanwinchester/plasm)

Filter, cast, and validate incoming data from **forms**, **API**s, **CLI**, etc.

Schema and Changeset for PHP are inspired by `Ecto.Changeset`
from [Elixir's Ecto library](https://hexdocs.pm/ecto/Ecto.Changeset.html).

### In Development!

### Planned for V1.0:

- [ ] Default messages str replacements
- [ ] Finish default validators
- [ ] One or two provided Framework/ORM integrations
- [ ] Figure how to implement DB constraints from Integrations (unique, etc.)

## Install

Use [composer](https://getcomposer.org).

```sh
composer require plasm/plasm:dev-master@dev
```

## Usage

### 1) Define a Schema:

In the schema we specify all the fields we care about and specify what type
we want them to be cast to.

Options:

- `type`: required. the type the field should be cast to
- `default`: Will default to this value if not present in changeset `$attrs`
- `virtual`: This will be a future to mark fields as not for storing

```php
['type' => 'string'],
'email' => ['type' => 'string'],
'is_admin' => ['type' => 'boolean', 'default' => false],
'age' => ['type' => 'integer'],
'money' => ['type' => 'float'],
'password' => ['type' => 'string', 'virtual' => true],
'password_confirmation' => ['type' => 'string', 'virtual' => true],
'password_hash' => ['type' => 'string'],
'nothing' => ['type' => 'string', 'default' => null]
];
}
}
```

### 2) Define a Changeset:

You can define multiple changesets in the same class. You can create completely different ones or build on top of others.

For example, below we'll have a `createChangeset` for creating a user that just builds off our generic `changeset` and
making some of the fields required.

```php
cast(['name', 'email', 'is_admin', 'age', 'money', 'password', 'nothing'])
->validateFormat('email', '/.+@.+\..+/')
->validateLength('password', ['min' => 8])
->validateConfirmation('password')
->validateNumber('age', ['greater_than' => 12], 'You need to be at least 13');
}

/**
* Changeset for creating a User.
*/
public function createChangeset($attrs)
{
return $this
->changeset($attrs)
->validateRequired(['name', 'email', 'age', 'password'])
->validateChange(
'password',
$this->validatePassStrength(),
'Your password is too weak'
);
}

/**
* A custom validator for checking password strength.
*/
private function validatePassStrength()
{
return function($password) {
$zxcvbn = new \ZxcvbnPhp\Zxcvbn();
$strength = $zxcvbn->passwordStrength($password);

return $strength['score'] >= 3;
};
}
}
```

### 3) Use them somewhere:

Just for example's sake, the example below looks a lot like a typical Laravel controller's
`store` method.

We'll pass all the request data into the `createChangeset` changeset and
not worry since our `cast` method will filter out the fields we specify, cast them
to their specified types, and validate them.

If we used the `EloquentChangesets` trait we could call the `createModel` method after checking
if the changeset is valid. If it wasn't valid we can return to the view with the changeset
and display the changeset errors to the user.

```php
function store($request)
{
$changeset = UserChangeset::using(UserSchema::class)
->createChangeset($request->all());

if (! $changeset->valid()) {
return back()->with('changeset', $changeset);
}

$user = $changeset->createModel();

return redirect()->route('users/index')
->with('success', "User {$user->email} added");
}
```

## License

MIT

## Credits

- [Ecto.Changeset](https://hexdocs.pm/ecto/Ecto.Changeset.html): Most of the ideas come from here.