How A Basic Page Loads With Survloop

This will go over some key paths in which a visitor's request travels through the codebase. Hopefully, you won't need to deal with these spots too often — unless you're helping make them better. But it is important to be able to track the main flows of the code.


This Page: /how-a-basic-page-loads-with-survloop

When you loaded this page, the server asks Laravel what to give you. During installation, the SurvloopServiceProvider taught it to check the file:


...which includes routes-slug.php, and will find a match here:

    $path . 'Survloop@loadPageURL'

This points to the class SurvloopControllersSurvloop, found in the file /survloop/src/Controllers/Survloop.php.

The function is also named in the route, which always receives the Request with GET, POST parameters, and more. In this case, only one more parameter is passed in as "common-code-routes-and-paths":

public function loadPageURL(Request $request, $pageSlug = '', $cid = 0, $view = '', $skipPublic = false)
$redir = $this->chkPageRedir($pageSlug);
if ($redir != $pageSlug) {
redirect($redir, 301);
if ($this->loadTreeBySlug($request, $pageSlug, 'Page')) {

This function first checks to see if this URL slug matches a redirect. If not, it will call other functions to find this page's slug in the SL_Trees table of the database, and check access permissions.

But whatever happens, this function returns this page back to you, the site visitor.


How Survloop Loads This Page Tree

Now that we've clarified how we got from a URL to the code base, let's go over the current loading process for this page. Pages and Surveys are stored and generated as branching Trees full of Nodes. Surveys are therefore loaded in a very similar way.

After matching the URL slug with a Page's Tree record, the loadTreeBySlug function called above will load The Globals Trunk by calling syncDataTrees:

public function syncDataTrees(Request $request, $dbID = 1, $treeID = 1)
    $this->dbID = $dbID;
    $this->treeID = $treeID;
    $GLOBALS["SL"] = new Globals($request, $dbID, $treeID, $treeID);
    return true;

$GLOBALS["SL"] now contains look-ups for the whole client database design, and universal access to some common data and utility function. This can be particularly useful when access is needed both in Controllers and deeply nested Views.

Next, loadLoop creates the client extension of the main Survloop engine. This site's custom abbreviation is 'SurvloopOrg', so it searches for a class at SurvloopOrgControllersSurvloopOrg.

public function loadLoop(Request $request, $skipSessLoad = false)
    $class = "RockHopSoftSurvloopControllersTreeTreeSurvForm";
    if ($this->custAbbr != 'Survloop') {
        $custClass = $this->custVend . "" . $this->custAbbr . "Controllers" . $this->custAbbr . "";
        if (class_exists($custClass)) {
            $class = $custClass;
eval("$this->custLoop = new " . $class . "("
. "$request, "
. "-3, "
. $this->dbID . ", "
. $this->treeID . ", "
. (($skipSessLoad) ? "true" : "false")
. ");"
); return true; }

It finds it at /survlooporg/src/Controllers/SurvloopOrg.php, which extends RockHopSoft/Survloop/Controllers/Tree/TreeSurvForm. It loads this primary Tree Trunk of the code base, with customizable extensions, passing in the page's Tree ID and the Database ID (1).

Currently, the Database ID is almost always #1, representing the primary client/installation-specific database. Database ID #3 is reserved for the database design of the Survloop engine itself (meta).

Next in loadPageURL, we check for a cache of this page (because it is a simple one without dynamic content). Odds are that you got the cache this page load. Good for you!

But that cache was created on-demand from another visitor's page load, where it called The Tree Trunk's index function:

$this->pageContent = $this->custLoop->index($request);

...which starts diving in closer to meat and potatoes of the branching tree managed by TreeSurv.php.

public function index(Request $request, $type = '', $val = '')
    $this->survLoopInit($request, '');
$this->v["content"] = $this->printTreePublic();

The survLoopInit function is found in the root level SurvloopController, and initializes data related to the current user, potentially relevant page load variables, and site navigation. It also makes a call to initExtra($request). This can be written in the client extension SurvloopOrg.php to inject any additional initialization needed.

The printTreePublic function will traverse the Page Tree's branching nodes and call printNodePublic for each (also in TreeSurv.php), compiling a finished output as it goes. Much of this engine's power executes within this traversal.

Back in the index function, the main page content has now been fully loaded into a variable of The Tree Trunk, $this->v, which is primarily used for data that needs to be passed into Views.

The main body content is scraped once more for Javascript and CSS, to be consolidated and minified in separate resource files. Finally, it is pumped into the highest-level master View with the HTML for general site structure, navigation layout, etc.
$this->v["content"] = $GLOBALS["SL"]->pullPageJsCss( $this->v["content"], $this->coreID );
return $GLOBALS["SL"]->swapSessMsg(
view('vendor.survloop.master', $this->v)->render()

Finally, we have generated the full HTML, JS, and CSS for this page. Since this is a simple static page, it is cached, but for only the current viewer's permission level.


Customizing How Specific Nodes Are Printed

Withing each branching Tree, each Node can be customized on the hard-coded level. With fresh Survloop installations, the first customization needed is often a Node that needs more complex data interpretation output beyond what Survloop's engine currently handles by default.

This Page's right column has a Node which just wraps its children in a 'card' (boxes with little shadows around). It's child, Node #3088, is hard-coded in the SurvloopOrg package. This process is shared by many other nodes throughout the public Pages for navigation of the documentation area of the website.

protected function customNodePrint($nID = -3, $tmpSubTier = [], $nIDtxt = '', $nSffx = '', $currVisib = 1)
    if (in_array($nID, [641, 2386, 441, 759, 999, 1081, 1793, 2281, 2681, 3088])) {
        return $this->printDocumentationNav($nID);
    return '';

Within the printNodePublic function mentioned above, there is a check for customization function called customNodePrint. By creating this function in the client/installation package, a developer can bust out as much complexity as they like.

Surveys make use of a parallel function, postNodePublicCustom, to customize how user responses are stored in the database, when a page within Survey is submitted.


Updated: November 7, 2019