Thanks for the discussion guys, I think I've come out with a conclusion of Method Chaining as an OOP practice. Id say Method Chaining can be either an anti-pattern or not depending on the context, or more precisely, whether the class designed for using method chaining introduces dependency between methods. One perfectly legal case for method chaining is the usage of setter methods, as setter methods usually do not depend on one another:
In the setter method example, you can flip the order of setProperty1(), setProperty2() and setProperty3(), the script will still work. In fact, it is perfectly fine even if you remove setProperty1() from the script and it will still be able to set the other two properties nicely. Perhaps this is what you guys mean by fluent interface of setter methods? They look quite nice to me too, unless one setter method depends on another.
I see one frequent usage of method chaining is to build a query object, which can be tricky. As your query object may use lots of chaining methods like select(), where(), limit(), order(), you may have two ways to accomplish this task. The first approach is to store a query string in the query object, and dynamically concatenates this string whenever a method is called on the query object. The second approach, on the other hand, stores different parts of the query string in separate query properties, while in the end these are combined to form a complete query string when the client coder uses the fetch() method to return records. The first approach is a poor OOP practice as it introduces dependency between each query methods, if you swap the position of select(), where(), and limit(), the resulting query string can be invalid and triggering an error. The second approach, however, essentially does not violate the law of demeter as you can call these query methods in any order, while still generating the correct results:
$query->select($table)->where($whereClause)->limit($limit)->order($order); // returns valid records for both approaches
$query->limit($limit)->order($order)->where($whereClause)->select($table); // may only return valid records for second approach
I'd say a rule of thumb is to swap the order of these chained methods being called, and see whether the script is still capable of generating appropriate results. If so, your method chaining does not violate law of demeter as you are simply providing a fluent interface rather than introducing dependency between methods. Otherwise, its a good idea to get rid of these chained methods as unwanted dependencies breaks the law of demeter rule.