Finally getting to look at your code

This is awesome. My notes:
Query
- Your needing to look up the table prefix for the given engine is something I hadn't anticipated. Your solution is clean, but the problem you run into with that is that, if I pass the secondary engine in with the engine object and not the name of the database configuration, the code has no idea what prefix to use. Concerning and frustrating. Maybe it would be better to have the DatabaseEngine abstract contain the name of the config, if it has one? That way you can pull it out of the engine itself rather than relying on the coder to supply it. Hmm... I'm not sure if that's the best way to do it or not. Thoughts?
- With the code as-is, you're calling the Config library to get the array of table prefixes. Then, if what it gives back is an array, you call Config again to get the table prefix with the appropriate array key. It would be doubly fast to just stick the key into the array you already have to get that value, rather than making another Config call
Config
- I... I have no idea why I was returning '' instead of false when exceptionOnError is off. Wtf? Actually... maybe I was doing it so I could use the return value in concatenation. Hmm. This will take more exploration. Creating a new string takes way more cycles than returning false. Do you know what you get when you concatenate a string with
false? Either way, thanks for sticking with what I already had there
- I'm torn on the order of arguments in getVal(). Ideally, it would be nice to be able to say getVal($section, $key, $subkey, $exceptionOnError), but it's so rare that you need the subkey... getVal($section, $key, false, $exceptionOnError) would be a pain after awhile. But keeping getVal($section, $key, $exceptionOnError, $subkey) feels so messy. These aren't so much notes, as they are my streams of consciousness xD. Maybe instead of making $exceptionOnError an argument in the public function, it should be an argument in a private function, then we'll have TWO public functions. a getVal-like function for throwing an exception, and a getVal-like function for returning false. So getVal($section, $key, $subkey) would throw the exception, and getValOrFalse($section, $key, $subkey) wouldn't. Or maybe getValNoError. Or the return-false version could be getVal and the exception-throwing version could be getRequiredVal. Thoughts? xD God I'm tired.
DatabaseEngineFactory
- Line 55->85 ... holy shit I can't believe I spelled "port" wrong. Thanks for the correction!
- You changed this line:
$engine = $engine ?: Config::getVal('database', 'engine');
To this line on line 90:
$engine = $engine ?: Config::getVal('database', 'engine', true);
Those two lines do exactly the same thing

The third argument is true by default. Did you mean false there?
- We shouldn't force keyed database entries to have one named "default". In PHP, there's an array method (
array_keys()) to get all the keys in an array, and they're returned in the order they've been declared in. So maybe we can see if one of them is named 'default' and use that, but if there's not, then just use the first one? Much more freedom for programmers with that.
Edit: Now I'm second-guessing myself. What if a programmer would rather the default be 'main'? Or 'primary'? Maybe going with the first declared key instead of looking for certain names would be best anyway. Thoughts?
SQLBean
- Wow, that fix was really dead easy with the changes made above. That's awesome

Beautiful code, dude!
General crap
- If you can, try to match my coding style as much as you can with this

. Everyone has their own personal preferences, but we should keep the format consistent throughout the library. Opening brace at the end of the same line that needs it, closing brace left-aligned with that line, contents 1 tab to the right of that line, else if instead of elseif, no braces around if-statement contents if the contents are one line... all that jazz. Not that I couldn't reformat it myself, but hey, I'm lazy ;-)
- If you change a function that has Javadoc (err.. PHPDoc. Whatever) on it, make sure to update the documentation
--------
Really kickass changes, most definitely

Just let me know how you feel about the above. The more I'm thinking about it, the more I really like the idea of getVal and getRequiredVal (which I can do -- not saying you have to change what you've written

I can accept your pull with that part as-is and write the update myself). I just have no idea what the best solution would be for table prefix lookups from an engine.
...and after all that, I now realize GitHub has an amazing notes system that allows you to leave overall notes in a file as well as line-specific notes. One day, I won't suck. One day ;-)
Edit: Another thought!
If we go with getVal and getRequiredVal, mabe getVal could have a fourth parameter to define what should be returned when the specified key isn't found. It could be 'false' by default, but you could pass it "" or NULL or whatever you wanted and it would return that instead. So that way, if you're doing string concatenation, you could have it return "" and you're in the clear. This is assuming, again, that you can't concatenate a string with boolean
false. Because if that works, then there's probably no need for this. Maybe.