Php psalm configuration and syntax error reporting - php

I have a case with a simple syntax error.
It goes like this
class Foo
{
public function __construct($a,$b,$c,) {...}
So, there is an syntax error after param $c -- an excess comma (im using php7.3).
When i run psalm
./vendor/bin/psalm src/Foo.php --no-cache it shows that nothing is broken here.
My question is am i missing some config or something else, why do psalm do not catch that simple syntax error case?

With php8 this code no longer brings errors:
<?php
class Foo
{
public function __construct($a,$b,$c,) {}
}
Try it self.
I suspect psalm may already take that into account.
The decisive factor is which errors PHP itself delivers and not what any IDE or other tools display.

Parse errors Psalm reports are generated by nikic/php-parser which Psalm uses under the hood, and the parser itself does not distinguish between PHP 8 and PHP 7 syntax.
The only reason Psalm reports parse errors at all is that it can't understand syntactically incorrect code. It's not Psalm's goal to find any syntax errors, there are a lot of tools that do that.
Thus you should be using a proper syntax checker, either php -l directly or some wrapper like php-parallel-lint/php-parallel-lint.

Related

How would I handle a fatal error while setting up Calendar API on PHP

Following the Google Calendar API quickstart for PHP, I've followed the steps but, got the verification code and instead of getting the expected output " No upcoming events found " I get a
No idea how to move forward from here...
Welcome to StackOverflow!
I've encountered this very same error with numerous WP plugins that had been developed before PHP 5.6 and where programmers have been, well, lazy. Once these plugins get upgraded to PHP 7, exceptions are thrown for things that were mere deprecation warnings a few years ago.
From what I see in your logs, you have a dependency somewhere on Guzzle. According to Guzzle's own documentation, the recent versions require PHP 7.2.5 to work. Therefore, I can only assume that you are:
using a plugin or something similar that is based on an outdated version of Guzzle or you're using Guzzle yourself, but for some reason relying on a deprecated version of it (in the former case, you'd have to pester the plugin developer to update their own dependencies...);
using PHP 7.2 or perhaps even a later version.
You should be using PHP 7.4 or 8.0 as of mid-2021 (everything else has been deprecated), so your installation is fine. It's just the obsolete code coming from that outdated version of Guzzle that requires updating.
So, a simple fix for that issue is to look at the culprit — open on your favourite editor the file C:\xampp\htdocs\api\vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php and scroll down to line 67 (where the exception was thrown).
According to the trace you've posted, on that line you should have something like:
if (count($some_variable_name_here) [...]) { [...] }
What happened, in this case, was the following:
The count() function requires what PHP calls a Countable object. Generally speaking, historically, these were arrays of some sort.
Lazy programmers often use count() simply to check if the array is empty or not. In the pre-PHP7 days, count(NULL) was defined as being 0 or false, like so many other things in PHP. In other words: if the array was either empty (i.e. initialised but still without any item stored inside) or uninitialised (i.e. still assigned to NULL) or non-existent (i.e. a new variable which had not been declared before), then, by definition, count(NULL) was false.
This allowed lazy programmers to check for a handful of potentially different error conditions with a single if (!count($myArray)) { [...] do this; }. In other words, you would just execute that code inside brackets if $myArray existed, was correctly initialised, and had at least one valid element. All that with a 'simple' check!
Unfortunately, from the perspective of the interpreter and JIT compiler, as well as many other modern optimisation tools used by recent versions of PHP, this is terribly inefficient — besides being very sloppy programming. Starting with PHP 5.6, this misuse of count() became flagged as a warning, then later shown as a deprecated, and finally started throwing exceptions.
So, in your case, whatever is on line 67, count($some_variable_name_here) has been passed an empty/invalid variable/array/object, and while this would be fine before PHP 7, it now throws an exception: count() will not work with so-called 'uncountable' objects, and for all purposes, an unexisting/empty/invalid object is uncountable by definition.
To fix it, all you need to do is to check first if the object is valid and not null, and then you can check if it has any elements inside it. In other words, instead of having something like:
if (count($some_variable_name_here) [...]) {
[... do something ...]
}
change it to:
if (!empty($some_variable_name_here) && is_countable($some_variable_name_here) && count($some_variable_name_here) [...]) {
[... do something ...]
}
Note that empty() is a shortcut for !isset($var) || $var == false, and that PHP evaluates expressions from left to right, aborting as soon as a final result is known. If the variable is empty, the first check will immediately return true and the remaining checks will not even be called; by design, empty() does not throw an error or an exception and is safe to use in all scenarios where variables are in an 'unknown' state.
In many cases, you might get away just by checking if the object $some_variable_name_here is countable or not; a NULL object is not countable, so, it would also fail. In other cases — most frequent these days — you might not really know what has been passed: it might not be a valid, countable object. It might have more than one element, or zero. It might be just garbage and not properly initialised. Or any other possible combination. In those cases, being extra-careful with the checks (as opposed to being sloppy and relying upon PHP to do something useful with an otherwise useless variable/array/object) pays off.
Anyway, I've checked, and the current version of Guzzle's CurlFactory.php still has a count() for function release(), which is what is called before the exception is thrown. However, your own code is clearly different (at the time of writing, the current version has the count() on line 80, not 67), so it's very hard to say if you can correct it easily (there might be other, more subtle errors in the code calling release()...).
One assumes that Guzzle's latest version will fix these and other issues you might have — mostly because they demand PHP 7.2.5 or later, and that means that they have made changes to fix earlier things that didn't work as they should, and such changes were only possible with PHP 7.2.5.
Thus the recommendation is to upgrade your version of Guzzle. If there is any good reason to keep an outdated (and potentially bug-ridden and security-flawed) version around, well, now you know how to do a simple fix. At the very least, your code won't throw an exception; with luck, it will even work as you expect...
Happy hunting!

Can I disable some errors that match a specific criteria on a PHP script in PhpStorm 8.0.2?

I would like to ask e.g. if I have a code like this:
/**
* Doc comment
*/
#Annotation
class MyClass {
}
I know it will generate a parse error cause PHP doesn't have annotations natively like Java (i.e. outside of comments), but anyway is there a way to make PhpStorm not to complain about it?
Can I disable anyhow that Expected: semicolon in PhpStorm? I mean something like disabling error checking for a pattern matching #[a-zA-Z]+ or something like that?
EDIT: #notulysses The Inspection window shows only Typo and Warning, how can I see the Errors too?
You cannot -- those errors come from Lexer/Parser which is a lower level than inspections (which you may suppress/disable completely on individual basis) and therefore is not suppressible (unless, you write your own PHP-alike language support plugin).

Parse error: unexpected '#' symbol in constant function in php

In my project, when I try to install a software, I got an parse error in last step of installation
The parse error is
Parse error: syntax error, unexpected '#' in
/path/to/server/subfolder1/projectfoldername/subfolder/filename.php
on line 21
The coding in that particular line of that file is
if(#constant($matches[1][0]) != #$matches[1][0]){
if(!empty(#constant(#$matches[1][0])) & !empty(#$matches[0][0]) & !empty(#$design_m_r[$key])){
$design_m_r[$key] = #str_replace($matches[0][0], constant($matches[1][0]), $design_m_r[$key]);
}
}
Our site php version is php 5.3.28. I tried to search for this error. But I dont get any solution for this. Some of the forums told about this error as "This is the advanced php version functions. So this should not support for php 5.3.28 version". But when I searched, there is no versions used this type of function.
You can't use the # error suppression operator like that.
From the PHP Docs..
The #-operator works only on expressions. A simple rule of thumb is:
if you can take the value of something, you can prepend the # operator
to it. For instance, you can prepend it to variables, function and
include calls, constants, and so forth. You cannot prepend it to
function or class definitions, or conditional structures such as if
and foreach, and so forth.
Also, passing arbitrary expressions on empty is allowed only from PHP 5.5 .

PHP - disable warning for single line

I have a plugin in my forum which throws a warning.
I want to fix the problem, but firstly, I want to hide the warning message to the users.
I know I can change it globally, but I just want to do it for some lines.
How can I do this?
$bbcode_parser =& new vB_BbCodeParser($vbulletin, fetch_tag_list());
gives the error:
Warnung: Assigning the return value of new by reference is deprecated in ..../includes/garage_func_var.php (Zeile 6411)
I already know I need to use # but where do I put this?
# can be used to suppress warnings, notices and errors.
Fatal errors are displayed in PHP 7 which breaks the script.
# can be used before variables, functions, include calls, constants and so forth but cannot be prepended to function or class definitions, conditionals, loops and so forth.
So for example, to hide an undefined property error:
Class Cars{
}
$obj = new Cars();
echo #$obj->idontexist;
As to your specific problem:
#$bbcode_parser =& new vB_BbCodeParser($vbulletin, fetch_tag_list());
should fix it.
While the mentioned deprecated warning message is displayed in PHP 5, the following will be displayed in PHP 7 since it was deprecated in the upgrade.
PHP 7 Note:
Parse error: syntax error, unexpected 'new' (T_NEW)
Use # only as an absolute last resort. It is considered bad coding to use # as slows things down and moreover creates headaches for programmers (including yourself) in the future when trying to debug. This is really frowned upon.
You should:
Hide warnings only for that call using a function using set_ini
Use "try" in php to manage errors.

php code, is it slow or wrong?

"multiple annotations found at this line"
i have been using aptana and other IDE before, but never gave me this error, but yesterday i installed zend studio and it was giving following error in all my code where i have assigned and also check if condition at same time.
code:
line 16: if ($message_array = #unserialize($e->getMessage()))
line 17: $message = $message_array;
on all if condition, where i assigned the value to a variable and also check if the variable is true/false, it gives me error "multiple annotations found at this line"
Yeah, that syntax is typically flagged by most decent IDEs as "Accidental Assignment" (since it's not obvious if you meant = or ==). Most will allow you to wrap it in a () to silence the error (since then it's apparent you want the result rather than a test):
if (($message_array = #unserialize($e->getMessage()))) {
}
Also, for readability and maintainability, I would suggest a few things there.
First, use braces. Since it's only a special case that lets you not use them, I personally think it's better form to always use them so that it's clear what was meant.
Second, do all asignment outside of the if clause. It makes it more explicit and easier to tell at a quick glance what you meant. Plus it looks less cluttered.
$message_array = #unserialize($e->getMessage());
if ($message_array) {
...
}
Third, I would suggest avoiding the # operator. To me it's a sign of code-rot. While I know it's easy to use and easier than properly handling the error, I think it's just a short-cut that will make life harder for you. You can avoid it in a few ways. First, you can check the string before you pass it to unserialize. Make sure it's non-empty, a string, etc. Secondly, you can install an error handler to throw exceptions on PHP errors (what I do). That way, you just wrap the unserialize call in a try {} catch(){} block. It's nicer since you actually can inspect the error rather than just trusting that the thrown error is what you think it is...
That is not an actual error. Instead the IDE has found more than one error, warnings or hints at the same code line.
You can look at the Problems tab to see the actual errors and warnings.

Categories