How I fought contexts

    As a true conservative, for a long time I used exclusively MODx Evolution. First of all, I was satisfied with the availability of comprehensive documentation, heaps of articles and the extremely understandable architecture of this version of MODx CMF. About the Revolution version, I periodically read various articles, but I did not want to change my usual system for anything else. However, at one point, the number of tables in the database of my multi-domain "hamster" on the hosting has reached terrifying sizes. There was a question about a multi-domain solution. Once I read about the possibility of creating a multi-domain site on MODx Revolution. I installed the engine on a test subdomain and started digging deeper. As it turned out, in the framework itself there is no ready-made solution for multi-domain. There is a certain system of contexts. Different contexts can be defined on different subdomains. Only for this you need to edit the index.php file.

    The first thing that comes to mind is to use the already proven popular code:

    switch($_SERVER['SERVER_NAME']) {
      case 'sub1.domain.tld': $modx->initialize('sub1'); break;
      case 'sub2.domain.tld': $modx->initialize('sub2'); break;
      case 'sub3.domain.tld': $modx->initialize('sub3'); break;
      default: $modx->initialize('web');
    }
    


    If, say, multilingualism is based on your contextual system, then you can even do this:

    switch($_SERVER['SERVER_NAME']) {
      case 'domain.ru': case 'www.domain.ru': $modx->initialize('ru'); break; // Переключаем на русский
      case 'domain.fr': case 'www.domain.fr': $modx->initialize('fr'); break; // Переключаем на французский (для примера)
      default: $modx->initialize('web');
    }
    


    And for not very large portals, where the number of subdomains is controlled by the hosting / domain administrator and rarely changes, such a solution is enough for the eyes. However, let's fantasize with you. You have your own server. It can be your personal server or VDS-ka on your favorite hosting. You have the ability to programmatically create subdomains. Suppose you are writing your analogue of livejournal.com ...

    Creating a context using the API is not very difficult. I won’t go into details; I haven’t studied the MODx Revolution API too much so far. Nevertheless, creating a context and a subdomain is one thing, but linking it together is another. Here the above solutions will not work, because it is not known in advance how many subdomains will be and how the contexts for them will be called. In theory, if the context aliases coincide with the names of the subdomains, then the solution is quite suitable:

    define("myRootDomain","domain.tld");
    $ctxKey = 'web';
    if (preg_match('#(\w+).'.myRootDomain.'#si',$_SERVER['SERVER_NAME']) > 0) {
      $ctxKey = preg_replace('#(\w+).'.myRootDomain.'#si','\1',$_SERVER['SERVER_NAME']);
      if ($ctxKey == 'www') $ctxKey = 'web';
    }
    


    The main context information in MODx is stored in the database in the context , context_setting tables . The first table contains descriptions of contexts (key, description, display order). In the second, context settings. Remember, in common solutions we needed to register error pages, host and the like? This is all there is stored. And the first thing that comes to mind is the SQL query for this table:

    $SQL = "SELECT * FROM ".$table_prefix." WHERE `key`='http_host' AND `value`='".$_SERVER['SERVER_NAME']."'";
    


    If the context system were provided in the old Evolution, then with the algorithm everything would be simple:

    $ctxKey = 'web';
    if ($result = $modx->db->query($SQL)) if ($row = mysql_fetch_assoc($result)) $ctxKey = $row['context_key'];
    


    However, in this regard, MODx developers have planted a little grunt for developers using MODx, because the MODx Revolution architecture is based on xPDO. And this is not the usual API for us, but a completely different conversation.

    Having studied a bunch of Google search results, including the official documentation for the MODx Revolution API, I still could not understand how easier it is to make a database query in MODx Revolution. But, having copied the core / model / modx / modx.php file , I found something like the following:

    $pluginEventTbl= $this->getTableName('modPluginEvent');
    $eventTbl= $this->getTableName('modEvent');
    $pluginTbl= $this->getTableName('modPlugin');
    $propsetTbl= $this->getTableName('modPropertySet');
    $sql= "
        SELECT
            Event.name AS event,
            PluginEvent.pluginid,
            PropertySet.name AS propertyset
        FROM {$pluginEventTbl} PluginEvent
            INNER JOIN {$pluginTbl} Plugin ON Plugin.id = PluginEvent.pluginid AND Plugin.disabled = 0
            INNER JOIN {$eventTbl} Event ON {$service} Event.name = PluginEvent.event
            LEFT JOIN {$propsetTbl} PropertySet ON PluginEvent.propertyset = PropertySet.id
        ORDER BY Event.name, PluginEvent.priority ASC
    ";
    $stmt= $this->prepare($sql);
    if ($stmt && $stmt->execute()) {
        while ($ee = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $eventElementMap[$ee['event']][(string) $ee['pluginid']]= $ee['pluginid'] . (!empty($ee['propertyset']) ? ':' . $ee['propertyset'] : '');
        }
    }
    


    This is a snippet of the getEventMap method of the modX class. It is logical to assume that instead of a long request, we can insert our request and, in theory, it should work out as it should. The result is a solution:

    $ctxCur = 'web';
    $ctxQur = "SELECT * FROM `".$table_prefix."context_setting` WHERE `key`='http_host' AND `value`='".$_SERVER['SERVER_NAME']."'";
    $ctxSQL = $modx->prepare($ctxQur);
    if ($ctxSQL && $ctxSQL->execute()) if ($ctxRes = $ctxSQL->fetch(PDO::FETCH_ASSOC)) $ctxCur = $ctxRes['context_key'];
    $modx->initialize($ctxCur);
    


    When using this solution, we only need to worry about the correct indication of the http_host field in the admin panel. And the context name in this case does not have to match the subdomain. That's it for sim. Thank you for your attention to my next bike!

    Also popular now: