Upgrading an Existing Add-on

AndyB

Well-known member
I would like some clarification on Upgrading an Existing Add-on.

My add-on "Flag Thread" uses the Installation Code and Uninstallation Code fields to alter the xf_thread table during installation and uninstallation.

My question is, what happens if the Upgrade Add-on button is used to upgrade the add-on? Will the Installation Code run? I assumed it would not, but it appears that it does.
 
Are you concerned about the query used to add the table/field being run again?
If so, use if not exists or try/catch.
 
Are you concerned about the query used to add the table/field being run again?

Hi Paul,

Yes that is the problem, the alter table command cannot be run on a table that already has the column added from a previous install.

I looked at the MySQL command IF NOT EXISTS which appears to only be used for CREATE TABLE command. In my case I'm not creating a table but alerting it.

Here's my code:

PHP:
<?php

class Andy_FlagThread_Install
{
    public static function install()
    {
        $db = XenForo_Application::get('db');      
        $db->query("
            ALTER TABLE xf_thread
                ADD flag TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT 0
        ");
    }
}

?>

I suppose I could simply state in my add-on instructions to NOT upgrade, but to uninstall the add-on and then install the newer version.
 
Use try/catch for adding a field to an existing table.

PHP:
try
    {
        $db->query("
            ALTER TABLE xf_thread
                ADD flag TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT 0
        ");
    }
catch (Zend_Db_Exception $e) {}
 
Thank you, Paul. That is exactly the information I needed. Works perfect.

PHP:
<?php

class Andy_FlagThread_Install
{
    public static function install()
    {
        $db = XenForo_Application::get('db');		
		
		try
		{	
			$db->query("
				ALTER TABLE xf_thread
					ADD flag TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT 0
			");
		}
		catch (Zend_Db_Exception $e)
		{
			return false;
		}
    }
}

?>
 
Thank you.

PHP:
<?php

class Andy_FlagThread_Install
{
    public static function install()
    {
        $db = XenForo_Application::get('db');		
		
		try
		{	
			$db->query("
				ALTER TABLE xf_thread
					ADD flag TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT 0
			");
		}
		catch (Zend_Db_Exception $e) {}
    }
}

?>
 
I assume it's good practice to use the try/catch code on the Uninstall.php as well?

PHP:
<?php

class Andy_FlagThread_Uninstall
{
    public static function uninstall()
    {
        $db = XenForo_Application::get('db');
		
		try
		{		
			$db->query("
				ALTER TABLE xf_thread
					DROP flag
			");
		}
		catch (Zend_Db_Exception $e) {}
    }
}

?>
 
Yeah good practice to use try/catch there too.

Speaking of good practice.

You should also be looking to prefix your custom columns and custom database tables with some sort of prefix unique to your add-on. Reason being, if XenForo were ever to update XenForo in future with a column called "flag" in the xf_thread table, it would no doubt cause all sorts of problems during upgrade for people who have your add-on installed.

Something like andyb_flag would work well.
 
Isn't there an easy way to detect which version of the addon is currently installed? That would allow to write much cleaner upgrade code.
(Using try/catch avoid unhandled exceptions is good practice. But to rely on them, when the exception itself could be avoided isn't.)

Edit: I found this: http://xenforo.com/community/threads/suggestion-is-addon-installed.43221/#post-570401
I will try this out in the installation script as indication which version is installed.
 
Last edited:
Isn't there an easy way to detect which version of the addon is currently installed?

You simply use this in your installer:
PHP:
public static function install($installedAddon)
{
    $version = is_array($installedAddon) ? $installedAddon['version_id'] : 0;

    if ($version < 1050010)
    {

Where 1050010 is the version ID.
 
Where does $installedAddon variable get defined?

PHP:
public static function install($installedAddon)
 
It gets passed to the function automatically when the installation callback gets called.
 
Top Bottom