Skip to content

Conversation

@nyamsprod
Copy link
Member

@nyamsprod nyamsprod commented Dec 19, 2025

Enum were introduced in PHP8.1 see https://wiki.php.net/rfc/enumerations#serialization but nothing was said about their serialization with http_build_query. This resulted on Enum using the same serialization as other object ie relying on the results of get_object_vars.

In PHP8.4 Enum representation was updated to match Enum representation with json_encode. This introduced a couple of changes:

  • http_build_query can serialise BackedEnum using their value;
  • http_build_query can not serialise UnitEnum and will throw a TypeError
  • UnitEnum can not be use as input for the first argument of http_build_query which will result also in a TypeError.

To allow migrating your code from pre-PHP8.4 this PR introduces an Enum:

enum QueryBuildingMode
{
    /**
     * Use current http_build_query algorithm.
     */
    case Native;

    /**
     * Strictly uses get_object_vars on objects (Enum included)
     * if the value can not be serialized the entry is skipped.
     *
     * ie http_build_query behavior before PHP8.4
     */
    case Compatible;

    /**
     * Mimic PHP8.4+ http_build_query behavior
     * with support for Enum
     */
    case EnumNative;

    /**
     * Validation-first mode.
     *
     * Guarantees that only scalar values, backed Enum and null are accepted.
     * Any object, Pure Enum, resource, or recursive structure
     * results in an exception.
     *
     * This contract is stable and independent of PHP's
     * http_build_query implementation.
     */
    case Strict;
}

And improve QueryString::compose and QueryString::composeFromValue as well as Query object related methods that currently uses only http_build_query.

enum Backed: string
{
    case One = 'Un';
    case Two = 'Deux';
}

$params = ['bar' => Backed::One, 'baz' => 1];

echo QueryString::compose($params, queryBuildingMode: QueryBuildingMode::Native);
// in PHP8.4+ returns "bar=Un&baz=1"
// in PHP8.4- returns "bar%5Bname%5D=One&bar%5Bvalue%5D=Un&baz=1"

echo QueryString::compose($params, queryBuildingMode: QueryBuildingMode::Compatible);
// returns  "bar%5Bname%5D=One&bar%5Bvalue%5D=Un&baz=1" regardless of PHP version

echo QueryString::compose($params, queryBuildingMode: QueryBuildingMode::EnumNative);
// returns "bar=Un&baz=1" regardless of PHP version

echo QueryString::compose($params, queryBuildingMode: QueryBuildingMode::Strict);
// returns "bar=Un&baz=1" regardless of PHP version

@nyamsprod nyamsprod self-assigned this Dec 19, 2025
@nyamsprod nyamsprod changed the title Introducing the QueryBuilder class to improve serialization Introducing the QueryBuildingMode Enum to improve serialization Dec 20, 2025
@nyamsprod nyamsprod added bug Something isn't working enhancement New feature or request labels Dec 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants