phpstan-wordpress
phpstan-wordpress copied to clipboard
have_posts() is an impure function!
stubFiles:
- tests/phpstan/wordpress-override.stub
<?php
/**
* Whether current WordPress query has results to loop over.
*
* @since 1.5.0
*
* @global WP_Query $wp_query Global WP_Query instance.
*
* @return bool
* @phpstan-impure
*/
function have_posts()
{
}
class WP_Query
{
/**
* Determines whether there are more posts available in the loop.
*
* Calls the {@see 'loop_end'} action when the loop is complete.
*
* @since 1.5.0
*
* @return bool True if posts are available, false if end of loop.
* @phpstan-impure
*/
public function have_posts()
{
}
}
Is this related to why the PHPStan reports for this:
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$list[] = [
'id' => \get_the_ID(),
'title' => \get_the_title(),
'url' => \get_permalink(),
];
}
}
\wp_reset_postdata();
While loop condition is always true.
I got this notice in phpstan once I updated to phpstan v1
Is this related to why the PHPStan reports for this:
Yes. have_posts changes its return value based on other methods of WP_Query.
Thanks, I'll just have to ignore this line per line 😅
I'll just have to ignore this line per line
You could try to edit your phpstan.neon.dist to always ignore that warning, by targetting something like:
message: '#While loop condition is always true#'
While it may catch other use-cases, it may help a bit instead of doing it line by line?
Yeah, I'd like not to ignore all those cases, because it might ignore legitimate notices 🙂 So one by one would be good alternative 😄
This isn't about WP_Query only if you wrap the while in the if it assumes it's true and always will untill the end of time.
The same happens with the ACF function have_rows used by the repeater field.
The example below gives an error 3 out of 4 times.
<?php
// normal template
if ( have_posts() ) :
while ( have_posts() ):
the_post();
endwhile;
else:
echo 'fallback template';
endif;
// custom query
$query = new WP_Query();
if ( $query->have_posts() ) :
while ( $query->have_posts() ):
$query->the_post();
endwhile;
else:
echo 'fallback template';
endif;
// ACF > including https://github.com/php-stubs/acf-pro-stubs
if ( have_rows( 'featured' ) ):
while ( have_rows( 'featured' ) ) :
the_row();
endwhile;
else:
echo 'fallback template';
endif;
// Custom Query
// No if === no error
$query = new WP_Query();
while ( $query->have_posts() ):
$query->the_post();
endwhile;
I'm willing to look into this although I have no experience with stanphp untill today... If someone has pointers I would appreciate it ;)
I have no experience with stanphp untill today...
Hello Janw!
PHPStan (not stanphp) is an OOP tool, it won't work with mysterious impure functions.
Please add @phpstan-impure to all stubs that need it. There is sed for you!
sed -i -e 's#^\s*\* @return bool True if posts are available, false if end of the loop\.$#&\n * @phpstan-impure#' vendor/php-stubs/wordpress-stubs/wordpress-stubs.php
All I can think of is a new extension that flags these functions as impure. But that sounds like a nightmare. I'm not willing to spend my time on this. You know?! WordPress!
Viktor did you handle this one already via 0c610fd or is this issue meant to be kept open for e.g. a more generic solution or something like that?
I cannot answer. There are only wrong answers. This is a 📌 pinned issue.
https://github.com/phpstan/phpstan/discussions/8822
It turns out it could be fixed without writing code! 👆🏻