tbDuplicateKeyPlugin
0.5.1beta
for sf 1.4sf 1.3sf 1.2sf 1.1sf 1.0 and Propel
MIT
tbDuplicateKeyPlugin allows you to easily extend admin generated modules to handle duplicate key errors gracefully, reporting them to the user with an appropriate, in-context form validation message instead of a 500 Server Error or an exception message.
This implementation
detects the native MySQL duplicate key error at save time. This is a Good Thing
because if we implemented this as a Symfony validator, there would
still be a race condition when two users insert an object by
the same name (or other unique field) at the same time. That approach also involves extra queries, which is a performance problem in a high-volume environment.
Developers
| Name |
Status |
Email |
Tom Boutell |
lead |
moc.evaknup <<ta>> mot
|
License
Copyright (c) 2008 Boutell.Com, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
tbDuplicateKeyPlugin
About
This code allows you to easily extend admin generated modules to handle
duplicate key errors gracefully, reporting them via the usual error handling
mechanisms instead of an exception message. This implementation
detects the native MySQL duplicate key error. This is a Good Thing
because if we implemented this as a Symfony validator there would
still be a race condition when two users insert an object by
the same name (or other unique field) at the same time.
Requirements
This code is Propel- and MySQL-specific. It wouldn't be
MySQL-specific if Propel had portable detection of
duplicate keys and it's really unfortunate that it doesn't. However
this plugin also takes advantage of a MySQL-specific command to figure out
which column caused the duplicate key error.
Usage
To use this plugin you must extend two methods in your admin-generated
action class: validateEdit() and saveObject($object) (substitute the
name of the class you're adminning for Object).
Here's an example implementation of validateEdit() for
a class called 'Venue':
public function validateEdit()
{
// We must pass the name of the model class we're editing
// (NOT necessarily the same as the name of the admin module).
if (!tbDuplicateKeyTools::validate('Venue'))
{
return false;
}
// Any other extra validation you want to do etc
return true;
}
You must also extend saveObject() (replace Object with the model class
you're adminning). Here is a sample implementation for a model class
called Venue. Note the need
to catch exceptions and pass them to tbDuplicateKeyTools::examine(),
along with the name of your admin module (often, but NOT always, the
same as the name of the model class but in LOWER CASE):
protected function saveVenue($venue)
{
try
{
parent::saveVenue($venue);
} catch Exception ($e)
{
// OUR admin module for the venue class is called venue.
// But YOURS is called whatever you named it.
tbDuplicateKeyTools::examine('venue', $e);
}
}
If the examine method recognizes a duplicate key exception, it will
stop execution by calling the forward method to retry the edit action,
after first setting a flash attribute that ensurs that your validator
picks up on the fact that a duplicate key error exists.
That's it- you're good to go! With these two changes in place,
any duplicate key errors caused by user input will automagically
result in an understandable error message pointing to the
offending field.
Note that if you have keys made up of multiple fields only the first
field will be flagged. This is a limitation of MySQL's error reporting.
Warnings
Some future version of MySQL or Propel may report duplicate key errors
in a radically different manner... though there is probably a lot of code
out there by now detecting them this way. Just don't be shocked
and amazed if Propel 2.0 or MySQL 7.0 breaks this code.
Yes, the examine method will re-throw exceptions it doesn't
recognize. This means that you can catch exceptions thrown by it if you wish.
But it will also throw an sfStopException when it successfully
detects a duplicate key error. So take care not to interfere with
exceptions of the sfStopException class.
tbDuplicateKeyPlugin outputs its error message by setting a flash
attribute as a message to the next request, then invoking the
sfRequest::forward method. Since forward() is implemented internally
and does not result in a genuinely new browser request, my expectation
is that flash attributes will work in this case even if the user is not
accepting session cookies. So this implementation should be valid even
with cookies turned off. But I have not rigorously tested that.
Your input would be appreciated.
The changes in the Symfony 1.1 and 1.2 admin generators don't
look drastic enough to break this code, so I've enabled it for those
versions as well. But I haven't tried it with those releases yet myself.
Your input would be appreciated.
Credits
tom@punkave.com
www.punkave.com
www.boutell.com
Changelog
0.5.1: markdown fixes, other documentation fixes. No code changes.
0.5.0: initial release.