nexxai's avatar
Level 37

Open-ended question about phpstan / larastan level 8 errors

So I've been working through the larastan issues on my current app by increasing the phpstan strictness level by 1, then fixing the found problems, then increasing by 1, fixing the problems, etc., but I'm now at level 8 and I'm seeing a bunch of VERY similar issues which I think points to a fundamental misunderstanding I must have about how things work, and so I want to use this as a learning opportunity.

Nearly every error showing up comes as some form of I'm assuming something will exist, but in theory it could be null:

Cannot call method methodName() on static(App\Models\Model)|null.
Cannot access property $id on App\Models\Model|null.
Method App\Models\Model::methodName() should return App\Models\OtherModel but returns App\Models\OtherModel|null.

Reading the text, it makes it pretty obvious what the problem is: at some point there was a chance that the method or property could have been passed in as null, so it's possible I'm going to try and access a property or method on a null object and that's going to fail.

I get the "what". But what I don't get is the "how".

Do I just put a bunch of if (!isset($model->property)) { throw new Exception('Missing model'); } conditionals around my code? That seems like adding a bunch of clutter, but maybe that's just how everyone does it?

I realize this is a very vague question and has lots of opportunity for "well it depends on your code" but I'm not looking for exact answers to one of the specific errors. What I'm looking for is: what is your thought process when you're building an app to avoid issues like these in the first place? What are the more foundational things that I'm probably not doing that are leading to issues like this?

I've learned everything I know from the Laravel docs and various video series here on Laracasts so there are definitely going to be gaps in my knowledge and this feels like a really important one that I should fill.

Thanks!

0 likes
1 reply
LaryAI's avatar
Level 58

Your question is a good one and it's great that you're using this as a learning opportunity. The errors you're seeing are related to the concept of null safety. In PHP, an object variable can hold either an object or null. If you try to call a method or access a property on a null, you'll get a fatal error.

The static analysis tool phpstan/larastan is warning you about these potential issues. It's telling you that there are places in your code where you're assuming an object will always exist, but there's a chance it could be null.

To avoid these issues, you can use a few strategies:

  1. Null coalescing operator (??): This operator is used to check if a variable is set and not null. If it is, it returns the first operand, otherwise it returns the second operand.
$model = $model ?? new Model();
  1. Optional helper: Laravel provides an optional() helper function that allows you to access properties or call methods on an object. If the object is null, optional() will return a new instance of the Optional class, and no methods or properties will be called.
$id = optional($model)->id;
  1. Null safe operator (?->): PHP 8 introduced the null safe operator. If the object is null, null is returned. If it's not, the method or property is called.
$id = $model?->id;
  1. Check before use: As you mentioned, you can always check if an object is null before using it. This can be a bit verbose, but it's a surefire way to avoid null errors.
if ($model !== null) {
    $id = $model->id;
}

Remember, the goal is to ensure that you're not trying to access methods or properties on a null object. How you achieve that depends on your specific use case and coding style.

Please or to participate in this conversation.