Analyzer::Php::Phalcon
Inherits Analyzer::Php::PhpEngine < FileScanEngine < Analyzer < FileHelper < Reference < Object
Phalcon (https://phalcon.io/) is a PHP framework implemented as a C extension. It exposes two independent routing styles that real apps mix freely in the same codebase:
- Micro — a Slim-style DSL:
$app->get('/path', function () {...});, optionally grouped withPhalcon\Mvc\Micro\Collection. - MVC —
Phalcon\Mvc\Router::add()(+addGet/addPost/…, optionally grouped withPhalcon\Mvc\Router\Group), PHPDoc annotation routing (@RoutePrefix/@Get/@Route) and convention-based controller/action dispatch (ProductsController::showAction->/products/show).
Constants
- MVC Router / Group generic add(), optionally chained with via(): $router->add('/products/update', 'Products::update')->via(['POST', 'PUT']); $blog->add('/save', ['action' => 'save']); Negative lookahead excludes addGet/addPost/... (case 3 above) and addPurge (a real Phalcon Router method for the non-standard PURGE verb, which this analyzer doesn't otherwise model — better to emit nothing for it than to mis-report it as an unrestricted GET route).
- MVC Router explicit-verb helpers: $router->addGet('/path', 'Products::edit');
- PHPDoc annotation routing:
/**
- @RoutePrefix('/api/products') / class ProductsController extends Controller { /* @Get('/search') / public function searchAction() {} /* @Route('/save', methods={'POST', 'PUT'}) */ public function saveAction() {} }
-
Convention-based controller/action dispatch: a public
fooActionmethod on a controller extendingPhalcon\Mvc\Controllermaps to/{controller}/{action}(default actionindexis omitted), with any action parameters appended as positional path segments —showAction($id)onProductsController->/products/show/{id}.Skipped entirely for controllers that already use PHPDoc annotation routing (case 5): an app wired with
RouterAnnotationstypically replaces the default convention router outright, so guessing convention routes alongside real annotation routes would invent endpoints that are never actually reachable.
- map()/via(): $app->map('/repos/store/refs', 'actionProduct')->via(['GET', 'POST']);
Matched by call boundary (not a single-line path+comma regex) because
the trailing
->via(...)lookup needs the position right after the map() call's own closing paren — which a non-closure handler (a bare string/callable-array, with no body to bound) doesn't otherwise give us.
->get(...)/->add(...) are not unique to routing in a Phalcon app:
Phalcon\Config/Phalcon\Di objects answer to ->get($key, $default)
(a 2-arg call shape identical to a route registration) and
Phalcon\Validation answers to ->add($field, $validator). Both are
extremely common in real Phalcon code — a config->get('adapter', 'Unknown') or validator->add('email', new Uniqueness(...)) call in a
model or service provider would otherwise read as a phantom route.
These are the receiver names real Phalcon apps conventionally use for
those non-routing services; a variable holding an actual Micro app,
Router or route Collection/Group is never named one of these.
Request/response accessors a Phalcon handler (Micro closure, MVC
controller action, or annotation-routed action) reads incoming data
through. $this->request/$this->cookies are available in every one
of those contexts — Phalcon binds Micro closures to the application
instance, so $this resolves the same way it does inside a
controller action.
Every PHP analyzer is fed every .php file in a project-wide scan, so
this gate is the only thing keeping Phalcon off other frameworks'
route/controller files. "Phalcon" itself is unambiguous — no other
ecosystem framework spells this namespace — so a plain substring match
is safe without the narrower use X\Y;-only matching Laminas needs
against the generic word "Zend".
- Micro app / Collection direct verb calls: $app->get('/path', function () {...}); $invoices->post('/add', 'add');
Class methods
Instance methods
Instance-side view of the same declaration. The per-file rescues live on
this base class, which has no way to name the analyzer that is running
inside them, so a skipped file could not be attributed to a tech.
Deriving it from analyzer_for keeps the name written exactly once.