Is it somehow possible to identify unused variables in a PHP file in Emacs?
With other languages, this is possible by using tools such as Flymake.
I've already enabled Flymake to show syntax errors for my PHP files on the fly, but still it's frustrating that PHP logic errors are sometimes due to situations like:
<?php
$foo = whatever();
$bar = something($fo);
...
Note the typo on $foo that will contribute to the developer's headache and to his/her exorbitant use of coffee.
After the hints by Pascal and viam0Zah, I set this in my php.ini file:
error_reporting = E_ALL | E_STRICT
When I run php from the command line, I'm now able to see the notice about the undefined variable (with or without the -l option):
php -r '$foo = 3; echo $fo;'
PHP Notice: Undefined variable: fo in Command line code on line 1
php -r '$foo = 3; echo $fo;' -l
PHP Notice: Undefined variable: fo in Command line code on line 1
This is what I'm currently using in my .emacs file. It works perfectly fine with parse errors, but I'm still not able to match on the notices, though :(
;; Flymake for PHP
(require 'flymake)
(defun flymake-php-init ()
"Use php to check the syntax of the current file."
(let* ((temp (flymake-init-create-temp-buffer-copy 'flymake-create-temp-inplace))
(local (file-relative-name temp (file-name-directory buffer-file-name))))
(list "php" (list "-f" local "-l"))))
(add-to-list 'flymake-err-line-patterns
'("\\(Parse\\|Fatal\\) error: +\\(.*?\\) in \\(.*?\\) on line \\([0-9]+\\)$" 3 4 nil 2))
(add-to-list 'flymake-err-line-patterns
'("Notice: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)" 2 3 nil 1))
(add-to-list 'flymake-allowed-file-name-masks '("\\.php$" flymake-php-init))
I've also tried Gabor's configuration, but with the same result. It is fine with errors, but bad with notices.
Please note that from the command line, parse errors look like:
php -r '$fo o = 3; echo $fo;' -l
PHP Parse error: syntax error, unexpected T_STRING in Command line code on line 1
I don't get why Notices are not matched. I've tried the regular expression separately and it seems to match correctly:
(search-forward-regexp "Notice: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)")
PHP Notice: Undefined variable: fo in Command line code on line 1
(C-x C-e will jump to the end of the lines).
Finally, I disabled Xdebug for now, since the notices were originally reported as:
PHP Notice: Undefined variable: fo in Command line code on line 1
PHP Stack trace:
PHP 1. {main}() Command line code:0
So, I guess I should slightly change the regexp to match the multiline errors. Any hint about this?
It's not really an answer to your question, as it's not working in Emacs, but PHP can raise notices, when you are trying to read from a variable that's not been initialized.
For more informations, see:
error_reporting, which should include E_NOTICE
display_errors to have those notices (and other errors) displayed
which is useful when developing,
but it should not be enabled on a production server.
For example, with error_reporting set to report E_NOTICE (and others), the following portion of code:
$aa = 'glop';
echo strlen($a);
Raises this notice:
Notice: Undefined variable: a in /.../temp/temp.php on line 5
It's not as simple as getting it in your editor, I admit -- but it will still help finding out why something doesn't work ;-)
Since Flymake uses the php binary's syntax check option (-l) for highlighting parse errors, there is no obvious way to catch notices and other errors without running or lexical parsing the code. If it's not a problem to not only lint but execute your script, then you can do the following.
Unfortunately, flymake-php defines error line patterns as constant (at least in the bundle shipped with Emacs Starter Kit), and even the flymake command is hard-coded. There is a few ways to achieve our goal and each is a pain. May be it's a quick and not so dirty solution to define our flymake-php-init function based on the original one.
(defun my-flymake-php-init ()
;; add a new error pattern to catch notices
(add-to-list 'flymake-err-line-patterns
'("\\(Notice\\): \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)"
3 4 nil 2))
(let* ((temp-file (flymake-init-create-temp-buffer-copy
'flymake-create-temp-inplace))
(local-file (file-relative-name
temp-file
(file-name-directory buffer-file-name))))
;; here we removed the "-l" switch
(list "php" (list "-f" local-file))))
Then customize flymake-allowed-php-file-name-masks to use my-flymake-php-init function for initializing flymake-php instead of the original one. And so it works:
(source: flickr.com)
Decent IDE's will give you the names of the variables in the current scope when you are typing them via Intellisense.
This should severely cut down on the number of times you misspell a variable name. It also allows your variable names to be more descriptive than $foo
Furthermore, you should always pay attention to undefined variable warnings, as they immediately tell you when you have made a misspelling.
Related
I have theses errors in php v7.2 but don't see any E_WARNING when using php v7.1.
How can I resolve following errors?
/web13/web/boutique/includes/Sites/Shop/NavigationHistory.php on line 39
[12-Jan-2018 22:44:20 America/Toronto] PHP Warning: Use of undefined constant MODULE_HEADER_SELECT_TEMPLATE_STATUS - assumed 'MODULE_HEADER_SELECT_TEMPLATE_STATUS' (this will throw an Error in a future version of PHP) in /var/www/clients/client1/web13/web/boutique/includes/Sites/Shop/Template.php on line 356
This is a common warning that occurs whenever PHP has detected the usage of an undefined constant.
Here is an example of constant being defined in PHP:
define('PI', 3.14);
Below is a list of some cases that might cause the issue:
Forgetting to use a $ symbol at the start of a variable name.
$name = "Aniket";
echo name; // forgot to add $ before name
The above code will throw: Notice: Use of undefined constant name – assumed ‘name’. Because there is no dollar sign in front of the variable “name”, PHP assumes that I was trying to reference a constant variable called “name”.
Forgetting to place quotes around strings.
echo $_POST[email];
In the example above, I failed to place quotes around the $_POST variable “email”. This code will throw: Notice: Use of undefined constant name – assumed ’email’.
To fix this, I’d obviously have to do the following:
echo $_POST["email"];
According to Deprecated features in PHP 7.2.x you should not use undefined constants because:
Unquoted strings that are non-existent global constants are taken to be strings of themselves.
This behaviour used to emit an E_NOTICE, but will now emit an E_WARNING. In the next major version of PHP, an Error exception will be thrown instead.
You can prevent this E_WARNING only if you declare the constant value before using it.
In the above question, MODULE_HEADER_SELECT_TEMPLATE_STATUS is not defined.
In addition, for those who are new to wordpress Plugin development and cant seem to figure out what it means to define "Constant" before its used...
Here is an example of what will throw an error:
add_action('wp_enqueue_scripts', myprefix_load_styles);
Declaring a function directly like that in a hook is one way to generate an error like this.
Instead:
add_action('wp_enqueue_scripts', 'myprefix_load_styles');
Note, the function name is now inside the quotes.
And that should work, if thats your scenario.
I've just created a PHP job to recursively clean up all files in a PHP project and automatically quote all strings which are undefined constants used inside square brackets for the array syntax.
Observation: this fix only targets array usage like $a[key1] which will be automatically transformed into $a['key1']. The clean up process DOES NOT parse and compute a list of defined constants in your project, in order to white-list them for usage without quotes in all possible contexts.
It's recommended to run it for your project on DEV first, check functionality and then push to LIVE.
QUICK USAGE:
git clone https://github.com/eyroot/lx-utils lx-utils
cd lx-utils && composer install --no-dev
php run/cleanUpSquareBrackets.php /path/you/want/to/clean/up
The complete usage instructions and source code are on the page:
https://github.com/eyroot/lx-utils
Short hand Search replace Regex for Notepad++
for array(test=>'bla')
Search: ([ (\t])([aA-zZ]+)([\t ]*=>)
Replace: \1'\2'\3
for [test]
Search \[([aA-Zz]+)\]
Replace:['\1']
I had a similar error in WordPress using PHP version 7.3:
The error: [23-Dec-2022 21:53:48 UTC] PHP Warning: Use of undefined constant ‘xmlrpc_enabled’ - assumed '‘xmlrpc_enabled’' (this will throw an Error in a future version of PHP) in functions.php in a child theme
The code:
add_filter( ‘xmlrpc_enabled’, ‘__return_false’ );
as you can see, there were quotes that in my editor (gedit) look like inverted commas. These do not work.
After I changed the quotes to:
add_filter( 'xmlrpc_enabled', '__return_false' );
the errors went away.
Thank you #wale for the pointer on where to look.
I have PHP set up for E_ALL, so usually receive notice/warning/error info in form:
Notice: Undefined variable: var in path\to\my\file on line 1
Now this has suddenly changed: my application is kicking them out in format
Noticepath\to\my\file1
i.e. no formatting, no description of the notice, just error-class, file-path and line number concatenated together
As far as I can tell nothing has changed with settings etc
If I do a simple test script the correct verbose format is still being produced
e.g.
echo $var;
where var is undefined
It just started happening this morning on an application that I am currently working on, which was not having this problem earlier, where as far as I can see nothing changed that should impact this
I haven't been able to find any remotely similar problems raised previously here or anywhere else so any suggestions would be much appreciated
OK: Fixed it. Thanks for help guys
Simple error - it was just the unexpected outcome in terms of impact on error reporting that threw me.
FYI: I had a variable called '$direct'; I missed the '$' in an if statement, and it looks like 'direct' in that context is meaningful
I'm referring to How to enable notices on my development server
I expect the following code shall give me some warning, when I execute it through, as my $a is not explicitly declared as array
php a.php
<?php
ini_set('display_errors', 1);
error_reporting(E_NOTICE);
$a['key'] = 123;
echo $a['key'] . "\n";
However, no warning message being printed. Is there anything I had missed?
The PHP I'm using is PHP 5.5.3. I'm not sure this matters?
I expect the following code shall give me some warning, when I execute it through, as my $a is not explicitly declared as array
Wrong... by writing $a['key'] = 123; you declare an array and set the key key to the integer number 123. That's a valid PHP array initialization. (The PHP version does not matter in this case.)
To explicitely produce an error notice for testing purposes…
If you want to provoke an error notice for testing purposes, you could add this line:
count($ThisIsNotDefinedOnPurpose);
which will produce an error notice saying
Notice: Undefined variable: ThisIsNotDefinedOnPurpose in … on line …
Why do I get notices when I execute a php file on my local server? Does that mean there is an error in my file? Notices like:
Notice: Use of undefined constant l - assumed 'l' in C:\xampp\htdocs\weekday.php on line 3
Notice: Use of undefined constant Monday - assumed 'Monday' in C:\xampp\htdocs\weekday.php on line 6*
You are likely getting notices because you have debugging turned on. It probably looks something like this:
error_reporting(E_ALL);
ini_set('display_errors', True);
To define a constant you need to do
define("Monday","value");
Also it is a php convention to name constants with all upper case. I suggest you stick to this convention so you can differentiate a constant from a regular string when reading your code.
These notices are there to tell you exactly where the problem is.
Look at line 3 of weekday.php and you'll see a place where you use l and realise that it's an undefined constant (look up constants)
You probably mean it to be a variable (look up variables - they start with a $ like $l in PHP) or a string constant (look up strings - they are surrounded by quotes like "l" or 'l')
going by the mention of "Monday" I'm going to assume you meant it to be a string.
Yes Notice means you have an error. As you can see it explains where the error is
There's a difference between errors and notices. An error will stop your script running; a notice is PHP telling you that there's something up with your script, and it's guessing what you actually meant.
A notice like:
Notice: Use of undefined constant Monday - assumed 'Monday' in C:\xampp\htdocs\weekday.php on line 6*
Means that you're using something like:
if ($day == Monday) .....
PHP is guess that you mean a string with the text of Monday in it, and it's right.
You don't have to fix notices - your code will still run. But it's definitely a good idea to do so - it'll make sure that your script executes exactly as you intend.
So I came across this feature/bug today and I'm struggling to wrap my head around what is going on.
so we all know that in php this:
echo 'hello';
print 'world';
echo gettype('test');
will return this:
hello
world
string
However, until today I was unaware that this:
echo hello;
print world;
echo gettype(hello);
will return this:
hello
world
string
What is going on here? What is happening in php's compilation process that it sees any single word as a string? Does this have a name? Does it have any utility?
If PHP can't find a function or constant by the name of hello, then yes, it treats it as a string. However, this is bad practice, and is even warned against:
>php -r 'error_reporting(E_ALL|E_STRICT);echo gettype(blah);'
PHP Notice: Use of undefined constant blah - assumed 'blah' in Command line code on line 1
So, the moral of the story is to always turn on error_reporting in PHP (just like you should always use strict and use warnings in Perl).
If you are not wrapping a piece of "string" inside quotes (be it double or single), the interpreter will try to make a guess and cast that into a String. I believe when you run that piece of PHP in error_reporting(E_ALL) you will see a notice
Notice: Use of undefined constant string - assumed 'string' in Command line code on line 1
A good practice is to always turn on error_reporting to E_ALL in development setups, but remember to turn it to less descriptive in production, you don't want people to have access to sensitive information (such as path) if your php errors out.