Skip to content

2.x Make object constructors final#2660

Merged
Levdbas merged 5 commits into2.xfrom
2.x-phpstan-final-constructors
May 26, 2023
Merged

2.x Make object constructors final#2660
Levdbas merged 5 commits into2.xfrom
2.x-phpstan-final-constructors

Conversation

@gchtr
Copy link
Copy Markdown
Member

@gchtr gchtr commented Oct 25, 2022

Related:

Issue

PHPStan reports "Unsafe usage of new static()" for some objects on level 0. What this means and how to solve this can be read in https://phpstan.org/blog/solving-phpstan-error-unsafe-usage-of-new-static.

Solution

Make the object constructors final. Not being able to overwrite a constructor seems like a good idea to me. As noted in the linked post:

So the PHPStan rule protects you from accidentally breaking your code when extending the class and defining a different constructor.

By making the constructors final, I already ran into an issue in PagesMenu, where I used a custom constructor. Removing the constructor and just updating the values on the object (or through a custom method) works fine.

This change was already discussed in #2203 (comment). In that discussion, there’s an example that wouldn’t work anymore with the change.

2. Making the constructor final precludes any user in the future doing anything involving a custom constructor. For example, I might want to do this:

class MyPost extends Post {
  protected function __construct($stuff, $things) {
    // do something special with $stuff and $things
  }

  public static function build( WP_Post $wp_post ) {
    [ $stuff, $things ] = SomeApi::special_sauce();
    return new static($stuff, $things);
  }  
}

Am I wrong to assume that this could be rewritten with a custom method do_something() that doesn’t change the constructor?

class MyPost extends Post {
  protected function do_something($stuff, $things) {
    // do something special with $stuff and $things
  }

  public static function build( WP_Post $wp_post ) {
    [ $stuff, $things ] = SomeApi::special_sauce();
    $object = new static($wp_post);

	$object->do_something($stuff, $things);
  }  
}

Impact

With final constructors, it will be easier to update constructors in the future, because we will not break backwards compatibility automatically. Otherwise, we’d have to assume that any constructor could have been overwritten.

Usage Changes

We won’t be able to overwrite the constructors in classes that extend the Timber core object. But it will still be possible to update the objects with other custom methods as shown above.

Considerations

In case we need some other functionality to make it easier to solve a certain use case, I’m sure we can come up with a proper API for that that doesn’t involve custom constructors.

Testing

Nothing in particular.

@gchtr gchtr added the 2.0 label Oct 25, 2022
@gchtr gchtr mentioned this pull request Nov 4, 2022
1 task
@gchtr gchtr marked this pull request as ready for review November 4, 2022 06:39
@gchtr gchtr added the Ready for Review Ready for a contrib to take a look at and review/merge label Dec 30, 2022
Base automatically changed from 2.x-phpstan-level-0 to 2.x-phpstan-setup January 24, 2023 17:01
Base automatically changed from 2.x-phpstan-setup to 2.x January 24, 2023 17:27
@gchtr gchtr mentioned this pull request May 17, 2023
30 tasks
Levdbas
Levdbas previously approved these changes May 21, 2023
Copy link
Copy Markdown
Member

@Levdbas Levdbas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a logical thing to do. I do think we need to document this change in the upgrade guide as well for folks that extended these classes in the past and maybe have overwritten the constructor?

nlemoine
nlemoine previously approved these changes May 26, 2023
Copy link
Copy Markdown
Member

@nlemoine nlemoine left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks @gchtr !

@gchtr gchtr dismissed stale reviews from nlemoine and Levdbas via 73d96d8 May 26, 2023 11:16
@gchtr
Copy link
Copy Markdown
Member Author

gchtr commented May 26, 2023

@Levdbas I added the notes in the Upgrade Guide: 73d96d8 (#2660). I’d be glad about a quick check by an additional pair of eyes 👀 .

After that, we can merge this.

Copy link
Copy Markdown
Member

@Levdbas Levdbas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this seems good. Maybe we can add a howto guide on what the recommended way is to extend a Timber object and how to call it from your code. But that is out of the scope of this PR.

@Levdbas Levdbas merged commit 10c5acd into 2.x May 26, 2023
@gchtr gchtr deleted the 2.x-phpstan-final-constructors branch May 26, 2023 12:30
@gchtr
Copy link
Copy Markdown
Member Author

gchtr commented May 26, 2023

@Levdbas Thanks!

I think we already covered how to extend Timber objects in https://timber.github.io/docs/v2/guides/extending-timber/, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2.0 Ready for Review Ready for a contrib to take a look at and review/merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants