PHP
Last verified end to end: 2026-07-14 (
query_codeschema version 2).
For exact inbound and outbound symbol edges, proof tiers, and adapter-specific caveats, see Reference Traversal.
PHP exposes instance, static, nullsafe, and object-creation calls; named arguments through kwargs; attributes through decorators; and namespace imports separately from trait composition.
Fixture
Section titled “Fixture”<?phpnamespace App;
use App\Support\Formatter;use App\Support\{Logger, Writer as WriterAlias};
#[Route('/run')]class Service { use Loggable;
public const LIMIT = -3;
public function run(string $code): string { audit_named(code: $code); $formatted = Formatter::format($code); return $formatted; }}
function audit_named(string $code): string { return $code;}
$service = new Service();$service?->run("input");Named arguments and static receivers
Section titled “Named arguments and static receivers”The named-argument query uses kwargs to distinguish audit_named(code: $code) from ordinary positional calls. A receiver constraint separately identifies the static formatter call.
(language php (call :callee (name "audit_named") :kwargs [(code (identifier :name "code" :capture "value"))])){"languages":["php"],"match":{"kind":"call","callee":{"name":"audit_named"},"kwargs":{"code":{"kind":"identifier","name":"code","capture":"value"}}}}{ "results": [ { "captures": [ {"name": "value", "start_line": 14, "text": "$code"} ], "enclosing_symbol": "App.Service.run", "end_line": 14, "kind": "call", "language": "php", "result_type": "structural_match", "path": "php/app.php", "start_line": 14, "text": "audit_named(code: $code)" } ], "truncated": false}(language php (call :callee (name "format") :receiver (name "Formatter"))){"languages":["php"],"match":{"kind":"call","callee":{"name":"format"},"receiver":{"name":"Formatter"}}}{ "results": [ { "enclosing_symbol": "App.Service.run", "end_line": 15, "kind": "call", "language": "php", "result_type": "structural_match", "path": "php/app.php", "start_line": 15, "text": "Formatter::format($code)" } ], "truncated": false}Attributes, imports, and trait boundaries
Section titled “Attributes, imports, and trait boundaries”PHP attributes are normalized as decorators. Namespace use declarations are imports, while use Loggable inside the class is trait composition and must not become an import match.
(language php (class :decorators [(name "Route")])){"languages":["php"],"match":{"kind":"class","decorators":[{"name":"Route"}]}}{ "results": [ { "enclosing_symbol": "App.Service", "end_line": 18, "kind": "class", "language": "php", "result_type": "structural_match", "path": "php/app.php", "start_line": 7, "text": "#[Route('/run')]…" } ], "truncated": false}(language php (import :module (name "WriterAlias"))){"languages":["php"],"match":{"kind":"import","module":{"name":"WriterAlias"}}}{ "results": [ { "end_line": 5, "kind": "import", "language": "php", "result_type": "structural_match", "path": "php/app.php", "start_line": 5, "text": "use App\\Support\\{Logger, Writer as WriterAlias};" } ], "truncated": false}(language php (import :module (name "Loggable"))){"languages":["php"],"match":{"kind":"import","module":{"name":"Loggable"}}}{ "results": [], "truncated": false}The adapter also exposes nullsafe calls, constructors, assignments, field access, literals, and lambdas. It deliberately does not reinterpret class-body trait composition as an import, so a zero-match result here is a correctness proof rather than a missing fallback.
Traverse Indexed Types And Members
Section titled “Traverse Indexed Types And Members”<?phpclass QueryRoot { public function rootMember() {}}
class QueryLeaf extends QueryRoot { public function leafMember() {}}(supertypes (enclosing-decl (language php (class :name "QueryLeaf")))){"languages":["php"],"match":{"kind":"class","name":"QueryLeaf"},"steps":[{"op":"enclosing_decl"},{"op":"supertypes"}]}{ "results": [ { "end_line": 4, "fq_name": "QueryRoot", "kind": "class", "language": "php", "path": "php/hierarchy.php", "provenance": [ { "seed": { "end_line": 8, "kind": "class", "path": "php/hierarchy.php", "result_type": "structural_match", "start_line": 6 }, "steps": [ { "op": "enclosing_decl", "result": { "end_line": 8, "fq_name": "QueryLeaf", "kind": "class", "path": "php/hierarchy.php", "result_type": "declaration", "start_line": 6 } }, { "op": "supertypes", "result": { "end_line": 4, "fq_name": "QueryRoot", "kind": "class", "path": "php/hierarchy.php", "result_type": "declaration", "start_line": 2 } } ] } ], "result_type": "declaration", "signature": "class QueryRoot {", "start_line": 2 } ], "truncated": false}(owner (members (subtypes :depth 2 (enclosing-decl (language php (class :name "QueryRoot")))))){"languages":["php"],"match":{"kind":"class","name":"QueryRoot"},"steps":[{"op":"enclosing_decl"},{"op":"subtypes","depth":2},{"op":"members"},{"op":"owner"}]}{ "results": [ { "end_line": 8, "fq_name": "QueryLeaf", "kind": "class", "language": "php", "path": "php/hierarchy.php", "provenance": [ { "seed": { "end_line": 4, "kind": "class", "path": "php/hierarchy.php", "result_type": "structural_match", "start_line": 2 }, "steps": [ { "op": "enclosing_decl", "result": { "end_line": 4, "fq_name": "QueryRoot", "kind": "class", "path": "php/hierarchy.php", "result_type": "declaration", "start_line": 2 } }, { "op": "subtypes", "result": { "end_line": 8, "fq_name": "QueryLeaf", "kind": "class", "path": "php/hierarchy.php", "result_type": "declaration", "start_line": 6 } }, { "op": "members", "result": { "end_line": 7, "fq_name": "QueryLeaf.leafMember", "kind": "function", "path": "php/hierarchy.php", "result_type": "declaration", "start_line": 7 } }, { "op": "owner", "result": { "end_line": 8, "fq_name": "QueryLeaf", "kind": "class", "path": "php/hierarchy.php", "result_type": "declaration", "start_line": 6 } } ] } ], "result_type": "declaration", "signature": "class QueryLeaf extends QueryRoot {", "start_line": 6 } ], "truncated": false}