Reputation: 481
I wanted to know if there was a good practice for list of values management. For example I have a database table logs as following :
--------------- | logs | |-------------| | id | | idLogType | | message | | date | ---------------
My question is about the field "idLogType". I know that an enum is not the good way to handle this kind of field because if I want to add new values I have to ALTER the table. So I'm going to create a list of values.
What is your recommandation to handle list of values ?
class LogTypeValues {
const LOGTYPE_CREATION = 1;
const LOGTYPE_EDITION = 2;
const LOGTYPE_DELETION = 3;
private $_logTypes = array();
public function __construct() {
$this->_logTypes[self::LOGTYPE_CREATION] = "Creation";
$this->_logTypes[self::LOGTYPE_EDITION] = "Edition";
$this->_logTypes[self::LOGTYPE_DELETION] = "Deletion";
}
public function getId($logType) { ... }
public function getLogType($id) { ... }
}
$request = $pdo->prepare('INSERT INTO logs SET idLogType = :idLogType, ...');
$request->execute(array('idLogType' => LogTypeValues::LOGTYPE_CREATION));
------------ | logTypes | ------------ | id | | logType | ------------
<?php
$request = $pdo->prepare('INSERT INTO logs SET idLogType = 1, ...');
$request->execute(array());
------------ | logTypes | ------------ | id | | logType | ------------
class LogTypeValues {
const LOGTYPE_CREATION = 1;
const LOGTYPE_EDITION = 2;
const LOGTYPE_DELETION = 3;
}
What do you thing about these 3 methods?
Upvotes: 13
Views: 3961
Reputation: 1624
What works for me is DB only because I tend to do database first approach when designing backend systems.
------------
| logTypes |
------------
| id |
| logType |
| code |
------------
id := generated database id
logType := varchar indicating the full name of the constant (i.e. "LOGTYPE_CREATION")
code := varchar representing a unique short length name or alias for quick and easy use in code (i.e. "LCR")
In this case this kind of constants might not be used in another relationships in your DB design, if that so, I would opt for the pure code base approach. But if they might appear on a relationship in the future then the DB approach would be the best for me.
Upvotes: 0
Reputation: 183
I also faced the similar situations a few times. Obviously, there are pros and cons of all those options mentioned above, and I haven't made my mind either. That's why I found this thread.
So far my preferred way is to use option 1, i.e., only storing constants in the application's source code (PHP/Java etc.). Its main advantage is to reduce unnecessary DB hits. Although some of you may say it's very small, but DB connection is often the bottle neck of lots of web applications. The other advantage is that it reduced the programming complexity.
The only thing I did in addition to what has been mentioned in this thread is to add a note to the comments in both the application source code and the related DB table columns to cross refer each other. This way, I tried my best to remind future developers to sync these two places if there is any change due to happen.
Upvotes: 3
Reputation: 1092
My favorite solution would be:
Stores log types in database:
CREATE TABLE logTypes (
id (SMALLINT, PK)
code VARCHAR(32) UNIQUE
)
Create constants in code
class logTypes {
const CREATE_USER = 1;
const EDIT_USER = 2;
...
}
and choose a sync policy:
Example:
SELECT * FROM logs JOIN logTypes USING logtype_id WHERE logType LIKE "% CREATION"
Upvotes: 5
Reputation: 29629
This is a great question - and reasonable people will have different opinions, depending on your definition of "good".
Option 1 makes the PHP work nicely, but means that when you want to query the log, you need to have the constants in two places - typically, the log viewer is not the same application as the log writer. And you have to write some custom logic to translate your integers in the database into human-readable strings. If you have more than one application writing to the log database, keeping the constants in sync between them all becomes important - if application 1 thinks logType 1 = "User error" and application 2 thinks it's "system error", the whole thing falls apart.
Option 2 faces the opposite problem - how does your PHP code "know" that the database believes logType 1 to be "user error"? You definitely do not want to have magic numbers in the PHP codebase.
Option 3 notionally keeps both systems in sync - but now you have to find a way of synchronizing the database with your PHP constants file. There are a variety of logical routes to do this - but none are trivial.
As I am lazy and paranoid about bugs creeping in, I usually don't use integers for this - instead, the PHP code writes a string representing the log type to the database, from a constants file.
Upvotes: 3
Reputation: 522155
More or less unstructured thoughts:
logType
in the database directly.ENUM
for the logType
column therefore also makes perfect sense. If you want to add log types, you need to alter the table... so what? That's not something that should happen very often, you need to alter your code anyway to add a new constant, and you should have schema migration code in place anyway that makes it trivial to add a new SQL enum value as well.So, this seems the best solution to me:
LogTypeValues::CREATION = 'creation'
logType
column of type ENUM('creation', ...)
Upvotes: 1