PHPackages                             bytepath/shared - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. bytepath/shared

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

bytepath/shared
===============

Shared libraries used in all Bytepath projects

1.0.5(3y ago)019mitPHPPHP &gt;=8.0

Since Mar 6Pushed 3y ago2 watchersCompare

[ Source](https://github.com/bytepath/shared)[ Packagist](https://packagist.org/packages/bytepath/shared)[ RSS](/packages/bytepath-shared/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (5)Dependencies (1)Versions (6)Used By (0)

Bytepath Shared Libraries
=========================

[](#bytepath-shared-libraries)

This package contains a bunch of libraries we use on every project. These libraries are framework agnostic in that you typically must provide an implementation for your framework of choice

Validator
---------

[](#validator)

Validator is a framework agnostic library for performing validation on client data. The class provides both an interface that defines how the validator works, and an abstract implementation of that interface that you can use to implement validation in your application.

### ValidatorInterface

[](#validatorinterface)

ValidatorInterface has two methods

```
    public function rules($rules): self;

    public function validate($data, ?Closure $callback): ValidationResult;
```

**rules()**

The first method, rules, accepts a list of $rules and returns a new instance of whatever validator you are using. Rules are not currentlyy formally defined. It's up to you to decide what rules are. In the future I plan to add some sort of rule definition class that makes your rules a bit more portable.

I use this with laravel, so 'rules' looks like this for me.

```
$rules = [
  "name" => "required|string|max:100",
  "age" => "required|numeric",
];
```

this method returns a new class, leaving the original intact, so you can call this method at any time without having to worry about state etc.

**validate()**

The second method, validate, runs your rules against the provided $data. If all rules pass and the data is considered validated, the closure provided in the second argument will be ran. This closure will only run if validation passes, so you can do "dangerous" actions such as creating rows in the database etc, here.

The closure will be passed a variable of validated $data. Any fields in the data array that do not have a corresponding rule will be filtered out so you don't need to explicitly check for this.

```
$rules = [
  "name" => "required|string|max:100",
  "age" => "required|numeric",
];

$userData = [
  "name" => "andrew",
  "age"  => 12,
  "zip" => "90210" // No rule for this
];

return $validator->rules($rules)->validate($userData, function($validatedData) {
   // zip will be filtered out of the $validatedData array

   // Returns a theoretical user object containing the validated data
   return App\Models\User::create($validatedData);
});
```

If a value is returned from the closure, you can access this value with the getData() method of the ValidationResult returned by this method.

### Validator

[](#validator-1)

Validator is an abstract class that does most of the work of implementing the ValidatorInterface for you. Though it's recommended you use this Validator as a base for your implementation, you are free to just implement the ValidationInterface directly if that fits your use case better.

This class has one abstract method

```
    abstract protected function checkData($data, $rules): ValidationResult;
```

That performs the validation action in the method of your choice. You must implement this method yourself.

This method returns an object that extends the ValidationResult class described below.

### ValidationResult

[](#validationresult)

The validate method of the ValidatorInterface returns an object that extends the abstract ValidationResult class. Assuming you are using the premade Validator class in this library, there are two possible objects that can be returned.

**PassedValidation**

As the name suggests, this object will be returned if the provided data passed validation. This object will contain any data that you returned from the closure passed to the validate() method described above in the ValidatorInterface section. To access this data you can run the getData() method of the PassedValidation class

**FailedValidation**

As the name suggests, this object will be returned if the provided data fails validation. This object will contain a key/val list of rules that did not pass as well as a human readable string that you can provide to the user in your form. You can access this list of errors with the getErrors() method

### Changing The Behaviour Of PassedValidation/FailedValidation In Your Apps

[](#changing-the-behaviour-of-passedvalidationfailedvalidation-in-your-apps)

You can return whatever you want from your implementation of Validator as long as the returned object extends ValidationResult. To make this process a bit simpler, the Validator class has two protected methods that you can override to change the class that will be returned in the event of pass/fail

```
    protected function passed($data = []): PassedValidation
    protected function failed($errors = []): FailedValidation
```

If you extend either of these methods in your implementation you can change the value that gets returned. Values returned must extend Passed/FailedValidation respectively.

An example of where you might want to do this is in Laravel, you could implement the Responsible interface to automatically transform these objects in to valid Laravel Response objects. Now you can just return the result directly from your controller method and it will magically transform into a valid http response with proper headers etc.

### Transforming Data Returned By Validator

[](#transforming-data-returned-by-validator)

The ValidationResult object has a method called transform that you can use to mutate the data returned by the ValidationResult object. This class accepts a callback function and returns "self" meaning you can chain this function call directly in your implementation.

As an example lets modify the previous example where we validated data and used it to create a user. Imagine instead we want to return a JSON string instead of an object. We could do so using the transform function like this

```
// Pulled from the validate() example from earlier in this doc
$result = $validator->rules($rules)->validate($data, function($validatedData) {
   return App\Models\User::create($validatedData);
});

// Transforms the "User" into JSON.
$result->transform(function($data) {
 return json_encode($data);
});

// Returns {"name": "andrew", "age": 12}
$shouldBeJSON = $result->getData();
```

### The transform() class on the FailedValidation object

[](#the-transform-class-on-the-failedvalidation-object)

The FailedValidation object does not have any data to transform, so if you call the transform() method on a FailedValidation object, the class just returns self without actually running the callback.

This was done intentionally so that we can return failed results while still retaining the ability to transform successful results.

```
$failed = $validator->rules($rules)->validate($data, $fn);  // Validation failed here returning a FailedValidation object

$failed->passes(); // False

$failed->transform(function($data) {
   return json_encode($data);   // This function will NOT be ran on FailedValidation so it's safe to assume we have validated data here
});
```

### Example Implementation

[](#example-implementation)

You can use the concepts described above to make really verbose, easy to read code. Here is a sample implementation you can use

```
class SomeService
{
    public function __construct(protected Validator $validator)
    {}

    /**
     * Creates a validator, then uses that validator to validate the data
     * and create a new user
    */
    public function createUser($data): ValidationResult
    {
        return $this->getCreateValidator()->validate($data, function($validatedData) {
            return App\Models\User::create($validatedData);
        });
    }

    /**
     * Creates a validator by passing it a list of rules required to make a new user
    */
    protected function getCreateValidator(): Validator
    {
        $rules = [
            "name" => "required|string|max:100",
            "age" => "required|numeric",
        ];

        return $this->validator->rules($rules);
    }
}
```

```
class SomeController
{
    public function __construct(protected SomeService $service)
    {}

    public function createUserReturnJSON($data)
    {
      /**
        If validation succeeds,we will create a new user and convert it to JSON

        If validation fails, we return a FailedValidation object that contains
        a list of validation errors you can provide to the user. You could
        process these errors here, or catch them in a middleware of some
        sort
      */
      return $this->service->createUser($data)->transform(function($data){
          // This callback will only run if validation was successful
          return json_encode($data);
      });
    }
}
```

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

5

Last Release

1164d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9af12181fd1cd1ddf882cff8b10b6c907534c6821dfb580bf8827dae9949aa5f?d=identicon)[bytepath](/maintainers/bytepath)

---

Top Contributors

[![bytepath](https://avatars.githubusercontent.com/u/11377286?v=4)](https://github.com/bytepath "bytepath (17 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/bytepath-shared/health.svg)

```
[![Health](https://phpackages.com/badges/bytepath-shared/health.svg)](https://phpackages.com/packages/bytepath-shared)
```

###  Alternatives

[verbb/many-to-many

A field type to manage relationships from both sides.

8112.0k](/packages/verbb-many-to-many)[ajmariduena/dynamic-field

A Laravel Nova field.

1822.9k](/packages/ajmariduena-dynamic-field)[teewurst/psr4-advanced-wildcard-composer-plugin

Adds a parser to enable composer, to be used with wildcards

1028.0k](/packages/teewurst-psr4-advanced-wildcard-composer-plugin)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
