This method may look good to an untrained eye. However, this method has some serious problems that are not obvious when first looking at it. StudentRegistry returns a Student object, getCourse off the Student object returns a Course object which has a getGrade method. However, what happens when say a student doesn't exist, maybe someone mistyped the name, or a student left the school. What happens if we mistype the course name and the course doesn't exist? What happens if there is no grade for the student in the course? Most people I've seen opt to return null or false when these things happen. This causes an issue for the next chained call down the line:

PHP Fatal error: Call to a member function getCourse() on a non-object in ...

Well what can we do to fix this? One approach is to keep the existing null or false interface and just stop chaining. Let's say if the developer chose to return null when things are not found:

Another approach to keep the method chaining is instead of returning null or false, you return an object of say Student or Course. However, you come up with a way to represent these objects as an empty instance, so they keep the same expectations within a method chain.

The other way is to use Option

Instead of having your methods return null, false, or some odd class instance that represents an empty Student or Course, make each method return an Option type.

This may not be as pretty as the first chaining method we had before, but it's safe, and it avoids a lot of sanity checks. Yet another appraoch I should mention, make your own specific class that is similar to Option with no methods but __call, and use magic methods to do what map() does. In my personal opinion, however, that's too much implicit magic going on. I like to make it obvious what the methods return, and I still think the Option pattern may not be as brief as that approach. This is much cleaner as it's more obvious what is going on. I'll leave it up to the reader to decide.