My set-up comprises a lib folder with classes and a view folder with PHP files, that produce output. The views are imported inside a View class similar to this:
class View {
public function render(string $basename, Array $params) : string {
extract($params, EXTR_PREFIX_INVALID, 'v');
ob_start();
include sprintf('%s/views/%s.php', dirname(__DIR__), $basename);
$out = ob_get_contents();
ob_end_clean();
return $out;
}
}
I have basically two problems with Psalm in this situation:
For
View::renderit reports aUnresolvableInclude. I can even type the$basenamewith something like@param "view1"|"view2"|"about" $basenamewithout effect. The unresolvable include remains.
The
extract()puts the content of$paramsin the local scope, where the view files are included. This allows me to have<?=escape($foo)?>“tags” in my view files with
$params === ['foo' => 'bar']. However, Psalm doesn’t catch up on this and reports a lot ofUndefinedGlobalVariableproblems.
My question: How can I tell psalm about the view files and the variables? Or alternatively, how can I re-structure this code so that psalm can test it for me?
There's a demo TemlateChecker plugin in Psalm's repo that seems to do something similar: it looks at the docblock in the view file for the tag like
@variablesfrom ClassName::methodand makes them available in the template file. Or just properties on$thisvariable from that method, not sure. It's also mentioned in Psalm docs: Checking non-PHP files.Alternatively, you could wrap your template into a minimal method/function as technically view is just a function that takes a bunch of variables and returns a string: https://psalm.dev/r/66898ee87f
This way any tool that analyzes code (including Psalm, but not limited to) would be able to understand it.