New Functions for Active Record & Fixes - #37
Conversation
- Add fetchColumn() to DatabaseStatementInterface + PDO/mysqli adapters - Add ActiveRecord::count() and exists() via a private queryScalar() helper
- pluck() returns a single column as a flat array (NULL-safe, order/limit aware) - ids() delegates to pluck() with the primary key - queryColumn() reuses the branch-1 fetchColumn() primitive
- isDistinct flag prefixes SELECT DISTINCT on the default table.* select - pluck() honors the flag; count() deliberately ignores it - flag resets with the rest of the query state
- rowCount() on DatabaseStatementInterface + PDO/mysqli adapters - updateAll()/deleteAll() run single statements without hydration or callbacks - mysqli affected_rows read is @codeCoverageIgnore (same as lastInsertId)
- $timestamps property + protected setTimestamps() hook - insert() sets both columns, update() sets updated_at only - explicitly dirty timestamp values are never overwritten
- Named scopes are plain chainable instance methods returning $this - scope() calls them by name; throws BadMethodCallException when undefined
- beginTransaction()/commit()/rollback() on DatabaseInterface + adapters - ActiveRecord::transaction() wraps a callable; commit on return, rollback + rethrow on failure - QueryCountingAdapter fixture updated for the new interface methods
- buildSqlCallback(): strict null comparisons (===) - buildSql(): remove commented-out debug echo - rename testScopeHelperThrowsOnUndefined to match plan naming
|
Hey thanks for the PR! This is a solid set of code changes and tagging 0.8.0 for the interface adds makes sense. Couple things I have questions in that I noticed.
Thanks again for the assist in maintaining this! |
|
Good catches, both, Here's what I'm considering for fixes:
Would both be ok or should one be chosen over the other. It's literally this or a varient: if ($allowEmptyConditions === false && $this->where === null) {
throw ...
}2: I do agree with you, an array is safer. In looking into it closer I found something a little contradictory to your concern to bring to your attention and ask for some guidance how I might proceed.
Should these be 'fixed' too while I'm taking care of Slight side note: I've forked the docs and added these there (and some other things I've written on flight in examples) but I'm holding off on the PR until these were settled so the docs match 100%. Long way to say you guys won't have to deal with the docs. |
I'm back! Been continuing work on my project(Pubvana v3) and using AR for the database interaction. In this PR I've done my best to segregate what Pubvana needs to what should actually be in an AR library. Hopefully I've gotten it right (EG: No query builder UNION type stuff) if you'd like to add this to the repo. -cheers
Bulk addition of new features and some cleanup to the Active Record library. All changes build on security/identifier-escaping work already on master. I did tag as 0.8.0 given the gaggle of changes. Numbers here correspond to my internal branches referenced throughout below.
New Functions:
Found Existing
Docs
Testing
Breaking changes
Two public interfaces are extended. Because these are interfaces any external user can implement themselves, adding a method to an interface means a custom implementation that doesn't add the method will no longer satisfy the interface, hence "breaking."
DatabaseStatementInterfaceAdded
fetchColumn()(branch 1): previously the statement interface could onlyexecute()andfetch(&$object), both read into an object. There was no driver-agnostic way to read a single scalar/column value, whichcount(),exists(),pluck(), andids()all need. Adding:means anyone with a custom
DatabaseStatementInterfaceimplementation must now implement this method.Added
rowCount()(branch 5): needed to return the number of affected rows fromupdateAll()/deleteAll(). Same interface-add caveat as above.DatabaseInterfaceAdded
beginTransaction(),commit(),rollback()(branch 8): required sotransaction()can work through the adapter layer regardless of whether the underlying connection is PDO or mysqli. Same interface-add caveat:What this means in practice
Also, happy to fork the docs and add all this to it as well if you want