I know shells can be uploaded via sql injection, remote file inclusion and exploiting the web app's own upload mechanism. Are there any other ways to upload a shell to a website and be able to execute commands?
You don't just have to be concerned by the ability for the user to upload a shell, but also by what exploitation of your code could achieve the same thing. There are many, many websites out there which use PHP commands such as
exec() on user submitted data (from $_POST or $_GET) without doing any kind of validation on them. These issues can be combated by properly escaping untrusted information before using it on the command line, or refactoring to avoid having to use the system shell at all (perhaps such that you can enable Safe Mode and disable dangerous functions such as these in production).
Another method in addition to those you mentioned in terms of actual malicious filed upload is the HTTP PUT request.