Home arrow PHP arrow Page 3 - Building a Site Engine Using PHP, Part 3

Stop Blocking Me - PHP

In this third article of the series, Iíll show you how the database and directories should be set up. Iíll also talk about the how to create, install, and use a content block, which mostly relies on arrays and array functions. I'll cover proper authentication methods for such a project so that multiple sites can run off the same users table in the database, while not barring a username from being used on a site because it is being use on another, all the while keeping the authentication accurate and secure from break-ins. (For part 2, see here.)

TABLE OF CONTENTS:
  1. Building a Site Engine Using PHP, Part 3
  2. Wanna Go Out on a Data?
  3. Stop Blocking Me
  4. Insert Username Here
By: James Murray
Rating: starstarstarstarstar / 48
June 28, 2004

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

Now itís about time to talk about the block system. Donít worry if the concept escapes you; itís taken me a lot of time and trial and error to get this all working right. Since Iím such a nice guy, Iím going to save you the trouble and tell you all about how it works so you donít have to pull your hair out. The block system can be very confusing if you donít pay close attention to what it does. Working with the block system can cause a lot of headaches. Now, on to the block system.

The block system is very intricate, so take your time when working with it or it can get very out of hand. At the beginning of our class, define all the variables that are going to be used in the class. Since PHP5 had been in beta 1 stage, it allows you to declare your variables at the beginning of a class with public or private. We want to define all ours as public so they can be used elsewhere in the site engine. Here are all the variables weíll be using:

    public $bcount;
    public $blocks_list;
    public $columns;
    public $rows;
    public $cur_block;
    public $cur_tags;

As you can see, weíll use nine variables through out the blocks plug-in. $bcount is a variable that will hold the number of blocks that have actually been loaded. $columns is the variable that weíre going to use to hold an array of each column thatís in our template. $rows is basically the same as $columns, but instead of holding an array of columns, itís going to hold an array of the rows in each column, as we use the column. $cur_block will hold the data for the block thatís currently being parsed, in our script. $cur_tags is the array that will hold all the block information that will replace the tags in our block template, with the actual block information. $blocks_list is the most important -- itís an array that holds all the information about our blocks, information such as the blockís titles, content, what column to load in, and what order it is in the column.

Now run our SQL query to select all the blocks that will be shown on the current page. Start by making our function. Name it blocks() so that when the blocks class is called it will automatically run the function.

function blocks(){

Now declare all the variables that weíll use as global. That way weíll be able to use all the data from the other classes in this function. Weíre also going to give our $bcount variable the value of 0 because we donít have any blocks loaded just yet.

        global $sql,$plugins,$modules,$site,$user;

        $this->bcount=0;

Now that weíre started on the function, we want to start a loop to make part of our query; this particular loop is going to count the number of groups the user belongs to from the $user->user[Ďgidsí] variable that I'll go over in a minute, then itís going to get the value of each group ID. Then it will generate the part of our query that makes it so that only blocks authorized for users authentication level are selected. Just a personal tip here -- when you make a script that generates a query or part of a query, itís usually a good idea to echo the query to the browser to make sure itís generating exactly what you want.

        $i=0;
        $b_grp="";
        while($i<$count=count($user->user['gids'])){
            $b_grp.="blocks.group_ID = '{$user->user['gids'][$i]}'";
            $i++;
            if($i==$count){
                $b_grp.=" ";
            }else{
                $b_grp.=" OR ";   
            }
        }

Now itís time for the meat of the blocks plug-in, the main SQL query. This query is fine tuned to select only the block information from the blocks that are supposed to be shown on the requested page, that meet a few prerequisites. For the blocks to be selected, the blocks must have a plug-in thatís been initialized; they must have a module thatís been initialized; they must have a site ID thatís the same as the ID of the site thatís requesting them; they must be within the authentication levels as the user requesting them; and they must be set to show up on the current page, or all pages. Another thing about the query is that we use the $b_grp, that contains our user group part of our query, in the query, as you can see in the following query.

        $blocks=$sql->_query("SELECT
                                  `blocks`.`block_ID`,
                                  `blocks`.`block_title`,
                                  `blocks`.`block_file`,
                                  `block_location`.`block_col`,
                                  `block_location`.`block_row`,
                                  `plugins`.`plugin_dir`,
                                  `plugins`.`plugin_file`
                            FROM
                                  `block_location`,
                                  `blocks`,
                                  `plugin_status`,
                                  `plugins`,
                                  `module_status`,
                                  `modules`
                            WHERE
                                  (`blocks`.`block_ID` = `block_location`.`block_ID`) AND
                                  (`blocks`.`plugin_ID` = `plugin_status`.`plugin_ID`) AND
                                  (`plugins`.`plugin_ID` = `plugin_status`.`plugin_ID`) AND
                                  (`plugin_status`.`plugin_status` = 'initialized') AND
                                  (`blocks`.`mod_ID` = `module_status`.`mod_ID`) AND
                                  (`modules`.`mod_ID` = `module_status`.`mod_ID`) AND
                                  (`module_status`.`mod_status` = 'initialized') AND
                                   $bgs
                                  (`block_location`.`site_ID` = '{$site->site['ID']}') AND
                                  ((`block_location`.`block_page` = 'all') OR
                                  (`block_location`.`block_page` = '{$site->site['page']}'))
                            ORDER BY
                                  `block_location`.`block_col`,
                                  `block_location`.`block_row`");

After the query returns the results in the $blocks variable, get the information from it with the _fetch_object() function that we made in the SQL class; this enables us to call the results from the query as an object. Then weíll rebuild it into another array that will be a little more user friendly to us later on in the project. The reason the new array is easier to use is because we set the array keys to the coordinates of the block; that way the engine knows that the block in the array thatís set as $blocks_list[1][2] (read as blocks list column 1 row 2) as the 2nd block down in the 1st column.

        while($block=$sql->_fetch_object($blocks)){
            if(file_exists("{$block->plugin_dir}/{$block->plugin_file}/blocks/{$block->block_file}.blk.php")){
                $this->blocks_list['column'.$block->block_col][$block->block_row]['block_path']="{$block->plugin_dir}/{$block->plugin_file}/blocks/{$block->block_file}.blk.php";
                $this->blocks_list['column'.$block->block_col][$block->block_row]['block_ID']=$block->block_ID;
                $this->blocks_list['column'.$block->block_col][$block->block_row]['block_title']=$block->block_title;
            }else{
                $this->blocks_list['column'.$block->block_col][$block->block_row]['block_path']="plugins/missing/blocks/404.blk.php";
                $this->blocks_list['column'.$block->block_col][$block->block_row]['block_ID']=$block->block_ID;
                $this->blocks_list['column'.$block->block_col][$block->block_row]['block_title']="Missing Block";
            }
        }

For example, if I were to replace the variables in the following code with their values, for the 1st block in the 2nd column, the result would look like this:

$this->blocks_list['column2'][1]['block_path']="plugins/test/blocks/test.blk.php";
$this->blocks_list['column2'][1]['block_ID']= "4";
$this->blocks_list['column2'][1]['block_title']="Test Block";

The reason we use the actual words ďcolumn1Ē, ďcolumn2Ē, and ďcolumn3Ē instead of just using the column numbers is because those will also be used by the template plug-in to replace tags with the blocks in the correct column. After we build the $blocks_list array, weíll go ahead and call the function parse_blocks() which actually puts the blocks in loading order, then ďpacksĒ them (as Iíd say) and sends them over to the template plug-in that weíll be discussing in the new article.

        $this->parse_blocks();
    }

The parse_blocks function is an important part of the blocks plug-in, if not the most important. What it does is it looks at the list of blocks that we just put together in the blocks() function, and it puts them in order by column, then by row. After that it calls the blockís template data from the template plug-in, parses it all into an array that contains strings of data that can be outputted to the browser, named $cur_column. Each array key of $cur_column is named as the column name that the data will be put into. After the array is built we send all the data to the template plug-in where it gets used and then sent to the browser.

This function is actually a fairly simple process. First we name the function, and set up our global variables.

    function parse_blocks(){
        global $template,$plugins;

Then we check to make sure the $blocks_list array have been built without errors

        if(is_array($this->blocks_list)){

If the array looks like itís all right, we then get the keys from the array that contains all the column names that is produced by the template plug-in, and set them to the values of another array called $columns. We then start a for each loop that will select each element from the $columns array, that will then make yet another array based on the keys from the specified column element of the $blocks_list array. We then start another for each loop that will process the data each block in the $blocks_list array.

            $this->columns=array_keys($template->columns);
            foreach($this->columns as $column){
                $this->rows=array_keys($this->blocks_list[$column]);
                foreach($this->rows as $row){

The easiest way to work with the current block at this level is to set it as the value of another easier to work with variable, weíll call it $cur_block,

                    $this->cur_block = $this->blocks_list[$column][$row];   

After thatís all taken care of, weíll go ahead and get "down and dirty" with our block data. First, set up a temporary array of all the data for the current block; at the moment the only data weíre worried about is the block title, the block content, and the block ID.

                        $this->cur_tags=array('block_title'=>$this->cur_block['block_title'],'block_ID'=>$this->cur_block['block_ID']);

To get the file that contains the blockís content, weíll have to include it and set it to a variable. That will contain the data after itís been included. However, itís a little tricky to do that because if you just include it, all the data from the include will show up at the top of the page instead of in the block. To fix this we turn to output buffering. Traditionally output buffering will stop all data output to the browser until itís told to stop buffering, at which time it will send all the data that it stopped to the browser. In this case we'll still tell it to stop buffering, but instead of having it send the data to the browse, weíre going to tell it to get the contents of the buffer, set it as the value of a variable then flush (also known as empty) the current buffer. This way we get all the contents of our include without it sending the data directly to the browser. After we have the content of our block, weíll add that to the $cur_tags array.

                        ob_start();
                        @include($this->cur_block['block_path']);
                        $bdata=$template->replace($this->cur_tags,ob_get_clean());
                        $this->cur_tags['block_content']=$bdata;

Donít worry itís winding down to the end of the blocks plug-in. now we have all our block data right where we want it. So what weíre going to do with it is pass all the info to the replace() function that we have set up in our templates plug-in which will fill in all the tags in our block template with the data in the $cur_tags array. Then it will assign it to the $cur_column variable, using the column name as the array key. Then after all the loops are finished weíll send all the data to the function that builds the columns and outputs it all to the browser in the, in the templates plug-in.

                        $this->cur_column[$column].=$template->replace($this->cur_tags,$template->loaded->block);
                        unset($this->cur_block,$this->cur_tags,$bdata);
                        $this->bcount++;
                }
            }
            $template->build_cols($this->cur_column);
        }       
    }

}



 
 
>>> More PHP Articles          >>> More By James Murray
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: