p2p.wrox.com Forums

Need to download code?

View our list of code downloads.


  Return to Index  

beginning_php thread: nik-version of the access logger


Message #1 by "Nikolai Devereaux" <yomama@u...> on Wed, 25 Sep 2002 10:36:24 -0700
Hey all, as much as I rant and preach about my "style" of programming, it's
come to my attention that none of you have really ever seen a concrete example
of what I am talking about.

Here's a script, originally posted by Anton, that I refactored to illustrate
key design concepts that I embrace.

The main script...
*  is the only script that outputs anything.
*  is the only script that exits execution.
*  does NOT contain HTML or SQL code, it just contains flow of control logic.

Utility functions...
*  are well named
*  perform only the task that their name implies
*  defined in include files
*  that contain SQL don't contain ANY HTML.
*  that contain HTML don't contain ANY SQL.

Database functions...
*  are generic.
*  that perform tasks (e.g. process_login) return true/false to indicate
success/failure, they don't output any error message and/or exit.

*  Forms use a single array to store all submitted values.

*  Arrays are used to organize related data, e.g. $user_data.


I whipped this up within the last 30 minutes or so, and the code is untested.
I don't have Anton's common_db.inc file, nor do I have a database with the
proper schema created.  This is purely for example purposes!


access_logger.php (the main script)
------------------------------------
<?php

session_start();

require_once('./common_db.inc');
require_once('./page_templates.inc');
require_once('./authentication.inc');


$page_text = page_header();             // page_templates.inc

if(isset($_POST['login_form']))         // user is attempting to log in
{
    if(!process_login($_POST['login_form'])) // authentication.inc
    {
        $page_text .= bad_login_text();      // page_templates.inc
    }
}

if(is_logged_in())                           // authentication.inc
{
    if(!log_access())                        // authentication.inc
    {
        $page_text .= sql_error();
    }
}
else
{
    $page_text .= login_form();              // page_templates.inc
}

$page_text .= page_footer();                 // page_templates.inc

echo $page_text;
?>
------------------------------------


Short, sweet, and to the point, huh?  Next, page_templates.inc:
------------------------------------
<?php
// page_templates.inc

function page_header($title)
{
    return "<HTML>
<HEAD>
<TITLE>{$title}</TITLE>
</HEAD>
<BODY>\n";
}

function page_footer()
{
    return "</BODY>\n</HTML>\n";
}

function login_form()
{
    // heredoc syntax example!
    $form = <<<EOH
<FORM METHOD="POST" ACTION="{$_SERVER['PHP_SELF']}">
  <DIV ALIGN="CENTER">
    <H3>Please log in to access the page you requested.</H3>
    <TABLE BORDER="1" WIDTH="200" CELLPADDING="2">
      <TR>
        <TH WIDTH="18%" ALIGN="RIGHT" NOWRAP>ID</TH>
        <TD WIDTH="82%" NOWRAP>
          <INPUT TYPE="TEXT" NAME="login_form[userid]" SIZE="8" />
        </TD>
      </TR>
      <TR>
        <TH WIDTH="18%" ALIGN="RIGHT" NOWRAP>Password</TH>
        <TD WIDTH="82%" NOWRAP>
          <INPUT TYPE="PASSWORD" NAME="login_form[userpassword]" SIZE="8" />
        </TD>
      </TR>
      <TR>
        <TD WIDTH="100%" COLSPAN="2" ALIGN="CENTER" NOWRAP>
          <INPUT TYPE="SUBMIT" VALUE="LOGIN" NAME="login_form[submit]" />
        </TD>
      </TR>
    </TABLE>
  </DIV>
</FORM>
EOH;
    return $form;
}

function bad_login_text()
{
    global $register_script;
    return "Authorization failed. " .
           "You must enter a valid userid and password combo. " .
           "Please try again<BR>\n" .
           "If you're not a member yet, click on the " .
           "following link to register.<BR>\n";
           "<A HREF=\"{$register_script}\">Membership</A>";
}
?>
------------------------------------


Finally, authentication.inc:
------------------------------------
<?php

function log_in($user_data)
{
    $_SESSION['auth']['logged_in'] = true;
    $_SESSION['auth']['userid']    = $user_data['userid'];
}

function log_out()
{
    session_unset();
    session_destroy();
}

function is_logged_in()
{
    return (isset($_SESSION['auth']['logged_in']) &&
$_SESSION['auth']['logged_in']);
}

function current_user()
{
    return (is_logged_in())? $_SESSION['auth']['userid'] : '';
}

function process_login($user_data)
{
    global $register_script, $default_dbname, $user_tablename,
$access_log_tablename;

    db_connect($default_dbname);
    $query = "SELECT userfirstname
              FROM {$user_tablename}
              WHERE userid = '{$user_data[userid]}'
              AND userpassword = password('{$user_data[userpassword]}')";

    $result = db_query($query);

    if($result && db_num_rows($result))
    {
        log_in($user_data);
    }

    return is_logged_in();
}


function log_access()
{
    global $default_dbname, $user_tablename, $access_log_tablename;

    $link_id = db_connect($default_dbname);

    $query = "UPDATE {$user_tablename}
             SET lastaccesstime = NULL
             WHERE userid='" . current_user() . "'";
    $result = db_query($query);

    $num_rows = db_affected_rows($link_id);
    if($num_rows != 1)
    {
        return false;
    }

    $query = "SELECT userid FROM {$access_log_tablename}
              WHERE page = '{$_SERVER['PHP_SELF']}'
              AND userid = '" . current_user() . "'";
    $result = mysql_query($query);

    if(!mysql_num_rows($result))
    {
        $query = "INSERT INTO {$access_log_tablename}
                  VALUES ('{$_SERVER['PHP_SELF']}',
                          '" . current_user() . "',
                          1, NULL)";
    }
    else
    {
        $query = "UPDATE {$access_log_tablename}
                 SET visitcount = visitcount + 1, accessdate = NULL
                 WHERE page = '{$_SERVER['PHP_SELF']}'
                 AND userid = '" . current_user() . "'";
    }

    db_query($query);

    $num_rows = db_affected_rows($link_id);

    return ($num_rows == 1);
}

?>
------------------------------------


Any questions, comments, rants, raves, etc... are always welcome!


Take care,

Nik

Message #2 by Peter Simard <peter@p...> on Wed, 25 Sep 2002 13:52:41 -0400
Thanks Nik;

Does   anyone   other  than me get this feeling of: "Wow...that  makes
sense ... " when you see Niks' examples?

Clarity of thought is a beautiful thing...

I'm  working  on  a JAVA application today, and in the process can see
how lazy I've become programming almost exclusively in PHP lately.

TTFN,

Pete


Message #3 by spam@k... on Wed, 25 Sep 2002 13:45:51 -0500
I like everything here except that in the login form the words "ID" and "Password" are separated from
their input boxes by a table wall. What would Edward Tuffte say? 


------------------------------------------------
On Wed, 25 Sep 2002 10:36:24 -0700, "Nikolai Devereaux" <yomama@u...> wrote:

> 
> Hey all, as much as I rant and preach about my "style" of programming, it's
> come to my attention that none of you have really ever seen a concrete example
> of what I am talking about.
> 
> Here's a script, originally posted by Anton, that I refactored to illustrate
> key design concepts that I embrace.
> 
> The main script...
> *  is the only script that outputs anything.
> *  is the only script that exits execution.
> *  does NOT contain HTML or SQL code, it just contains flow of control logic.
> 
> Utility functions...
> *  are well named
> *  perform only the task that their name implies
> *  defined in include files
> *  that contain SQL don't contain ANY HTML.
> *  that contain HTML don't contain ANY SQL.
> 
> Database functions...
> *  are generic.
> *  that perform tasks (e.g. process_login) return true/false to indicate
> success/failure, they don't output any error message and/or exit.
> 
> *  Forms use a single array to store all submitted values.
> 
> *  Arrays are used to organize related data, e.g. $user_data.
> 
> 
> I whipped this up within the last 30 minutes or so, and the code is untested.
> I don't have Anton's common_db.inc file, nor do I have a database with the
> proper schema created.  This is purely for example purposes!
> 
> 
> access_logger.php (the main script)
> ------------------------------------
> <?php
> 
> session_start();
> 
> require_once('./common_db.inc');
> require_once('./page_templates.inc');
> require_once('./authentication.inc');
> 
> 
> $page_text = page_header();             // page_templates.inc
> 
> if(isset($_POST['login_form']))         // user is attempting to log in
> {
>     if(!process_login($_POST['login_form'])) // authentication.inc
>     {
>         $page_text .= bad_login_text();      // page_templates.inc
>     }
> }
> 
> if(is_logged_in())                           // authentication.inc
> {
>     if(!log_access())                        // authentication.inc
>     {
>         $page_text .= sql_error();
>     }
> }
> else
> {
>     $page_text .= login_form();              // page_templates.inc
> }
> 
> $page_text .= page_footer();                 // page_templates.inc
> 
> echo $page_text;
> ?>
> ------------------------------------
> 
> 
> Short, sweet, and to the point, huh?  Next, page_templates.inc:
> ------------------------------------
> <?php
> // page_templates.inc
> 
> function page_header($title)
> {
>     return "<HTML>
> <HEAD>
> <TITLE>{$title}</TITLE>
> </HEAD>
> <BODY>\n";
> }
> 
> function page_footer()
> {
>     return "</BODY>\n</HTML>\n";
> }
> 
> function login_form()
> {
>     // heredoc syntax example!
>     $form = <<<EOH
> <FORM METHOD="POST" ACTION="{$_SERVER['PHP_SELF']}">
>   <DIV ALIGN="CENTER">
>     <H3>Please log in to access the page you requested.</H3>
>     <TABLE BORDER="1" WIDTH="200" CELLPADDING="2">
>       <TR>
>         <TH WIDTH="18%" ALIGN="RIGHT" NOWRAP>ID</TH>
>         <TD WIDTH="82%" NOWRAP>
>           <INPUT TYPE="TEXT" NAME="login_form[userid]" SIZE="8" />
>         </TD>
>       </TR>
>       <TR>
>         <TH WIDTH="18%" ALIGN="RIGHT" NOWRAP>Password</TH>
>         <TD WIDTH="82%" NOWRAP>
>           <INPUT TYPE="PASSWORD" NAME="login_form[userpassword]" SIZE="8" />
>         </TD>
>       </TR>
>       <TR>
>         <TD WIDTH="100%" COLSPAN="2" ALIGN="CENTER" NOWRAP>
>           <INPUT TYPE="SUBMIT" VALUE="LOGIN" NAME="login_form[submit]" />
>         </TD>
>       </TR>
>     </TABLE>
>   </DIV>
> </FORM>
> EOH;
>     return $form;
> }
> 
> function bad_login_text()
> {
>     global $register_script;
>     return "Authorization failed. " .
>            "You must enter a valid userid and password combo. " .
>            "Please try again<BR>\n" .
>            "If you're not a member yet, click on the " .
>            "following link to register.<BR>\n";
>            "<A HREF=\"{$register_script}\">Membership</A>";
> }
> ?>
> ------------------------------------
> 
> 
> Finally, authentication.inc:
> ------------------------------------
> <?php
> 
> function log_in($user_data)
> {
>     $_SESSION['auth']['logged_in'] = true;
>     $_SESSION['auth']['userid']    = $user_data['userid'];
> }
> 
> function log_out()
> {
>     session_unset();
>     session_destroy();
> }
> 
> function is_logged_in()
> {
>     return (isset($_SESSION['auth']['logged_in']) &&
> $_SESSION['auth']['logged_in']);
> }
> 
> function current_user()
> {
>     return (is_logged_in())? $_SESSION['auth']['userid'] : '';
> }
> 
> function process_login($user_data)
> {
>     global $register_script, $default_dbname, $user_tablename,
> $access_log_tablename;
> 
>     db_connect($default_dbname);
>     $query = "SELECT userfirstname
>               FROM {$user_tablename}
>               WHERE userid = '{$user_data[userid]}'
>               AND userpassword = password('{$user_data[userpassword]}')";
> 
>     $result = db_query($query);
> 
>     if($result && db_num_rows($result))
>     {
>         log_in($user_data);
>     }
> 
>     return is_logged_in();
> }
> 
> 
> function log_access()
> {
>     global $default_dbname, $user_tablename, $access_log_tablename;
> 
>     $link_id = db_connect($default_dbname);
> 
>     $query = "UPDATE {$user_tablename}
>              SET lastaccesstime = NULL
>              WHERE userid='" . current_user() . "'";
>     $result = db_query($query);
> 
>     $num_rows = db_affected_rows($link_id);
>     if($num_rows != 1)
>     {
>         return false;
>     }
> 
>     $query = "SELECT userid FROM {$access_log_tablename}
>               WHERE page = '{$_SERVER['PHP_SELF']}'
>               AND userid = '" . current_user() . "'";
>     $result = mysql_query($query);
> 
>     if(!mysql_num_rows($result))
>     {
>         $query = "INSERT INTO {$access_log_tablename}
>                   VALUES ('{$_SERVER['PHP_SELF']}',
>                           '" . current_user() . "',
>                           1, NULL)";
>     }
>     else
>     {
>         $query = "UPDATE {$access_log_tablename}
>                  SET visitcount = visitcount + 1, accessdate = NULL
>                  WHERE page = '{$_SERVER['PHP_SELF']}'
>                  AND userid = '" . current_user() . "'";
>     }
> 
>     db_query($query);
> 
>     $num_rows = db_affected_rows($link_id);
> 
>     return ($num_rows == 1);
> }
> 
> ?>
> ------------------------------------
> 
> 
> Any questions, comments, rants, raves, etc... are always welcome!
> 
> 
> Take care,
> 
> Nik
> 
> 
> 

  Return to Index