Skip to content
kanduvisla edited this page Apr 1, 2012 · 6 revisions

Note: this page is derived from the concept of A Database less approach to Symphony's structre, and summarizes it to a concrete functional design. Therefore it is already written in how Symphony 'should' work.

Symphony stores the structure of Sections, Fields, Datasources, Events and example markup in modules. These are self-contained packages which allow for some interchangeable functionality across multiple Symphony installations. Therefore a webdeveloper doesn't constantly has te be re-inventing the wheel when creating a new site. Each time a new site is made the same modules can be used over and over again; news, image gallery, jobs, links, faq items, etc. Including their corresponding fields, datasources, events, attachment to pages, etc.

For example, a newsmodule consists of:

  • A news-section, with fields like 'title', 'date' and 'content'.
  • Some datasources for showing the index, archive and a isolated news item.
  • Some XSLT-utilities, transforming the datasources' output to HTML displaying the news.
  • The pages, displaying the news whilst using the XSLT-utilities (included as example).
  • Some CSS and JavaScript-files (inclded as example).

Interchangeability

A complete module as described above can be picked up and inserted in another Symphony site without all too much configuration/customization. Modules are generic and can be shared between the community.

The structure

Only the storage of data is done in the database. This means only the following is stored in the database:

  • Authors
  • Cache
  • Entries
  • Entry data
  • Sessions

The following is stored in XML-files in the workspace-folder:

  • Sections
  • Pages configuration
  • Datasources
  • Events

More information on the workspace file structure

Loose coupling

Since modules are site-independent, we can't work with ID's to tie it all together. Therefore, we provide each section, field and page with a unique hash. This hash is the timestamp + name when the section, field or page was created. This unique hash is stored in the XML file and get's never changed again.

In the database there are 3 lookup tables on how the sections, fields and pages are matched with ID's. The ID's are thus used purely internally by Symphony for making the correct relations.

The structure of the lookup table looks like this (in this case, for sections):

| ID_SECTION | HASH                             | FILE_HASH                        | XML_DATA        |
|------------+----------------------------------+----------------------------------+-----------------|
| 1          | 97dcae5e3bd3c9fb78fa302c0a083947 | b747b6e5ffa3db6bff396b6759fddcd7 | (some xml ...)  |
| 2          | bb2c28e57b6f2cd75723f67948e3c73c | 61c00b1e696c954ff681558938a44d1d | (some xml ...)  |
  • ID_SECTION: This is the ID used internally by Symphony to match the data stored to the correct section.
  • FILE_HASH: This is a hash of the corresponding file stored in the database. This is to determine if the content of the XML-file has been changed outside of the UI. This could otherwise cause issues (think about typo's, duplicate unique hashes, or accidentally the removal of sections/fields). When the XML-files and the hash in the database don't match, the developer gets a notification about this, and goes to a difference-page to synchronize the sections/fields.
  • XML_DATA: The XML content is also stored in the database, for when a mismatch is found, the stored XML could be used instead of the external file.

The XML

Our dear friend XML stores the structure of sections, fields and pages. Here an example of how these XML-files look like:

Sections & Fields

<section>
    <name>News items</name>
    <sortorder>1</sortorder>
    <hidden>false</hidden>
    <navigation_group>Content</navigation_group>
    <unique_hash>bb2c28e57b6f2cd75723f67948e3c73c</unique_hash>
    <fields>
        <field>
            <label element_name="name">Name</label>
            <unique_hash>97dcae5e3bd3c9fb78fa302c0a083947</unique_hash>
            <type>input</type>
            <required>true</required>
            <sortorder>1</sortorder>
            <location>main</location>
            <show_column>true</show_column>
            <configuration>
                <validator />
            </configuration>
        </field>
        <field>
            <label element_name="date">Date</label>
            <unique_hash>61c00b1e696c954ff681558938a44d1d</unique_hash>
            <type>date</type>
            <required>true</required>
            <sortorder>2</sortorder>
            <location>side</location>
            <show_column>true</show_column>
            <configuration>
                <pre_populate>true</pre_populate>
            </configuration>
        </field>
        <field>
            <label element_name="content">Content</label>
            <unique_hash>b747b6e5ffa3db6bff396b6759fddcd7</unique_hash>
            <type>textarea</type>
            <required>true</required>
            <sortorder>3</sortorder>
            <location>main</location>
            <show_column>false</show_column>
            <configuration>
                <formatter>CK_Editor</formatter>
                <size>25</size>
            </configuration>
        </field>
    </fields>
</section>

Pages

To provide a hook for extensions or other code to refer to a specific page, a page also has a unique hash.

<page>
    <title handle="news">News</title>
    <unique_hash>b747b6e5ffa3db6bff396b6759fddcd7</unique_hash>
    <parent>3b42206b9fe82adaa1066f0756c27213</parent>
    <path>media</path>
    <params>page</params>
    <datasources>
        <datasource>news-archive</datasource>
    </datasources>
    <events />
    <types>
        <type>hidden</type>
    </types>
    <sortorder>1</sortorder>
</page>

Mutations

When editing a section from Symphony's UI, the XML is saved. However, when editing the XML externally (or in a same scenario, using a module from another Symphony installation in your own), the system will show a message that the XML is modified, and send the administrator to a page showing the differences. On this page you could accept/synchronise the changes, or reject them.

Relations in fields

Some fields store relations to other fields, like Select Box Link for example. This is relation is stored by refering to the unique hash of the related field in the XML. For example, a Selectbox Link Field looks like this:

<field>
    <label element_name="category">Category</label>
    <unique_hash>b747b6e5ffa3db6bff396b6759fddcd7</unique_hash>
    <type>selectbox_link</type>
    <required>true</required>
    <sortorder>4</sortorder>
    <location>sidebar</location>
    <show_column>false</show_column>
    <configuration>
        <allow_multiple_selection>false</allow_multiple_selection>
        <show_association>true</show_association>
        <related_field_hash>61c00b1e696c954ff681558938a44d1d</related_field_hash>
        <limit>20</limit>
    </configuration>
</field>

Adding and deleting fields

When a section is initialized, Symphony checks for each field if it has a corresponding data-table (tbl_entries_data_n) in the database. This is done by checking if the hash already exists in the lookup table. If not, then the initialization/installation-method of the specific field should be executed, followed by inserting its unique hash into the database.

The deletion of fields follows a similar pattern. When a unique hash is detected in the database, and no corresponding field is found, it means that the field is removed from the XML-file. The data-table of the field is then dropped.

Now, to be sure that we're not accidentally dropping data from the database, an extra security measure is made. This is done on the difference page when synchronizing the section.

Mutating field types

The XML-approach makes it theoretically possible to change the type of a field, whilst retaining its data. You could for example change a field from type upload to unique_upload. This situation is not yet implemented, since Symphony has no solution for mutation of field types. In this scenario, Symphony will show a notification that there is a type mismatch and cannot synchronize the XML.

Code flow

Sections

On initialization, the section manager creates an internal list of all sections and iterates through them with the following logic:

Section logic

Datasources & Events

Datasources and events use the unique hash of the section and the unique hash of the field for filtering. This reference is made in the getSource()-function and in the $dsParamFILTERS-parameter.

Workspace file structure

Your workspace-folder might look something like this:

workspace
    data-sources        <!-- datasources folder -->
    events              <!-- events folder -->
    sections            <!-- sections folder -->
    pages
        my-page.xsl     <!-- stylesheet -->
        my-page.xml     <!-- configuration file -->                
    utilities
    assets
        css
        js

In retrospect, our news-module example could look like this:

workspace
    data-sources
        data.news-index.php
        data.news-archive.php
        data.news-detail.php
    events
    sections
        news.xml
    utilities
        format-date.xsl
    pages
        news.xsl
        news.xml
        news-archive.xsl
        news-archive.xml
        news-detail.xsl
        news-detail.xml
    assets
        css
            news.css
        js
            news.js

Extensions / Dependencies

Extensions are a bit of a strange entity in this complete picture. Some sections could depend on it, since they might use field-types which are provided by extensions. If a fields' type cannot be found, the system will show a message that the field-type is not available and that they need to install the extension for it. In other words: a synchronization cannot be done when trying to install fields which are not available in the Symphony installation.