Dessert #13 - A simple Config Model
Posted on 20/9/06 by Felix Geisendörfer
A lot of you probably like the idea of storing some of your applications configuration in a database since this way you can easily tweak things at run time versus having to edit configuration files on the server.
For me I found it pretty useful to just have a simple table called configs which contains two fields: "name" and "value". "name" is the primary key and it's type is varchar(255). The "value" fields type is text. After setting this up, I created a simple Model called Config and added two convenient little function named get & store to it which I can call from my controllers.
The code for the Config Model is this:
{
var $name = 'Config';
var $primaryKey = 'name';
var $validate = array('name' => VALID_NOT_EMPTY);
function get($name, $default = null)
{
$config = $this->findByName($name);
if (isset($config['Config']['value']))
return $config['Config']['value'];
else
return $default;
}
function store($name, $value)
{
return $this->save(array('name' => $name, 'value' => $value));
}
}
And usage is as simple as this:
{
var $uses = array('Config');
function beforeFilter()
{
$this->theme = $this->Config->get('theme', 'summer');
}
}
So in the example above the beforeFilter tries to get the value of 'theme' out of the configs table and in case that fails (theme isn't set), it will return 'summer' as default value.
--Felix Geisendörfer aka the_undefined
You can skip to the end and add a comment.
My database table doesn't have an id field, it's just name+value and name is the primary key. So since I told CakePHP about this setup by using $primaryKey, it will automatically either use INSERT if the config value hasn't been set before, or update if it already exists. Didn't have any problems with it so far.
Nice idea, however, I would assume that each get() would generate a separate query?
In my apps, I quite often need more than one config value in a page. What about the idea of setting it up with a function that gets all the configs from the database and storing them in the class. The get() function could then check to see if the value has already been read from the database, and if not, it will fetch it.
Although the initial select query could take a bit of time, it would mean only one query, regardless of how many config variables required.
James: Yes, every get() generates one query. The application I work on right now has less then 10 config values, so no need to optimize here. If you plan to use this in a bigger application you might want to get the entire configs table upfront and cache it as you said.
So you think doing multiple select queries is better (performance wise) than doing one intial select query for all 10 rows? I would have thought that provided you require more than 1 config value, it would be quicker to just select all rows in the config table and store them in an array?
Oh yes, performance is incredibly faster this way. Not the performance of the application, but the performance of myself getting the job done that is; ). I mean come on, how much traffic is the site you are working on right now going to get? If it's not in Alexa's top #50,000 there is almost not going to be any reason for optimzing things like that. We don't live in the days where code performance is the #1 criticial factor you should care about. CPU cycles are cheap these days, and unless you have a really good reason for doing so, you should never put performance concerns over simplicity & maintainability of your code. That's my oppinion.
I've got to agree with Felix on that point, James. If you're concerned about the performance difference between one honkin' query versus multiple tiny queries, then have you ever considered the performance loss in using cakePHP itself? Writing regular PHP without a framework would certainly chug out pages faster, so you should give it a try some time :-D Or if you're like Felix and I, you can save yourself some time and use what makes your job easier. Saving a few microseconds for the user isn't life-changing, and let's not forget view caching...
My 3 cents :) ...
IMO, performance should be a PRIMARY concern when developing an application. This is the reason why PHP gets s**t on from the programming community. PHP is seen as a lazy language wherein many programmers "wing" stuff within their apps to get by and have no reusability with their code.
Performance should start on the DB level and work up (for cake-style applications) to model, controller then view. A well thought out and fast db schema can save you unforseen time when creating the actual components (MVC's).
Onto your clever config idea ... I think "Config" should be a component, not a model. To me, models are used for repetative, interactive use within a controller.
Config::startup () should read in all config values into a class var and then use Config::get(..) to retrieve the data from the local variable. Config::store(..) should use a simple query (yes, SIGH, an actual SQL query) to enter the data into the db.
Model's are nice, they offer a nice and easy abstraction to the database but you don't need to create a model for every table in your db -- especially for tables that are only referenced a few times.
Felix & Bret, the number of potential visitors is very important in a case such as mine, where I am planning on developing an app that will be sold via the internet as a commercial web based application. Just because we are using the MVC approach is no excuse to write inefficient code! I think that regardless of our design methodology (eg MVC, procedural, etc), it is very important to optimise our code as much as possible. Also, if you run you inefficient site on a shared host, you are much more likely for your site to be suspended if your site is inefficient from a performance point of view.
Brandon, I agree with that you say that performance should be a PRIMARY concern. I'm not quite sure whether I agre with your component vs model idea, as I am quite new to MVC and CakePHP . What does everyone else think?
Brandon, James: I disagree with both of you guys bigtime. Performance as a primary concern as a general programming approach is so oldschool I can't believe anybody would suggest it. I'll get into a little bit more detail now, but you cannot make a general statment like this on my blog - no way : p.
I don't know about you guys, but I would assume you would agree with me that our all time is more or less valuable. You've probably also heard about ROI (Return on Investment), YAGNI (You Aren't Gonna Need It) and RAD (Rapid Application Development). I consider all of those 3 important to what I'm doing. So often I get into a situation where I have to decide whether I want to spent 3 hours on optimizing some piece of code which will cost, depending on the wage around $150 or if I'm gonna keep it simple and let the performance suffer. So let's say the performance loss forces me to switch the app from a $5 / month host to a $15 / month one. Applying some minor math (150 / 10) you'll find out that saving those 3 hours would actually pay for the first 2 years and 3 month of hosting the application. That's quite some time, and if performance is your #1 concern, you can easily spend a lot more hours on it. In a case like the one above I wouldn't even remotly consider spending time on optimization. CPU cycles are cheap these days and my labor is valuable, so why shouldn't I use it for more meaningful things like adding another feature?
Again, there are situations where you should focus on performance. I think your situation demands it James, but the site I'm doing right now will get 50-100 visitors / day, so I would have to be crazy to optimize it. And those people who give php programmers shit for being pragmatic are jealouse as hell.
I come from a Visual Basic background and used to do some game programming. You wouldn't believe the shit I got from C++ programmers when posting in game developer forums because I was using Visual Basic. They were talking to me like an idiot for using VB and told me to use a real language because the code your write in VB is doomed to be horrible, slow and so on. While I now would totally agree with them on all of those points I think they missed the major point: My applications were coming together 10x faster then the ones of the oh-so-skilled c++ developers. I was doing 2D and Visual Basic was fast enough for it. It was easy to use and scaled well. It was the RIGHT TOOL for the JOB. And the only problem the c++ dev's had with it was that all their ideology failed them in the real world.
I'm a big fan of the entire theory behind programming, and I often enjoy doing more work then I would need to do on some code to make it better. However, I do this out of the joy in programming and nothing else. When working on a project with a strict deadline I have to force myself into a little more pragmatic mode and focus on real world requirements. So again, if your real world requirement is to make a huge application or one that has a very small memory footprint for shared hosting, go for the optimization. If you work for a specific client where you can get a good estimate on traffic, be realistic about what need's to be optimized and what not.
So far so good, let me know if you still disagree.
Felix...
I think James brings up a great point. Building on top of his comments, most of a PHP/Cake programmers work comes from these quick, short jobs (usually only lasting maybe a week at most) where code optimization isn't necessary. But falling into these bad habits will only make it harder to break away from them later down the road. I couldn't tell you how many habits I had to get rid of when converting over to cake a year ago.
I respect you a lot when it come to programming and your "thinking outside the box" but I think you might not be looking at the larger picture here. The major cost of software isn't development -- its maintenance and upgrading. So by taking less time in development with concerns of performance (or other things) you will inevitably spend that time in the maintenance or upgrade phase of the project. Through my experience it is much easier to do it in development when you don’t have to worry about it being an issue – ever.
Who is to say that your little app someday won't be implemented into a larger project? Maybe one day, like James, you will want to package it up for commercial use.
I am not suggesting you go through and rethink ALL of your code but think about performance WHILE creating your code. In this Config example there are a few, VERY SIMPLE, ways to increase the performance of the code without extraneous thought or time invested – that was my initial point I tried to make.
BTW...
I think our site topped out at 32,000 on Alexa over this summer -- do I qualify, then, for being as passionate as I am about performance? :)
Brandon: I agree with the points you bring up, but I still think we are talking about 2 different scenarios ; ). To be a little bit more specific: I'm doing a web site for a Hotel. This Hotel has a limited amount of rooms available, and it doesn't look like they are going to expand at any point soon. So for this project I think it's very safe to estimate the traffic and optimize only to the point of meeting this requirement.
Ok, now you could say that: maybe, one of these days, I'll build a website for another Hotel, with more traffic, and then I might have to go through all of the code again and optimize it. Very true. But I can't know that. And if I would get stuck in that "What if ...?" kind of thinking, I would automatically build very bloated apps. Opimization is only one thing, but it goes on with the business logic: "What if" the client ever wants to change his booking procedure? "What if" he ever wants to change his database from MySql to Text files? "What if" he wants to add Theming to his site? "What if" ...! I mean as I already said, I think that probably both you should be concerened about optimization, because you have strong reasons for doing so. But if that reason does not exist, then I think it's a waste of time.
And as far as the stuff on this blog goes: Most of the code I post on here is not optimized as much as it could be. Whenever the optimization makes the code harder to understand, or distracts from the idea itself, I leave it out. So for little snippets like this, never expect them to be copy & paste ready without having to worry about anything else. I will make a comment on it if I think it's a completly thought out solution.
Oh and again: I believe the stuff in your last comment is true. It's just that because the majority of cars are red, it doesn't mean mine will be too ; ). Same goes for research about software development..
This post is too old. We do not allow comments here anymore in order to fight spam. If you have real feedback or questions for the post, please contact us.
What about a way to enforce unique key names? It looks like your store() method would just create mutliple records of the same name.