覆盖父方法得到了

Why does the code below:

class A {   
    public function foo() {}
}

class B extends A { 
    private function foo() {}
}

generates an fatal error while this:

class A {
    private function foo() {}   
}

class B extends A {
    public function foo() {}    
}

doesn't although the documentation says "If the child doesn't see the parent's private methods, the child can't override them"?

It is all about semantic. In first example in method foo of class B you can call parent method foo of class A using parent::foo(), but he is a private.

So let's analyze what you have:

class A {
    private function foo() {}   
}

class B extends A {
    public function foo() {}    
}

Here class A has a private method, and since it's private it's not seen in class B. So in class B you can create method with the same name. It's not overriding, it's just creating method with the same name.

And in this example:

class A {   
    public function foo() {}
}

class B extends A { 
    private function foo() {}
}

Method A::foo is public and you can override it in class B. But as it's public, visibility of children method shouldn't be stricter then parent one. So you can't have B::foo as private, only public.