Doesn't class design need methods to have a return type?
Why? You aren't modifying the code itself at runtime, so the method has a return type whether it's predeclared or not. Just because it can't be enforced doesn't mean it doesn't exist — it can clearly be inferred from the code itself.
Doesn't methods signatures have specifically-typed parameters ?
Again, there's nothing to say that the method can't simply be liberal in what it receives. Get user by id? Sure, pass in a String or an integer. How does that break object-oriented-programming?
How can OOP techniques help you code in PHP if you have to always check the types of parameters received because the language doesn't enforce types ?
Here, based on the above arguments, I again fail to see why "extra checking", even if needed, renders OOP techniques powerless.
The loosely-typed languages that I am familiar with don't have method overloading, which is often used to make methods more flexible on input (while still using the same name), so I fail to see much difference from using one method and "extra checking". A diligent developer can write the same method, with the same contract, stability and security in a loosely-typed language.
When you design things using UML, then code classes in PHP with no return-typed methods and no-type parameters... Is the code really compliant with the UML design ?
Well this depends on your method itself, doesn't it? What it actually does with the inputs and what it outputs?
Typing still exists
The bottom line is, types still exist, they are just loose or weak1, and these systems can even have certain advantages.
In fact, some IDEs like those by JetBrains (IntelliJ, PHPStorm) support all kinds of type hinting using PHPDocs for PHP. As I've used it, it provides almost all the convenient warnings, click-through, code-completion, etc. that an IDE for a strongly-typed can provide.
1: Both "loose" and "weak" are just a poor grouping anyway; there are so many different type systems that these terms are likely to cause confusion. See Eric Lippert's informative perspective on this topic on Stack Overflow.
Method doc and inline example
/**
* @static
* @param mixed $id
* @return User
*/
public function getUserById($id) {
....
}
public function printUserName() {
// code completion provided on getName method because of @return
$name = $this->getUserById("5")->getName();
// type hinting for arrays
/** @var User[] $users */
$users = array(new User());
}
Casting example
public function checkUser(User $user) {
if ($user instanceof Administrator) {
/** @var Administrator $admin */
$admin = $user;
$admin->logAccess();
}
}
If I'm wrong, please let me know. :)