Skip to content

ext/filter: Add Filter\Filter and Filter\Flag enums and support them in the filter extension - #24111

Open
arshidkv12 wants to merge 2 commits into
php:masterfrom
arshidkv12:filter_enum_2
Open

arshidkv12 wants to merge 2 commits into
php:masterfrom
arshidkv12:filter_enum_2

Conversation

@arshidkv12

Copy link
Copy Markdown
Contributor

The filter extension currently exposes filter IDs and flags as integer
constants such as FILTER_VALIDATE_INT and FILTER_FLAG_ALLOW_HEX.

While these constants are well established and will remain available,
using integers for filter IDs and flags provides little type information
and makes the API harder to discover and use with modern PHP type
systems.

This added two backed enums:

  • Filter\Filter for filter IDs
  • Filter\Flag for filter flags
namespace Filter;
enum Filter: int
{
  case DEFAULT = FILTER_DEFAULT;
  
  case VALIDATE_BOOL = FILTER_VALIDATE_BOOL;
  case VALIDATE_INT = FILTER_VALIDATE_INT;
  case VALIDATE_FLOAT = FILTER_VALIDATE_FLOAT;
  case VALIDATE_REGEXP = FILTER_VALIDATE_REGEXP;
  case VALIDATE_DOMAIN = FILTER_VALIDATE_DOMAIN;
  case VALIDATE_URL = FILTER_VALIDATE_URL;
  case VALIDATE_EMAIL = FILTER_VALIDATE_EMAIL;
  case VALIDATE_IP = FILTER_VALIDATE_IP;
  case VALIDATE_MAC = FILTER_VALIDATE_MAC;
  
  case SANITIZE_STRING = FILTER_SANITIZE_STRING;
  case SANITIZE_EMAIL = FILTER_SANITIZE_EMAIL;
  case SANITIZE_URL = FILTER_SANITIZE_URL;
  case SANITIZE_NUMBER_INT = FILTER_SANITIZE_NUMBER_INT;
  case SANITIZE_NUMBER_FLOAT = FILTER_SANITIZE_NUMBER_FLOAT;
  case SANITIZE_SPECIAL_CHARS = FILTER_SANITIZE_SPECIAL_CHARS;
  case SANITIZE_FULL_SPECIAL_CHARS = FILTER_SANITIZE_FULL_SPECIAL_CHARS;
  case SANITIZE_ADD_SLASHES = FILTER_SANITIZE_ADD_SLASHES;
  
  case CALLBACK = FILTER_CALLBACK;
}


enum Flag: int
{
  case NONE = FILTER_FLAG_NONE;
  
  case ALLOW_OCTAL = FILTER_FLAG_ALLOW_OCTAL;
  case ALLOW_HEX = FILTER_FLAG_ALLOW_HEX;
  
  case STRIP_LOW = FILTER_FLAG_STRIP_LOW;
  case STRIP_HIGH = FILTER_FLAG_STRIP_HIGH;
  case STRIP_BACKTICK = FILTER_FLAG_STRIP_BACKTICK;
  
  case ENCODE_LOW = FILTER_FLAG_ENCODE_LOW;
  case ENCODE_HIGH = FILTER_FLAG_ENCODE_HIGH;
  case ENCODE_AMP = FILTER_FLAG_ENCODE_AMP;
  case NO_ENCODE_QUOTES = FILTER_FLAG_NO_ENCODE_QUOTES;
  case EMPTY_STRING_NULL = FILTER_FLAG_EMPTY_STRING_NULL;
  
  case ALLOW_FRACTION = FILTER_FLAG_ALLOW_FRACTION;
  case ALLOW_THOUSAND = FILTER_FLAG_ALLOW_THOUSAND;
  case ALLOW_SCIENTIFIC = FILTER_FLAG_ALLOW_SCIENTIFIC;
  
  case PATH_REQUIRED = FILTER_FLAG_PATH_REQUIRED;
  case QUERY_REQUIRED = FILTER_FLAG_QUERY_REQUIRED;
  
  case IPV4 = FILTER_FLAG_IPV4;
  case IPV6 = FILTER_FLAG_IPV6;
  case NO_RES_RANGE = FILTER_FLAG_NO_RES_RANGE;
  case NO_PRIV_RANGE = FILTER_FLAG_NO_PRIV_RANGE;
  case GLOBAL_RANGE = FILTER_FLAG_GLOBAL_RANGE;
}

API Changes

filter_input()

The current signature is:

function filter_input(
    int $type,
    string $var_name,
    int $filter = FILTER_DEFAULT,
    array|int $options = 0
): mixed {}

It becomes:

function filter_input(
    int $type,
    string $var_name,
    Filter\Filter|int $filter = Filter\Filter::DEFAULT,
    array|Filter\Flag|int $options = 0
): mixed {}

This allows:

filter_input(
    INPUT_GET,
    'id',
    Filter\Filter::VALIDATE_INT
);

and:

filter_input(
    INPUT_GET,
    'id',
    Filter\Filter::VALIDATE_INT,
    Filter\Flag::ALLOW_HEX
);

filter_var()

The current signature is:

function filter_var(
    mixed $value,
    int $filter = FILTER_DEFAULT,
    array|int $options = 0
): mixed {}

It becomes:

function filter_var(
    mixed $value,
    Filter\Filter|int $filter = Filter\Filter::DEFAULT,
    array|Filter\Flag|int $options = 0
): mixed {}

For example:

filter_var(
    '0xff',
    Filter\Filter::VALIDATE_INT,
    Filter\Flag::ALLOW_HEX
);

filter_input_array()

The current signature is:

function filter_input_array(
    int $type,
    array|int $options = FILTER_DEFAULT,
    bool $add_empty = true
): array|false|null {}

It becomes:

function filter_input_array(
    int $type,
    array|Filter\Filter|int $options = Filter\Filter::DEFAULT,
    bool $add_empty = true
): array|false|null {}

For example:

filter_input_array(
    INPUT_GET,
    Filter\Filter::VALIDATE_INT
);

filter_var_array()

The current signature is:

function filter_var_array(
    array $array,
    array|int $options = FILTER_DEFAULT,
    bool $add_empty = true
): array|false {}

It becomes:

function filter_var_array(
    array $array,
    array|Filter\Filter|int $options = Filter\Filter::DEFAULT,
    bool $add_empty = true
): array|false {}

For example:

filter_var_array(
    $data,
    Filter\Filter::VALIDATE_INT
);

Filter Flags

Filter\Flag can be passed directly where a filter flags integer is
accepted:

filter_var(
    '0xff',
    Filter\Filter::VALIDATE_INT,
    Filter\Flag::ALLOW_HEX
);

Multiple flags can still be combined using their backing values:

filter_var(
    '0xff',
    Filter\Filter::VALIDATE_INT,
    Filter\Flag::ALLOW_HEX->value |
    Filter\Flag::ALLOW_THOUSAND->value
);

For array-based filter definitions, enum flags can be used as the
flags value:

filter_var('0xff', Filter\Filter::VALIDATE_INT, [
    'flags' => Filter\Flag::ALLOW_HEX,
]);

The existing integer and scalar behavior of array-based filter options
is preserved.

Backwards Compatibility

This proposal does not remove or change the existing filter constants.

Existing code continues to work:

filter_var('123', FILTER_VALIDATE_INT);

and:

filter_var('0xff', FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX);

The new enums are an additional way to specify filters and flags.

Existing integer arguments remain accepted by all affected APIs.

Duplicate Values

Some filter constants are aliases and have the same integer value.

Backed enums cannot contain multiple cases with the same backing value.
Therefore, only one enum case is provided for each unique backing value.

The existing constants remain unchanged, including aliases.

For example, if multiple FILTER_FLAG_* constants have the same backing
value, they cannot all be represented as separate cases of
Filter\Flag.

Naming

The enum cases use names corresponding to the existing filter constant
names, without the FILTER_ or FILTER_FLAG_ prefix.

For example:

FILTER_VALIDATE_INT  -> Filter\Filter::VALIDATE_INT
FILTER_FLAG_ALLOW_HEX -> Filter\Flag::ALLOW_HEX

This keeps the relationship between the existing constants and the new
enums straightforward.

@iluuu1994 iluuu1994 added the RFC label Oct 4, 2026
@iluuu1994

Copy link
Copy Markdown
Member

Hi @arshidkv12. Please start a discussion on the mailing list. I'm not sure it's a good idea to extend this API further.

@arshidkv12

Copy link
Copy Markdown
Contributor Author

Sure, I’ll start a discussion.

@arshidkv12

Copy link
Copy Markdown
Contributor Author

Discussion thread: https://externals.io/message/132783

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants