Doing hook_update_N() when module is installed
I'm doing a module for infrastructure which is all about applying configuration updates, and it does only configuration, nothing else. I'd like to create hook_update_N() functions, but I'd also like all of them to be run when the module is installed. Is there any "correct" way to do this? Many modules implement the functionality in both hook_install and hook_update_N, and that's fine for database-only issues, which is what these were built around (like schema changes). But it doesnt' really make sense for site config changes. Obviously, I can run the hook functions from hook_install(), in direct or indirect ways. Suggestions? Thanks, -Randy -- Randy Fay Drupal Development, troubleshooting, and debugging randy@randyfay.com +1 970.462.7450
To run an action the first time a module is installed, use hook_enable() in D5 or D6. - Ken On Thu, Nov 12, 2009 at 5:08 AM, Randy Fay <randy@randyfay.com> wrote:
I'm doing a module for infrastructure which is all about applying configuration updates, and it does only configuration, nothing else. I'd like to create hook_update_N() functions, but I'd also like all of them to be run when the module is installed. Is there any "correct" way to do this? Many modules implement the functionality in both hook_install and hook_update_N, and that's fine for database-only issues, which is what these were built around (like schema changes). But it doesnt' really make sense for site config changes. Obviously, I can run the hook functions from hook_install(), in direct or indirect ways. Suggestions? Thanks, -Randy -- Randy Fay Drupal Development, troubleshooting, and debugging randy@randyfay.com +1 970.462.7450
-- Ken Rickard agentrickard@gmail.com http://ken.therickards.com
Ken Rickard wrote:
To run an action the first time a module is installed, use hook_enable() in D5 or D6.
Yes, this works, but be aware that any time the modules is disabled and re-enabled, this hook will fire. My suggestion would rather be to just call the appropriate hook_update_N() within the hook_install(). It may look a bit of a kludge, but it is the safer thing to do. Nancy E. Wichmann, PMP Injustice anywhere is a threat to justice everywhere. -- Dr. Martin L. King, Jr.
On Thu, 2009-11-12 at 08:55 -0500, Nancy Wichmann wrote:
My suggestion would rather be to just call the appropriate hook_update_N() within the hook_install(). It may look a bit of a kludge, but it is the safer thing to do.
I often does some thing like: function _mymodule_some_new_really_important_business_stuff() { // Bla bla } function mymodule_install() { // Some stuff _mymodule_some_business_stuff(); // Some other stuff } function mymodule_update_N() { // Some stuff again _mymodule_some_business_stuff(); // Some other stuff again } To remove some ambiguity. It does nothing more than calling the mymodule_update_N() function into the hook_install(), but it allows you to put other things that don't have to be called at install in the same hook_update_N() implementation. Pierre.
I dislike calling update functions in the install hook. Update functions change a lot over time, so this creates maintenance issues (it's easy to forget that the old update is no longer valid to call, and every new update means some refactoring). Also, for settings the install function should only set up good defaults, and the update function should only change settings when the old setting was no longer valid or it's entirely new, so they really don't even operate on the same scope. Some duplication of .install code is a lesser evil, and a helper function can be appropriate. For settings, I prefer to just put the defaults in the code when calling variable_get and not have to deal with the .install at all. There can be some minor duplication, but I never have to worry about the DB being in an invalid state. - Ken Winters On Nov 12, 2009, at 9:09 AM, Pierre Rineau wrote:
On Thu, 2009-11-12 at 08:55 -0500, Nancy Wichmann wrote:
My suggestion would rather be to just call the appropriate hook_update_N() within the hook_install(). It may look a bit of a kludge, but it is the safer thing to do.
I often does some thing like:
function _mymodule_some_new_really_important_business_stuff() { // Bla bla }
function mymodule_install() { // Some stuff _mymodule_some_business_stuff(); // Some other stuff }
function mymodule_update_N() { // Some stuff again _mymodule_some_business_stuff(); // Some other stuff again }
To remove some ambiguity. It does nothing more than calling the mymodule_update_N() function into the hook_install(), but it allows you to put other things that don't have to be called at install in the same hook_update_N() implementation.
Pierre.
On Thu, 12 Nov 2009 Nancy Wichmann wrote:
My suggestion would rather be to just call the appropriate hook_update_N() within the hook_install(). It may look a bit of a kludge, but it is the safer thing to do.
And anyone finding code where the hook_update_N is called from within hook_install should open a critical bug report immediately. Hook_install is reserved for installing the database schema. Hook_update_N is reserved for updating the database schema. It is not a safe thing to call hook_update_N from hook_install. -- Earnie -- http://r-feed.com/ -- http://for-my-kids.com/ -- http://www.4offer.biz/ -- http://give-me-an-offer.com/
I keep learning every day - and I'm glad to know about hook_enable(), which I didn't know about. I don't think it answers my question, though, since I'm concerned about taking actions at install time, which would be hook_install(). And in my particular case, the install actions are the same as the set of hook_update_N(). The only way I know to include all those in hook_install() is either to duplicate code or to make a runner function. Both ugly. -Randy On Thu, Nov 12, 2009 at 2:35 AM, Ken Rickard <agentrickard@gmail.com> wrote:
To run an action the first time a module is installed, use hook_enable() in D5 or D6.
- Ken
On Thu, Nov 12, 2009 at 5:08 AM, Randy Fay <randy@randyfay.com> wrote:
I'm doing a module for infrastructure which is all about applying configuration updates, and it does only configuration, nothing else. I'd like to create hook_update_N() functions, but I'd also like all of them to be run when the module is installed. Is there any "correct" way to do this? Many modules implement the functionality in both hook_install and hook_update_N, and that's fine for database-only issues, which is what these were built around (like schema changes). But it doesnt' really make sense for site config changes. Obviously, I can run the hook functions from hook_install(), in direct or indirect ways. Suggestions? Thanks, -Randy -- Randy Fay Drupal Development, troubleshooting, and debugging randy@randyfay.com +1 970.462.7450
-- Ken Rickard agentrickard@gmail.com http://ken.therickards.com
-- Randy Fay Drupal Development, troubleshooting, and debugging randy@randyfay.com +1 970.462.7450
On Thu, 12 Nov 2009 Randy Fay wrote:
I keep learning every day - and I'm glad to know about hook_enable(), which I didn't know about.
I don't think it answers my question, though, since I'm concerned about taking actions at install time, which would be hook_install(). And in my particular case, the install actions are the same as the set of hook_update_N(). The only way I know to include all those in hook_install() is either to duplicate code or to make a runner function. Both ugly.
Why would hook_update_N be the same as hook_install? The hook_install is for installing the database as described in the hook_schema. The hook_update_N is reserved for schema changes. The hook_enable can be used to execute your ``runner function'' as long as the ``runner function'' isn't modifying the database schema. You need to be more specific with what you're doing in hook_install and hook_update_N. You may also be interested in hook_requirements. -- Earnie -- http://r-feed.com/ -- http://for-my-kids.com/ -- http://www.4offer.biz/ -- http://give-me-an-offer.com/
Thanks for your comments on this! While you're right that the original intent of hook_install() is to do a * schema* setup and the original intent of hook_update_N() it to update that when change occur down the line, they are both actually and widely used to set up the Drupal configuration in non-schema ways so that it's ready for the module. You yourself mentioned in a later message a variable_set() which is a configuration change, not a schema change. I *think* that the reality is that these two functions are often used in a variety of ways to make sure configuration is correct for the current version of the module, not just in terms of schema. You mention the idea of setting up something for cron to do... but that would be a privately implemented hook_update_N, woudn't it? In my case, which is a bit extreme, I'm writing a module whose only job is to do one-off configuration changes to staging*.drupal.org. There are 10 of these machines, and their configuration is slightly different from Drupal.org, but they are occasionally reinstalled with D.o's database. That means that the install needs to work to set the config correctly, and also that when a config change is introduced, hook_update_N (or a similar technique) needs to take care of it. We're trying to avoid reconfiguring everywhere. As others have mentioned, this pattern is quite common. A valuable discussion. I'm interested in hearing more. -Randy On Fri, Nov 13, 2009 at 11:00 AM, Earnie Boyd <earnie@users.sourceforge.net>wrote:
On Thu, 12 Nov 2009 Randy Fay wrote:
I keep learning every day - and I'm glad to know about hook_enable(),
which I didn't know about.
I don't think it answers my question, though, since I'm concerned about taking actions at install time, which would be hook_install(). And in my particular case, the install actions are the same as the set of hook_update_N(). The only way I know to include all those in hook_install() is either to duplicate code or to make a runner function. Both ugly.
Why would hook_update_N be the same as hook_install? The hook_install is for installing the database as described in the hook_schema. The hook_update_N is reserved for schema changes. The hook_enable can be used to execute your ``runner function'' as long as the ``runner function'' isn't modifying the database schema. You need to be more specific with what you're doing in hook_install and hook_update_N. You may also be interested in hook_requirements.
-- Earnie -- http://r-feed.com/ -- http://for-my-kids.com/ -- http://www.4offer.biz/ -- http://give-me-an-offer.com/
-- Randy Fay Drupal Development, troubleshooting, and debugging randy@randyfay.com +1 970.462.7450
On Fri, 13 Nov 2009 Randy Fay wrote:
Thanks for your comments on this!
You're welcome. Let me apologize for being late in responding. Other duties kept me off list for quite a while.
While you're right that the original intent of hook_install() is to do a * schema* setup and the original intent of hook_update_N() it to update that when change occur down the line, they are both actually and widely used to set up the Drupal configuration in non-schema ways so that it's ready for the module. You yourself mentioned in a later message a variable_set() which is a configuration change, not a schema change.
I do understand that hook_install and hook_update_N have been misused to help a package maintain sanity. It is that misuse that needs to be addressed by providing either updated documentation for hook_install and hook_update_N to allow for the unintended use or to provide instruction for how to control the variable default values of a package during install and upgrade phases.
I *think* that the reality is that these two functions are often used in a variety of ways to make sure configuration is correct for the current version of the module, not just in terms of schema.
Yes, I agree that they have been used this way but shouldn't be. Perhaps a specialized menu callback that is created during the install or update phases that can is then executed on first use and removed from then removed from the router table is what is needed for this. Only the install or update phase would create the menu callback within the menu router table.
You mention the idea of setting up something for cron to do... but that would be a privately implemented hook_update_N, woudn't it?
No, a variable can be reset outside of the install/update phase so that it can be executed manually if desired. In D7 hook_update_N will only be allowed to be executed once.
In my case, which is a bit extreme, I'm writing a module whose only job is to do one-off configuration changes to staging*.drupal.org. There are 10 of these machines, and their configuration is slightly different from Drupal.org, but they are occasionally reinstalled with D.o's database. That means that the install needs to work to set the config correctly, and also that when a config change is introduced, hook_update_N (or a similar technique) needs to take care of it. We're trying to avoid reconfiguring everywhere.
The thing I dislike about this is you are requiring a installation of an update to your module just to make a configuration change. If instead you put the changes in a INI file type and create a hook_cron (or even a hook_init if the code doesn't take very long) to check for a new file date you can make the configuration changes without shutting down the site for update.php.
As others have mentioned, this pattern is quite common.
INI files are for configuration. It makes sense to use what is already available for configurations and PHP can read them for you to the point that it returns an associative array of values. You can even have a hierarchical tree array.
A valuable discussion. I'm interested in hearing more.
Yes, I agree and I would like to hear more as well. -- Earnie -- http://r-feed.com/ -- http://for-my-kids.com/ -- http://www.4offer.biz/ -- http://give-me-an-offer.com/
We've run in this pattern a lot with economist.com. We avoided code duplication for a while and just ran all our updates in hook_install(). That became awful after a while since were doing and undoing things that had changed over time during hook_install. Now, we set ourselves up to the latest, good configuration in hook_install(). In a few cases, that does mean calling into an update function directly but most of the time we just set the variables and such in both the install and update hooks. Thats the drupal way, right now. Also, I think Ken meant hook_install, not hook_enable when he offerred a place to do one-time install related activity. hook_enable is potentially run many times.
Yes, Moshe is right. hook_install() is better, though I prefer the hook_enable / hook_disable combo to running specific "must have" routines in hook_update_N. - Ken On Thu, Nov 12, 2009 at 4:07 PM, Moshe Weitzman <weitzman@tejasa.com> wrote:
We've run in this pattern a lot with economist.com. We avoided code duplication for a while and just ran all our updates in hook_install(). That became awful after a while since were doing and undoing things that had changed over time during hook_install. Now, we set ourselves up to the latest, good configuration in hook_install(). In a few cases, that does mean calling into an update function directly but most of the time we just set the variables and such in both the install and update hooks. Thats the drupal way, right now.
Also, I think Ken meant hook_install, not hook_enable when he offerred a place to do one-time install related activity. hook_enable is potentially run many times.
-- Ken Rickard agentrickard@gmail.com http://ken.therickards.com
The pattern of hook_update_N() being related in any way to the install functions is an unfortunate side effect of both being in the same file. As I understand it, they should ideally remain separate: No update function should be called anywhere in the module, nor call any of the other functions (particularly hook_schema). This ensures that a) update functions can safely be left as-is when the rest of the code changes, and can be relied on to keep a clean upgrade path, and b) old update functions can safely be deleted. A little duplicated code for a new table is not so bad... On Fri, Nov 13, 2009 at 1:08 AM, Ken Rickard <agentrickard@gmail.com> wrote:
Yes, Moshe is right. hook_install() is better, though I prefer the hook_enable / hook_disable combo to running specific "must have" routines in hook_update_N.
- Ken
On Thu, Nov 12, 2009 at 4:07 PM, Moshe Weitzman <weitzman@tejasa.com> wrote:
We've run in this pattern a lot with economist.com. We avoided code duplication for a while and just ran all our updates in hook_install(). That became awful after a while since were doing and undoing things that had changed over time during hook_install. Now, we set ourselves up to the latest, good configuration in hook_install(). In a few cases, that does mean calling into an update function directly but most of the time we just set the variables and such in both the install and update hooks. Thats the drupal way, right now.
Also, I think Ken meant hook_install, not hook_enable when he offerred a place to do one-time install related activity. hook_enable is potentially run many times.
-- Ken Rickard agentrickard@gmail.com http://ken.therickards.com
-- Nothing beside remains. Round the decay Of that colossal wreck, boundless and bare, The lone and level sands stretch far away. --------------------------------------------- AOL: realarancaytar / 282026638 XMPP: arancaytar.ilyaran@gmail.com PGP: http://ermarian.net/downloads/0x27CA5C74
On Thu, 12 Nov 2009 Randy Fay wrote:
I'm doing a module for infrastructure which is all about applying configuration updates, and it does only configuration, nothing else.
I'd like to create hook_update_N() functions, but I'd also like all of them to be run when the module is installed.
Is there any "correct" way to do this? Many modules implement the functionality in both hook_install and hook_update_N, and that's fine for database-only issues, which is what these were built around (like schema changes). But it doesnt' really make sense for site config changes.
Obviously, I can run the hook functions from hook_install(), in direct or indirect ways.
Suggestions?
I think I would use a variable_set in hook_install and hook_update_N to say there are configuration changes and then use a hook_cron or batch operations to make the actual changes. As you've noted hook_install and hook_update_N are reserved for DB schema changes and hook_enable doesn't feel correct either. Using the variable_set you could create a settings tools page that will allow the user to re-execute the configuration changes if necessary. -- Earnie -- http://r-feed.com/ -- http://for-my-kids.com/ -- http://www.4offer.biz/ -- http://give-me-an-offer.com/
participants (8)
-
Arancaytar Ilyaran -
Earnie Boyd -
Ken Rickard -
Ken Winters -
Moshe Weitzman -
Nancy Wichmann -
Pierre Rineau -
Randy Fay