Library / SDK
Wixel/GUMP avatar
Wixel/GUMP

GUMP: framework-free PHP validation with 76 rules and a single class file

A fast, flexible PHP validation class that works anywhere and validates any data.

1,166 stars330 forksPHPMIT

At a glance

What is it?
GUMP validates and filters data in PHP without a framework, with rules written as pipe-separated strings, custom error messages per rule, and a class file you can include directly. It has been around since 2013, and the trade-off is that it does exactly validation and nothing else.
Who is it for?
Adopt GUMP if you want validation in a PHP project with no framework, if you prefer rules as readable strings over an attribute or schema DSL, and if you want the whole library to be one class file. Do not adopt it if your project already has a validation layer in its framework, since you would be adding a second source of truth, and do not treat its sanitization filters as a security boundary, because they transform data rather than escape it for a specific output context.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 154 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One class, no dependencies, since 2013

GUMP is a standalone PHP data validation and filtering library that makes validating any data easy without relying on a framework. The README says it has been serving the PHP community since 2013, and the repository is a single class file at its root, `gump.class.php`, alongside a `src/` directory, a `lang/` directory for translations, and `tests/`.

Installation is a Composer requirement:

bash
composer require wixel/gump

But manual installation is a first-class path rather than a fallback. The README says to download the latest release from GitHub Releases, extract it, and include the class file:

php
require_once 'path/to/gump.class.php';

One file, included directly, with no autoloader. For a project that has no Composer setup at all, that is the difference between using the library and not using it.

The feature list names 76 built-in validators, 19 languages with built-in internationalization support, custom validators and filters as an extension point, and a security focus described as built-in XSS protection and data sanitization. It supports PHP 7.1 through 8.4 and above.

The licence is MIT, the package is on Packagist as `wixel/gump`, and the recent releases are v2.3.2 from 2025-11-28, v2.3.1 and v2.3.0 from 2025-08-10, with the last push on 2026-05-23.

Two ways in: a static call or an instance you configure

The library exposes two entry points, and the choice between them is about how much configuration you need.

The static form validates and filters in one call. `GUMP::is_valid` takes the data and a rule array and returns either `true` or the list of errors:

php
<?php
require_once 'vendor/autoload.php';

$is_valid = GUMP::is_valid([
    'username' => 'johndoe',
    'email'    => '[email protected]',
    'age'      => '25'
], [
    'username' => 'required|alpha_numeric|min_len,3',
    'email'    => 'required|valid_email',
    'age'      => 'required|integer|min_numeric,18'
]);

if ($is_valid === true) {
    echo "All data is valid!";
} else {
    // Display validation errors
    foreach ($is_valid as $error) {
        echo "Error: " . $error . "\n";
    }
}

`GUMP::filter_input` is the same shape for filtering, and the README shows what the filter rules look like in practice:

php
$filtered = GUMP::filter_input([
    'username' => ' JohnDoe123 ',
    'bio'      => '<script>alert("xss")</script>Clean bio text'
], [
    'username' => 'trim|lower_case',
    'bio'      => 'trim|sanitize_string'
]);

The instance form is the one to use when you need custom messages or separate rule sets. You create a `GUMP` object, set the validation rules with `validation_rules`, set per-field error messages with `set_fields_error_messages`, set the filter rules with `filter_rules`, and then call `run` on your input. The errors are then read with `errors()` and the readable versions with `get_readable_errors()`.

The custom message API is per field and per rule, which is the part that matters for a real form. A user-facing message for a missing username and a different one for a username that is too short are separate entries in the same array, and the returned errors are the ones you wrote rather than generic strings.

The rule syntax is a string, and it reaches into nested data

Rules are written as pipe-separated strings, with parameters after a comma. A field name maps to a rule string, and the rules run in order, so `required|alpha_numeric|min_len,3` means the value must exist, must be alphanumeric, and must be at least three characters.

The parameter convention is the same everywhere. `min_len,3` and `max_len,100` set lengths, `min_numeric,18` sets a numeric minimum, `date,Y-m-d` passes a format, `extension,jpg;jpeg;png;gif` lists allowed extensions, and `valid_array_size_greater,0` compares a size against a threshold.

The part that is more capable than it first appears is the addressing. Field names are dot-separated paths, and a wildcard matches every element of a list:

php
$is_valid = GUMP::is_valid($data, [
    'user.name'        => 'required|valid_name',
    'user.email'       => 'required|valid_email',
    'products.*.name'  => 'required|min_len,3',
    'products.*.price' => 'required|float|min_numeric,0',
    'tags'             => 'required|valid_array_size_greater,0'
]);

So one rule covers every product in a list of products, and another covers a nested object. That is the feature that makes a small library usable on structured input rather than only on flat form fields.

File uploads are addressed the same way, with the file rules merged into the request data:

php
$is_valid = GUMP::is_valid(array_merge($_POST, $_FILES), [
    'profile_photo' => 'required_file|extension,jpg;jpeg;png;gif',
    'document'      => 'required_file|extension,pdf;doc;docx',
    'username'      => 'required|alpha_numeric'
]);

Note that the file rules check the extension rather than the content. That is a validation of what the client claimed, and it is worth keeping in mind when you decide how much to trust it.

Zero dependencies is a claim about Composer, not about PHP

The feature list says zero dependencies, and that is true in the Composer sense: pure PHP, no external dependencies required. It is not true in the sense of the runtime, and the requirements section is where the difference shows.

Five extensions have to be available: `ext-mbstring` for multibyte string support, `ext-json` for JSON processing, `ext-intl` for internationalization functions, `ext-bcmath` for arbitrary precision mathematics, and `ext-iconv` for character encoding conversion.

That is a real deployment constraint. A minimal PHP image, or a shared hosting account with a restricted php.ini, may not have ext-intl or ext-bcmath enabled, and the failure would appear at the point the relevant validator runs rather than at install time.

The extension list also explains the feature list. ext-intl is why the library can claim 19 languages with built-in internationalization, since the message catalogue and the locale-aware behaviour rest on those functions. ext-bcmath is there for the arbitrary precision arithmetic that some of the numeric validators need. ext-mbstring and ext-iconv together handle the character handling that a validation library gets wrong when it assumes single byte strings.

The language support is not a separate package to install. The `lang/` directory at the repository root holds the translations, and the README has an internationalization section for how they are selected, so the catalogue is data rather than code.

The repository layout is a small project with a real test suite

Beyond the class file, the repository root has `src/`, `lang/`, `tests/`, `ci/`, `dev/` and `composer.json`, plus `phpunit.xml.dist`, `.php-cs-fixer.php`, a `coverage.xml` and a `LICENSE`.

The PHPUnit configuration and the `tests/` directory mean the library is tested, and the coverage badge in the README points at Coveralls. The presence of a checked-in `coverage.xml` at the root is a convention worth noting: it is a report file in the repository rather than an artefact of a CI run, which some teams use so that the coverage is visible in a diff.

`.php-cs-fixer.php` is the code style configuration, and the CI directory holds the workflow definitions, with the build badge in the README pointing at a `ci.yml` workflow. The `dev/` directory is separate from `src/`, which is the usual split for a project that keeps its scratch tooling out of the published package.

The library is on Packagist as `wixel/gump` and the repository is licensed MIT, with the licence file at the root. The homepage recorded for the project is the Packagist page rather than a separate site, which matches a library whose documentation is its README and its docblocks.

Where GUMP is the wrong choice

The first wrong case is a project with a framework that already validates. GUMP's selling point is that it works without a framework, which is also its reason to exist alongside one. In a Laravel or Symfony application, adding it means two validation systems, two error formats and two places where a rule can be wrong, and the framework's own mechanism will be the one your team knows.

The second is a codebase that prefers types over strings. Rules as pipe-separated strings are readable and easy to grep, and they are also not checked by anything. A typo in a rule name is a runtime failure rather than a compile error, and a rule cannot be introspected by an editor. A schema or attribute based approach gives you that, at the cost of more ceremony.

The third is a security boundary. The `sanitize_string` filter strips markup, and `sanitize_email` and the other filters transform values, but a filter that rewrites data is not the same as output encoding for a specific context. The README's security section is the place to check what is claimed, and the general rule holds: escaping belongs at the point of output, in the template or the response, and not in the input pipeline.

The fourth is a project on a modern PHP version that wants typed static analysis. The library is a single class with static methods and docblocks, and the visible documentation does not describe stub files or generic types, so a project running PHPStan at a high level will have work to do.

The fifth is a team that needs validation to be part of the schema of the domain. GUMP validates at a boundary, which is exactly what it is for, and it has no concept of a validated object that carries its own guarantees once constructed.

Editorial conclusion

Adopt GUMP if you want validation in a PHP project with no framework, if you prefer rules as readable strings over an attribute or schema DSL, and if you want the whole library to be one class file. Do not adopt it if your project already has a validation layer in its framework, since you would be adding a second source of truth, and do not treat its sanitization filters as a security boundary, because they transform data rather than escape it for a specific output context. Before you install, confirm the required extensions are present, since mbstring, intl, bcmath and iconv all have to be enabled even though the library itself has no Composer dependencies.

Frequently asked questions

How do I install GUMP for PHP?

With `composer require wixel/gump`, or manually by downloading the latest release from GitHub Releases and including the class file with `require_once 'path/to/gump.class.php'`. The manual route needs no autoloader.

Which PHP extensions does GUMP need?

The requirements list ext-mbstring for multibyte strings, ext-json for JSON processing, ext-intl for internationalization functions, ext-bcmath for arbitrary precision mathematics and ext-iconv for character encoding conversion, on PHP 7.1 through 8.4 and above.

How do I validate nested arrays and lists with GUMP?

Field names are dot-separated paths and a wildcard matches every element of a list, so rules such as `user.name`, `products.*.name` and `products.*.price` apply to nested objects and to every item in a list in one call.

How does GUMP let me write my own error messages?

Set the validation rules with `validation_rules` and the messages with `set_fields_error_messages`, giving one message per field and per rule. After `run`, the messages are read with `errors()` and `get_readable_errors()`.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. Wixel/GUMP on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/wixel-gump.svg)](https://hysenlabs.com/projects/wixel-gump)

Was this useful?