PHP RFC: user-from syntax for namespace use declarations
- Version: 0.1
- Date: 2026-01-05
- Author: Stuardo Rodríguez, str@maphpia.com
- Status: Under Discussion
- Implementation: https://github.com/php/php-src/pull/20844
This RFC proposes an alternative spelling for namespace imports that reads “import X from Y”, as syntax sugar for existing `use` declarations.
Introduction
This RFC adds an alternative `use` syntax that places the imported symbol(s) first, followed by a shared namespace prefix introduced by `from`.
It is intended to improve readability for imports and to provide a brace-first grouped form for multiple imports from the same namespace.
Motivation and Rationale
The `use ... from ` makes it easier to scan and (optionally) sort import lists by imported symbol (class/function/const) rather than by namespace prefix. Placing the symbol immediately after `use` makes symbol-first ordering straightforward for humans and formatters, while projects that prefer namespace-first ordering can continue to do so.
Example (symbol-first ordering):
use Carbon from Illuminate\Support; use Inertia from Inertia; use SettingService from App\Services; use Status from App\Models; use Task from App\Models; use TaskCreated from App\Events; use TaskRepository from App\Repositories; use TaskService from App\Services; use TaskUpdated from App\Events; use TaskUpdateData from App\DTOs; use User from App\Models; use ZipArchive;
This RFC is pure syntax sugar (no runtime behavior change). The design is intentionally localized: the only notable compatibility surface is the introduction of a contextual/soft keyword token for `from` in `use` declarations.
Adding new syntax to PHP requires a clear and strong justification. The `use ... from` form meets that bar by reducing cognitive friction for developers who regularly move between languages that already use a similar form (e.g., JavaScript's `import X from 'Y'` and Python's `from Y import X`). Making PHP imports resemble these familiar patterns helps onboarding and code review across mixed-language teams and makes the import semantics immediately recognizable to a wider audience.
The combination of improved cross-language familiarity, better symbol-first sorting ergonomics, and low implementation risk provides a compelling rationale for adoption.
Proposal
New syntax
The proposal introduces the following additional forms:
1) Single imports (class-like imports):
use Name from Prefix; use Name from Prefix as Alias; use Name as Alias from Prefix; use Service from App\Domain;
2) Group imports (brace-first):
use {A, B as C} from Some\Namespace;
3) Function and const group imports:
use function {fn_a, fn_b} from Some\Namespace; use const {ConstA, ConstB} from Some\Namespace;
4) Mixed group imports (existing mixed-group behavior, with brace-first `from` form):
use {Php\WebSite, function JS\printTotal, const JS\BUAIKUM} from Mizo\Web;
Semantics
All new forms are syntax sugar for existing import forms and do not change runtime behavior.
- `use Name from Prefix;` is equivalent to `use Prefix\Name;`
- `use Name from Prefix as Alias;` is equivalent to `use Prefix\Name as Alias;`
- `use Name as Alias from Prefix;` is equivalent to `use Prefix\Name as Alias;`
- `use {A, B as C} from Prefix;` is equivalent to `use Prefix\{A, B as C};`
- `use function {fn_a} from Prefix;` is equivalent to `use function Prefix\{fn_a};`
- `use const {ConstA} from Prefix;` is equivalent to `use const Prefix\{ConstA};`
Mixed-group semantics and parsing
Mixed groups are syntax sugar for the existing prefix-group form: each entry in the brace list is interpreted as a *suffix* that is appended to the `Prefix`. For example, in
use {Php\WebSite, function JS\printTotal} from Mizo\Web;
both entries are suffixed onto `Mizo\Web` and the statement is equivalent to:
use Mizo\Web\{Php\WebSite, function JS\printTotal};
Entries inside the braces may themselves include namespace separators and will still be treated as suffixes (so `Php\WebSite` becomes `Mizo\Web\Php\WebSite`). A leading backslash on an entry makes it absolute and it will NOT be prefixed. Qualifiers such as `function` and `const` apply to the following name exactly as they do for existing grouped `use` declarations, and `as` aliases are supported per-entry.
Compatibility and implementation notes
This proposal introduces a new token `T_FROM` (token text: `from`) for use by the parser in `use`-declaration contexts.
To preserve compatibility with existing code that uses `from` as an identifier, `from` is treated as a *contextual* (soft) keyword. Tokenizers/lexers SHOULD emit `T_FROM` only when `from` occurs inside a `use` declaration, and emit `T_STRING` otherwise (method calls, property access, function names/calls, named arguments, etc.).
Implementation note: the Zend scanner must be context-aware (e.g., via lexical state or a scanner flag set after `use` and cleared at the terminating `;` / end-of-tag implicit `;`).
Tooling note:
- AST-based tools are unaffected: `$db->from()` and related identifiers remain valid and produce the same AST.
- Token-stream tools must handle `T_FROM` in `use` contexts.
Examples
Single imports (comma-separated supported):
use Classname from My\Full as Another, NSname from My\Full;
Brace-first group imports:
use {ClassA, ClassB, ClassC as C} from Some\Namespace;
Function/const group imports:
use function {fn_a, fn_b} from Some\Namespace; use const {ConstA, ConstB} from Some\Namespace;
Mixed group imports:
use {Php\WebSite, function JS\printTotal, const JS\BUAIKUM} from Mizo\Web;
Backward Incompatible Changes
- Tokenization change: the string `from` becomes a contextual token and may be emitted as `T_FROM` in `use` declarations instead of `T_STRING` in `token_get_all()` / `PhpToken::tokenize()` output.
- Token-stream tools (formatters, linters, IDEs, analyzers) must be updated to handle `T_FROM`.
- Mitigation guidance: token-only tooling should treat `T_FROM` as a keyword only in `use`-declaration contexts; where possible, prefer AST-based parsing.
- This proposal explicitly preserves `function from() {}`, `from()`, method/property names (e.g., `$db->from()`), and named arguments (`fn(from: ...)`).
Impact analysis (e.g. scanning Composer packages) is TBD; we recommend performing a repository-scale scan for uses of `from` as an identifier in third-party libraries and coordinating with major static-analysis and IDE projects to review possible impacts.
Proposed PHP Version(s)
next PHP 8.x
RFC Impact
To the Ecosystem
- Token-based tools will need to recognize `T_FROM`.
- Parsers that implement PHP grammar (or partial grammars) will need to account for the new `use … from …` and brace-first group forms.
To Existing Extensions
- `ext/tokenizer` exposes a new token constant `T_FROM`.
- No other extension impact is expected.
To SAPIs
No expected impact.
Open Issues
- Confirm the intended scope of “soft keyword” behavior for `from` across identifier positions (method names, class names, namespaces, named arguments, etc.).
- Quantify backward compatibility impact by scanning existing codebases for `from` used as an identifier in affected contexts.
- Decide whether mixed-group `from` imports should remain allowed (current implementation supports it).
- Decide whether to allow static-method imports (e.g., `use method from Class` as sugar for importing a static method or binding); this has non-trivial grammar and semantic implications (double-colon `::` interactions) and is out of scope for the initial proposal — record as a future investigation point.
- Design lexer state transitions for contextual `T_FROM` in the Zend scanner (`Zend/zend_language_scanner.l`) and ensure tests cover multiline, comments, and error recovery.
- Contact maintainers of major token-based tools, IDEs, and static analyzers to coordinate tokenization changes and provide migration guidance and tests.
Future Scope
- Consider whether to allow additional symmetric forms (e.g. alternative grouping spellings) only if there is strong demand.
- Consider IDE / tooling guidance (formatting conventions) after the syntax is accepted. In particular, provide guidance and formatter options so projects can choose symbol-first or namespace-first sorting (and ideally a configurable formatting rule), and provide recommended defaults and migration guidance for large codebases.
- Consider guidance for how formatters and linters should behave if a future static-method import form is introduced (e.g., `use method from Class`): provide warnings, opt-in formatting rules, and migration helpers to avoid surprising changes across large codebases.
Voting Choices
Primary Vote requiring a 2/3 majority to accept the RFC:
Patches and Tests
Implementation: https://github.com/php/php-src/pull/20844
Tests (proof of concept):
- Syntax and semantics:
- Zend/tests/use_from_syntax.phpt — basic single-import `use Name from Prefix` forms and simple comma-separated imports
- Zend/tests/use_from_syntax_qualified.phpt — handling of qualified and fully-qualified prefixes (leading backslash)
- Zend/tests/use_from_syntax_comprehensive.phpt — comprehensive coverage of combinations and edge cases
- Zend/tests/use_from_syntax_aliases.phpt — aliasing (`as`) semantics for single and grouped imports
- Zend/tests/use_from_group.phpt — brace-first group imports for classes, functions and consts
- Zend/tests/use_from_manual_examples.phpt — manual-style examples from the RFC demonstrating common usage
- Zend/tests/use_from_as_function_name.phpt — ensures `from` remains usable as a function name and call target
- Zend/tests/use_from_as_method_name.phpt — ensures instance method named `from` still works (`$db->from()`)
- Zend/tests/use_from_static_method.phpt — ensures static method named `from` still works (`C::from()`)
- Zend/tests/use_from_named_argument.phpt — ensures `from` can still be used as a named argument label (`fn(from: ...)`)
- Zend/tests/use_from_mixed_group_equivalence.phpt — demonstrates that `use {A, function B} from P;` is equivalent to `use P\{A, function B};`
- Tokenizer test:
- ext/tokenizer/tests/t_from_token.phpt — tokenizer test asserting that `from` is emitted as `T_FROM` in `use` contexts
- ext/tokenizer/tests/t_from_method_call.phpt — tokenizer test asserting `from` is `T_STRING` in `$db->from()` contexts
- ext/tokenizer/tests/t_from_token_get_all.phpt — token_get_all test verifying `T_FROM` vs `T_STRING` differences
Implementation
After the RFC is implemented, this section should contain:
- the version(s) it was merged into
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
References
Links to external references, discussions, or RFCs.
Rejected Features
Keep this updated with features that were discussed on the mail lists.
Changelog
If there are major changes to the initial proposal, please include a short summary with a date or a link to the mailing list announcement here, as not everyone has access to the wikis' version history.