Ok, I think I'm beginning to understand this better. Thanks a lot for the explanation darkagn. I really appreciate it
Abstract classes can also be used to hide complex code, while still being extensible.
Say implementing the Animal class was quite involved and complex, now someone who didn't know about Animals wanted to use the features of Animals but didn't want to go into the gory details could use it to model a Reptile with limited knowledge. (A better example would be, if you wanted to download email, but didn't want to go into the details of the POP3 or IMAP protocol, you could use an abstract POP3 class)
A good model of relationships:
If Reptile extends Animal, then you know an Animal is more general then a Reptile. These make it easier to make sense of the relationships in a bunch of code.
A way of defining interfaces, guides or structure
If there is an Animal abstract class, then all types of animals must extend the animal class to also be animals. This gives a single interface within a PHP application. A real example would be a abstract Storage class providing an interface for Databases, Sessions, File storage etc. Down the chain, the Database class could be abstract also for the different Database types (mysql, sqlite, flat file, etc.). This provides a level of control, structure and order within the app and is also used as a base to implement other programming patterns successfully.
Modular, less conflicting, good for Teamwork etc.
When working with a team, abstract classes really make it easier to understand what the others are doing, and contribute also. Each person could be working on separate functionality that share the same common base (abstract class) without conflict.
Not to forget making it easier to modify stuff later on. The difference between having to fix up a bunch of procedural code, and those with well defined relationships is huge.