Skip to content
This repository has been archived by the owner on Nov 24, 2019. It is now read-only.

v1.5 Multi site coding

vee w, edited this page Apr 27, 2014 · 3 revisions

Fuel Start recommend use multi-site as table per site instead of adding site_id into table, but however you can use both.
Table per site make data store individually, use site id to separate may use many space per table.
If you have too much data in a table the use of site id to separate may reach table size limit (64TB).

In short.
To store many data in a table per site, use table per site.
To store few data in a table per site, use site id to separate it.
Example of table per site:
main site table [account_level, account_level_group, account_level_permission, config]
sub site table [2_account_level, 2_account_level_group, 2_account_level_permission, 2_config]

Create multi-site table

Multi-site table means table that store data in a table per site.

When you created table that needs to store data individually per site, you have to add those tables name in sites model.

  1. Open fuel/app/classes/model/sites.php
  2. Find public $multisite_tables = array(
  3. Add your table name in this array before end of array.
    Example:
    public $multisite_tables = array(
        'account_fields',
        'account_level',// this table require data.
        'account_level_group', // this table require base level data.
        'account_level_permission',
        'account_permission',

        'config', // this table must copy "core" config data

        'product', // this is my new table
        'category', // this is my new table
    );

Copy data when create new site

If your table have to copy data when create new site, add your code in this method. copyNewSiteTable()

Get data from multi-site

Use ORM

In your ORM model class, add this method to set new table name with site id prefix.

    /**
     * run before initialize the class
     * use this method to set new table prefix with multisite.
     */
    public static function _init()
    {
        // get current site id
        $site_id = \Model_Sites::getSiteId(false);

        if ($site_id != '1') {
            static::$_table_name = $site_id . '_' . static::$_table_name;
        }
    }

Example:
If you get data from product table on main site, the product table will be call.
If you get data from product table on sub site that has site id = 2, the product table will be call as 2_product.

Use DB class

To use DB class with select(), insert(), update(), delete() or DBUtil class, all you have to do is just check that current site id is 1 or not and if not you just prefix table with site id.

Example:
Get data from product table.

class Controller_Product extends \Controller_BaseController
{
    public function action_index($id = '')
    {
        // check site id and set table name (with site id prefix if not on main site)
        $site_id = \Model_Sites::getSiteId();
        if ($site_id == '1') {
            $table_name = 'product';
        } else {
            $table_name = $site_id . '_product';
        }

        // get product data from selected id
        $result = \DB::select('*')->from($table_name)->execute();
    }
}

Account related in multi-site table

All account related in multi-site table must add delete manually in fuel/app/classes/model/accounts.php.
Let say that you have comments table. Each site you created must store its comment data per site table. The registered user have account_id in comments table.
This means comments table is account related and when administrator delete that account the comment data must be delete in all sites.

  1. Open fuel/app/classes/model/accounts.php file.
  2. Find deleteAccount() method
  3. Find "// @todo [multisite] more multi-site tables that has account_id related should be delete here." line in deleteAccount() method
  4. Add your delete data after that line.

Example:

    public static function deleteAccount($account_id = '') {
        // check if it is guest or site owner (id = 1), not delete.
        if ($account_id === '0' || $account_id === '1') {return false;}

        // delete avatar
        static::instance()->deleteAccountAvatar($account_id, false);

        // @todo [api] for deleting account here.

        // loop sites to delete this account id related in multi-site tables.
        $site_id = \Model_Sites::getSiteId(false);
        $list_site_option['list_for'] = 'admin';
        $list_site_option['unlimit'] = true;
        $sites = \Model_Sites::listSites($list_site_option);
        if (isset($sites['items']) && is_array($sites['items']) && !empty($sites['items'])) {
            foreach ($sites['items'] as $site) {
                // skip delete from current site id table.
                if ($site->site_id != $site_id) {
                    if ($site->site_id == '1') {
                        $table_siteid_prefix = '';
                    } else {
                        $table_siteid_prefix = $site->site_id . '_';
                    }
                    
                    // delete from account_level table
                    \DB::delete($table_siteid_prefix . 'account_level')->where('account_id', $account_id)->execute();
                    
                    // delete from account_fields table
                    \DB::delete($table_siteid_prefix . 'account_fields')->where('account_id', $account_id)->execute();

                    // delete from account_permission table
                    \DB::delete($table_siteid_prefix . 'account_permission')->where('account_id', $account_id)->execute();
                    
                    // @todo [multisite] more multi-site tables that has account_id related should be delete here.
                    // delete this account id from comments table of all sites.
                    \DB::delete($table_site_id_prefix . 'comments')->where('account_id', $account_id)->execute();
                }
            }
        }
        unset($list_site_option, $site, $sites, $site_id, $table_siteid_prefix);

        // delete account now.
        static::find($account_id)->delete();// needs to use ::find() to delete in related table

        return true;
    }

Administrator tips

Before you create new site. Please make sure that you have at least 1 enabled super administrator.
On create new site all account level will be copy from main site to newly created site. All of those account that is not super administrator will be reset to member role.

If you did not have enabled super administrator before you create new site, you cannot log in to administrator dashboard.
To fix this, go to your database management tool such as phpMyadmin.

  1. Get your target site id
    1. If your site that have this problem is test.com. Find test.com id in sites table.
    2. Copy the site_id you found.
  2. Go to [site_id]_account_level table of site you want to fix. Example: test.com site_id is 2; your level table will be 2_account_level
  3. Open it (browse)
  4. Look at your account id and click edit
  5. Change level_group_id to 1 which is super administrator.
  6. Save change
  7. Clear cache using Website > Tools > Cache management menu.

Now, your account will become super administrator on new site. You can log in to change user's roles and set permission for roles and users.