First of all, I would disagree with this statement:
Favour exceptions over error codes
This is not always the case: for example, take a look at Objective-C (with the Foundation framework). There the NSError is the preferred way to handle errors, despite the existence of what a Java developer would call true exceptions: @try, @catch, @throw, NSException class, etc.
However it is true that many interfaces leak their abstractions with the exceptions thrown. It is my belief that this is not the fault of the "exception"-style of error propagating/handling. In general I believe the best advice about error handling is this:
Deal with the error/exception at the lowest possible level, period
I think if one sticks to that rule of thumb, the amount of "leakage" from abstractions can be very limited and contained.
On whether exceptions thrown by a method should be part of its declaration, I believe they should: they are part of the contract defined by this interface: This method does A, or fails with B or C.
For example, if a class is an XML Parser, a part of its design should be to indicate that the XML file provided is just plain wrong. In Java, you normally do so by declaring the exceptions you expect to encounter and adding them to the throws
part of the declaration of the method. On the other hand, if one of the parsing algorithms failed, there's no reason to pass that exception above unhandled.
It all boils down to one thing:
Good interface design.
If you design your interface well enough, no amount of exceptions should haunt you.
Otherwise, it's not just exceptions that would bother you.
Also, I think the creators of Java had very strong security reasons to include exceptions to a method declaration/definition.
One last thing: Some languages, Eiffel for example, have other mechanisms for error handling and simply do not include throwing capabilities. There, an 'exception' of sort is automatically raised when a postcondition for a routine is not satisfied.
There is no single proper approach to your problems even within MVC pattern so simple answer to your questions does not exist.
1 Error handling
If you are using the PDO you can change error handling by setting PDO::ATTR_ERRMODE so you don't have to use exceptions but regardless of the way errors are returned it is a programmers responsibility to handle them properly.
If your method is returning false if the user doesn't exists then the controller should check what value was returned. There is no such thing as "controller assumes" it only means that the programmer assumed and didn't check returned value.
There are different errors which should be handled in different way some of them may require only showing error message some of them may be critical (like no db connection). You can use messages, views or additional controller to handle errors.
2 The proper way to show a view
Code from your example would be usually handled by the layout (header, footer, different element placement) and by the controller (using different views depending on the request). It is not good idea to use 'include' directly rather wrap it in the method. You can also create view class which would be responsible for handling views. view != .phtml
3 Managing user rights
In MVC pattern used for web applications there is usually additional "front controller" and permission checking will be handled there. You have to check for permission with each request and each request will require access to specific controller/method if you implement proper ACL it should resolve all your problems with user rights.
Best Answer
You are correct to say you should not throw HTTP specific exceptions in the service layer. The service layer should not have any knowledge of http things.
Most server frameworks have a top level exception handler and an error handling middleware. That top level exception handler could catch any exceptions not handled by your code and return 500 Internal server error.
Usually you can customize that and say okay if it's this language level exception, use this http response. I don't know the framework you are using, as an example in asp.net, when we throw (System.Collections.Generic) KeyNotFoundException then on the top level we return 404. It's not perfect, but it better than directly coupling the two.
Look here: https://docs.nestjs.com/exception-filters