Framework

Repository Author Commit message Committed SHA  
 
schema by dg DOCS
schema by dg removed support for key PreventMerging, removed Helpers::merge() (BC break)
schema by dg AnyOf::merge() merges layers according to the matched alternative instead of blindly (BC break)
schema by dg Structure::merge() driven by MergeMode; numeric-key appending decoupled from otherItems (BC break)
schema by dg added MergeMode enum, mergeMode() and mergeWith(); arrays merge only according to the schema (BC break)

Every element resolves its merging the same way: a mergeWith() closure (a
pure combiner, legitimate for scalars too) wins outright, MergeMode::Replace
returns the later layer wholesale, and arrays merge by keys with the mode
deciding whether numeric elements append (AppendKeys, the default) or
overwrite positionally (OverwriteKeys). Deep merging follows the schema
only: ArrayType recurses through its items schema, and a colliding key
holding arrays on both sides with no schema guidance is a CannotMerge error
instead of a silent guess; an explicit mergeMode() is the declared opt-out.
The blind Helpers::merge() no longer backs Type::mergeValues(); a null layer
still loses to an array and beats a scalar.

schema by dg ArrayType: mergeDefaults() are disabled by default (BC break) [Closes #28, Closes #31]
schema by dg Schema::merge() receives Context and reports merge errors through it (BC break)
schema by dg the options moved to the kind subclasses (BC break)

min(), max(), pattern(), items() and mergeDefaults() live on NumberType,
StringType and ArrayType; on a plain Type they throw DeprecatedException
saying who has them, closing the deprecations 1.4 opened. Type::complete()
became a template the subclasses hook into (coerce, validate, mergeDefault,
normalizeValue, mergeValues), the items completion moved to
ArrayType::completeItems() and describe() reports the subclass options
tightened by a deprecated range in the expression.

schema by dg Expect::type(): a union of different kinds is anyOf() (BC break)

A union such as 'int|string' or 'scalar' has no options of its own (1.4
deprecated them), so Expect::type() now builds anyOf() of the variants via
the new TypeExpression::format(), and error messages read "int|string" the
way anyOf() reports alternatives. A union of a single kind ('int|float',
'int|null') keeps its subclass and its options, exactly as 1.4 promised.
A directly constructed plain Type still accepts a union and keeps the 1.4
deprecation notice for its options.

schema by dg Type validates by itself; Validators-coupled expressions are deprecated (BC break)

Type checks the value against the parsed expression on its own: matches() is
the one place that knows every Kind, and Validators is asked only about named
string formats and the deprecated constructs. Those still work exactly as
before but raise a notice and 2.1 refuses them: a range in the expression
('int:1..5', use min() and max()), a validator name that is not a type
('numeric' and friends, use assert()), and a directly constructed Type for
a kind that has its own class (use Expect::type()). Helpers::validateType()
and the deprecated helpers of Base are gone, getCastStrategy() no longer
consults Validators for the builtin list.

schema by dg used #Deprecated
schema by dg Expect::from() works with class names
schema by dg Expect::from() removed support for phpDoc annotations (BC break)
schema by dg Schema: added return type hints (BC break)
schema by dg opened 2.0-dev
schema by dg updated DOCS
schema by dg Expect::listOf() with wrap: a single value is accepted and wrapped into a one-item list
schema by dg AnyOf: dynamic() is a flag, not a variant

A DynamicParameter passes straight through instead of being matched against
a Type(DynamicParameter::class) variant, which describe() would then have to
recognize and hide.

schema by dg added Expect::tuple()

A tuple is a TupleType, a Structure with a list shape cast to an array whose
layers replace each other wholesale - half-crossing two tuples is always
nonsense, so merge() simply keeps the later layer. otherItems() naturally
provides rest elements, describe() reports Kind::Tuple and JSON Schema
exports prefixItems with the rest schema or false as items. Structure is no
longer final.

schema by dg added Expect::enum() for backed enums

EnumType accepts a case or its backing value and yields the case; an
enum-typed property of Expect::from() maps to it. The validation is still
Type's instanceof, only a before() hook maps the backing value first, so
messages and everything else stay the same. An enum class in Expect::type()
keeps meaning plain instanceof, as for any other class; accepting values is
what Expect::enum() is for. Expect::from() no longer recurses into an enum
default as if it were a nested object.

schema by dg added StringType, NumberType and ArrayType as kind-specific subclasses of Type

Expect::string(), int(), listOf(), type('email') and the like return the
subclass that says what kind of value it is; every instanceof Type, type hint
and method called by name keeps working, Type is only no longer final. The
subclasses add no behavior in 1.x: validation still goes through Validators,
so Expect::type('url') and the other string pseudo-types keep working and are
reported by describe() as strings in that format. Methods that make no sense
for the kind (pattern() on a number or an array, items() outside arrays) are
deprecated with a notice; the fluent setters return static.

schema by dg added schema inspection (describe()) and JSON Schema export

Type, Structure and AnyOf report what they accept as a plain array with a
closed Kind vocabulary; child schemas are reported as they are. TypeExpression
is the single translator of the Expect::type() language into that array and
follows Validators::is() exactly (an unknown name is a class, 'int[]' is any
iterable of ints, legacy validator names are Other). JsonSchema::export() is
a pure function over describe() and refuses PHP-only types instead of emitting
a schema the Processor would reject.

Everything is @internal for now so the vocabulary can still change.

http by dg uses #Deprecated wip
http by dg removed samesite check using cookie (BC break)
http by dg IRequest, IResponse: added typehints, unification (BC break)
http by dg SessionSection: removed $warnOnUndefined (BC break)
http by dg Response: passing 0 as the expiration to setCookie() is deprecated

0 historically meant a session cookie; null now expresses that explicitly.
0 is still accepted for BC but emits a deprecation notice.

http by dg silently deprecated methods trigger E_USER_DEPRECATED
http by dg removed deprecated stuff
http by dg opened 4.0-dev
http by dg RequestFactory: added setBaseUrl() and 'http: baseUrl' option as a fallback for CLI

When the application runs from the command line (cron, tasks, MCP server),
$_SERVER carries no host, so the request URL was meaningless and everything
derived from it (%baseUrl%, LinkGenerator, template $baseUrl, assets) broke.

The base URL is used only when no host can be detected from the environment,
so a web application on any domain keeps working without changes.

http:
baseUrl: https://example.com/

http by dg Response::setCookie() treats an explicitly empty domain or path as given

The path/domain defaulting used truthy checks, so an explicit '' (a host-only
cookie or an empty path) behaved as if the argument was omitted: the cookie
inherited cookiePath instead of widening to '/', or cookieDomain instead of
staying host-only. Only null now means "not given".

Last synchronization: 2026-09-02 05:02:52