Entity collection best practice (separation of concerns, dependency injection, ...)
Design

Dependency injection is very useful when you have multiple implementations of a given dependency. If you don't plan implementing another Validator, then it's probably premature abstraction. I'll assume here that you have other Validator implementations.

Let me answer your questions:


The separation itself is good.
An exception is meant to be catched "whenever possible", and it is not possible in WorldCollection, since you don't know how to handle it. You need to wonder what you want your application to do when the data does not validate.

If you want WorldCollection::offsetSet to not do anything when the validation fails, then WorldValidator::validate should simply return true or false, and no exception should be thrown.

If the exception is to be catched later on in the code, then don't do anything in WorldCollection::offsetSet, since another code will take care of the issue.

You can easily mix those two approaches in order to catch some of the exception at some point, and other ones later on (which means WorldValidator::validate should always throw an exception, and return nothing).
Only if you plan on having other WorldCollections. I don't think so.
LogicException should only be launched if there is a flow in your program, ie. an exception that would never be thrown in a perfect program. RuntimeException is a base class used for errors such as OutOfBounds or Overflow. I'd use InvalidArgumentException.
I didn't understand the question. Note that instanceof is never good design, and exists to work around design errors.
ArrayAccess is a reasonable choice, it lets you do foreach on your data easily, whereas with Iterator you would have to implement a ton of methods. SplObjectStorage could be used, but only if you don't need the keys ArrayAccess provides.


Implementation


Do you want only one exception with different types, such as ERROR_CODE_INVALID_TYPE?

Why don't you use multiple exceptions?
If you want to stick with one exception, don't pass "invalid type" in the constructor, since it is always going to be the same message. Prefer to override Exception::__toString() to return "invalid type" when the type is ERROR_CODE_INVALID_TYPE.

Use offsetExists in offsetGet instead of repeating yourself?
Consider using NULL instead of null, and TRUE instead of true, even if they are case-insensitive.
$this-&gt;oValidator-&gt;validate($value) forgot a semicolon?
Don't use return if you're not going to check the return value.