Going from Spaghetti PHP OOP to SOLID OOP
Reading through this code and your goals, it seems this class has two responsibilities:


Provide a Key-Value store
Get data from the database (potentially with caching)


To make it more SOLID, you can pick one of these responsibilities for this class and put the other one somewhere else.

If you wanted to use this class to provide a KV store, you would inject an array pre-filled with all of the data into the constructor rather than injecting DB information. You could then use a factory that takes those parameters to build the DataID object with the data. This removes a dependency on anything database related, simplifies your constructor, and reduces the class to a thin veneer over the underlying array. It cannot, however, get new information by itself, nor can it provide database caching. You could create an adapter class around the database result set and inject that instead of the array. The result set adapter could then handle getting additional information and caching, but this might end up replicating the concerns you have here, just somewhere else.

If you wanted to use this class as an adapter over the StorageInterface class, you would not do all the work in the constructor and simply make calls to the underlying storage object in the getID method. This allows you to simplify the constructor once again, but does not in itself provide caching. You said the StorageInterface implementation provides query-level caching, but you can create a separate adapter wrapper around it that encapsulates your SQL and caches a whole table whenever one element is retrieved from it, and can limit those caches based on table size. Once again you can use a factory method so that your external application does not need to know about this internal adapter. This option seems to fit most closely with what you want to achieve while still having better SOLID-ness.

EDIT:

Here's how this achieves better adherence to the SOLID principles:


S: This class's responsibilities have been reduced from two to one.
O: I can add additional functionality by adding decorators and adapters around the various objects to add additional functionality, without having to change those objects directly.
L: StorageInterface uses Liskov Substitution, but an adapted class around the StorageInterface can also follow Liskov Substitution by adding decorators around it to add functionality.
I: The adapters are small, client-focused APIs.
D: StorageInterface is an abstraction, and your StorageInterface adapters/decorators can also be build as abstractions.


Bonus Points:

By removing the work out of the constructor, you are adhering more closely to the Law of Demeter. Rather than asking for something to get something through it, you are asking for what you really want.