Hey all, this tip is based on multi-value variables viewtopic.php?f=5&t=10892 and this tip viewtopic.php?f=8&t=11092

Story:
I always debug my code with 'cms:dump' and 'cms:dump_all' tags. When I code an average website, I know that something might go wrong and unnoticed, so I try to leave as many 'traces' as possible to debug variables and code chunks. Sometimes I get back to older projects to see how some thing worked there.
Following tip might help to to spend less time reading code and find errors quicker.

Idea:
Define a global mv-variable 'log' and put there variable names and values and a description for later times.
Output those nicely in the front-end without need to add 'dump' or 'dump-all' tags.

Code to kfunctions.php is similar to the tip posted earlier:

Code: Select all

// Create a variable for debug
$FUNCS->add_event_listener( 'add_render_vars', 'add_debug_vars' );
function add_debug_vars(){
    global $CTX, $AUTH;

    $CTX->set( 'log', array(), 'global', 1 ); // logging for everyone

    if( $AUTH->user->access_level >= K_ACCESS_LEVEL_SUPER_ADMIN ){
        $CTX->set( 'log.admin', 1, 'global' );
    }

    // Dump session for everyone
    if( count($_SESSION) > 1 ){

        $CTX->set( 'log.k_session', array(), 'global', 1 );
        $CTX->set( 'k_session', array(), 'global', 1 );
        $CTX->set( 'k_session_set', 1, 'global', 1 );

        foreach( $_SESSION as $k=>$v ){
            if( $k != 'KSESSIONmsgs' ){
                $CTX->set( 'k_session.' . $k, $v, 'global' ); // k_session.myvar
                $CTX->set( 'log.k_session.' . $k, $v, 'global' ); // log.session.myvar
            }
        }

    }

    $CTX->set( 'time_start', microtime(true), 'global', 1 ); // for measuring time of a script

}


Now for every template we don't have to define a 'log' variable - it will be ready to use automatically.
Samples of how I use it throughout the couch-code in my templates:

Code: Select all
SAMPLES:

            <cms:capture into='log.some-var' is_json='1'>
                [
                123,
                321
                ]
            </cms:capture>

            <cms:set log.some-new-var=some_new_var />

            <cms:set log.current_url. = current_url />

            <cms:capture into='log.desc' is_json='1'>
                "Lists all pages of 'country.php' with restriction to published pages of 'index.php' that are related to it. Counts related pages."
            </cms:capture>

            <cms:capture into='log.sql_countries' is_json='1'>
                {
                    "desc":"Lists all pages of 'country.php' with restriction to published pages of 'index.php' that are related to it. Counts related pages.",
                    "value":"<cms:excerpt count='1000' truncate_chars='1'><cms:show sql_countries /></cms:excerpt>"
                }
            </cms:capture>



What's best in this logging approach - is that you can trace how your variables get changed during the run of code.
A simple illustration with calculations:

Code: Select all
<cms:set log.sum = '[]' is_json='1' />
<cms:set sum.desc = 'Sum of values' />
<cms:set sum = '0' /><cms:set log.sum. = sum />
<cms:set sum = "<cms:add '1' '3' />" /><cms:set log.sum. = sum />
<cms:set sum = "<cms:add sum '5' />" /><cms:set log.sum. = sum />


See that each new value of 'sum' will be stored as a new array value with automatically assigned key (0,1,2 etc).
Now I don't output each value in the html-comments or in the front-end at the place of calculation, rather I store all values in 'log' variable and output where I need it. Let's see how I do it:

Front-end display:
I have a snippet 'logging.html' which I can embed somewhere at the front-end (around footer is handy).
Its content:

Code: Select all
<cms:if log.admin >
    <cms:set log.script_time = "<cms:sub "<cms:php>echo $time_start = microtime(true); </cms:php>" time_start />" />
    <div class="bg-warning">
        <div class="alert alert-success" >
            <div class="container alert-dismissable">
                <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
                <samp>
                <h3>LOG</h3>
                <ul class="">
                <cms:each log>
                    <cms:if "<cms:is_array item />">
                    <li><kbd><cms:show key /></kbd>
                        <ul>
                        <cms:each item>
                            <li><code><cms:show key /></code> : <cms:show item /></li>
                        </cms:each>
                        </ul>
                    </li>
                    <cms:else />
                    <li><kbd><cms:show key /></kbd> : <cms:show item /></li>
                    </cms:if>
                </cms:each>
                </ul>
                </samp>
            </div>
        </div>
    </div>
</cms:if>



This snippet does nothing more than a good default bootstrap-styled output of multi-value variable 'log'. A sample:
2017-09-13-202157.png
2017-09-13-202157.png (49.3 KiB) Viewed 324 times


If I need also to see the output of 'cms:dump' tag, I can add a check if a variable 'dump' exists in a session and which value it has:

Code: Select all
        <cms:if log.k_session.dump eq '1' >
        <div class="alert alert-success">
            <div class="container alert-dismissable">
                <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
                <samp>
                <cms:dump />
                </samp>
            </div>
        </div>
        </cms:if>
        <cms:if log.k_session.dump eq '2' >
        <div class="alert alert-info">
            <div class="container alert-dismissable">
                <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
                <samp>
                <cms:dump_all />
                </samp>
            </div>
        </div>
        </cms:if>



On the front-end in a special comfortable place I have 2 dropdowns, which control the appearance of log output and dump output, so I can switch the logging information display on and off:

Code: Select all
                    <cms:if log.admin>
                    <div class="row">
                        <div class="col-xs-6">
                            <h3>Settings</h3>
                            <div class="styled-select">
                            <cms:form method="post" anchor='0'>
                                <cms:if k_success>
                                    <cms:if frm_log eq '1' ><cms:set_session name='log' value=frm_log /><cms:else /><cms:delete_session name='log' /></cms:if>
                                    <cms:redirect k_page_link />
                                </cms:if>
                                <cms:input type='dropdown' class="form-control" opt_values='No log*0|Log*1' opt_selected=k_session.log  val_separator='*' name='log' onchange='this.form.submit();'/>
                            </cms:form>
                            </div>
                            <div class="styled-select">
                            <cms:form method="post" anchor='0'>
                                <cms:if k_success>
                                    <cms:if frm_dump eq '1' || frm_dump eq '2' ><cms:set_session name='dump' value=frm_dump/><cms:else /><cms:delete_session name='dump' /></cms:if>
                                    <cms:redirect k_page_link />
                                </cms:if>
                                <cms:input type='dropdown' class="form-control" opt_values='No dump*0|Dump*1|Dump all*2' opt_selected=k_session.dump  val_separator='*' name='dump' onchange='this.form.submit();'/>
                            </cms:form>
                            </div>
                        </div>
                    </div>
                    </cms:if>



2017-09-13-203105.png
2017-09-13-203105.png (10.7 KiB) Viewed 324 times


These 2 forms are simple and can be removed or left there when the website is online and handed over to client. It will be displayed only to superadmin, so in case some trouble occurs I can log in as superadmin, turn on the log and track to the place where error starts happening. Alternative to log, this could be a way to make a simple documentation which will stay with code and not make it look bad.

P.S.
This is all very simple. Once you've mastered multi-value variables - it will be a big change in the way you code - with json and arrays. In following sample I list a company's data and remember it to a json one time. Then I can output these as many times as I need to in the template and do not call database with 'cms:pages' or 'cms:get_custom_field' over and over again, thus saving server's resources, thus allowing more visitors have better experience with good page load times.

Code: Select all
<!-- Let's find a company, associated with current user -->
<cms:pages masterpage='partners.php' custom_field="c_related_user=id(<cms:show k_user_id />)" limit='1' return_sql='0' show_future_entries='1' >

    <!-- Remember company data in json -->
    <cms:capture into='c' is_json='1'>
        {
        "Company name"  : "<cms:show k_page_title />",
        "Company type"  : "<cms:show c_type />",
        "APTA number"   : "<cms:show c_apta />",
        "Contact name"  : "<cms:show c_cname />",
        "Position"      : "<cms:show c_position />",
        "Phone number"  : "<cms:show c_phone />",
        "Email"         : "<cms:show c_email />",
        "Street address": "<cms:show c_street />",
        "Town/City"     : "<cms:show c_towncity />",
        "Zip code"      : "<cms:show c_zipcode />",
        "Country"       : "<cms:show c_country />"
        }
    </cms:capture>

</cms:pages>