Part of the EllisLab Network
   
5 of 12
5
Proposal: View Library (updated x3!)
Posted: 25 July 2007 08:03 AM   [ Ignore ]   [ # 61 ]  
Summer Student
Total Posts:  28
Joined  03-09-2007

thanks to all, for helping.

 Signature 

for a life less orinary*

Profile
 
 
Posted: 25 July 2007 12:22 PM   [ Ignore ]   [ # 62 ]  
Research Assistant
RankRankRank
Total Posts:  917
Joined  07-10-2006
Code Arachn!d - 24 July 2007 09:02 PM

One thing I think we should have in this library is the “set_header” aspect of the current CI templating abilities. (see SimpleHeader class http://codeigniter.com/forums/viewthread/51313/#250141)

At least this much

function no_cache() {
  $this
->output->set_header('Last-Modified: ' . gmdate("D, d M Y H:i:s") . ' GMT');
  
$this->output->set_header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
  
$this->output->set_header('Pragma: no-cache');
  
$this->output->set_header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
}

But I’m thinking it would be good to add some function in the class to set the header and then have the no_cache as a config setting or something along those lines…

For that matter, the code between the head elements could be embedded in a view fragment called head and loaded using the part method. Then it might become easier to dynamically control head based on config values as well as code that could conditionally sets values. For example, consider the case where you usually load meta data from language strings for your various modules and also need to load meta data stored with content in a table (e.g., the meta data for a blog article).

Profile
 
 
Posted: 25 July 2007 02:28 PM   [ Ignore ]   [ # 63 ]  
Summer Student
Total Posts:  2
Joined  07-12-2007

I was using the following functions as a ‘helper’ to add things like javascript and css to the header…

I just like that I can use the controller to throw a directory at bundleFiles, which returns an array of paths that are then included in the view..


It makes including stuff like scriptaculous very easy… or it should… one problem is that you’re at the mercy of the filename sort; and so, you have to prepend your js file names with a number so that they load in the right order..


ex. controller:

...
$data['js']= bundleFiles("/scriptaculous");
$this->load->view("main",$data);

...

ex. view:

<head>
<?php
   
if(isset($js)){
     
echo getJavaScript($js);
   
}
?>
...

You can do the same with CSS files etc..  probably not as efficient as the class, but it works for me.

/**
* bundleFiles
*
* gather all files in a directory, and return them in an array.
*
* @access    public
* @param    directory to be scanned
* @param     whether or not to go beyond first directory level
* @param    how far down do you want to go?
* @return    array
*/

function bundleFiles($dir, $recurse=false, $depth=false) {
     
# Original PHP code by Chirp Internet: www.chirp.com.au
     # Please acknowledge use of this code by including this header.
     # array to hold return value
        
$retval = array();
        
# add trailing slash if missing
        
if(substr($dir, -1) != "/") $dir .= "/";
        
# open pointer to directory and read list of files
        
$d = @dir($dir) or die("getFileList: Failed opening directory $dir for reading");
        while(
false !== ($entry = $d->read())) {
            
# skip hidden files
            
if($entry[0] == ".") continue;
            if(
$entry == "index.html") continue;
            if(
is_dir("$dir$entry")) {
                $retval[]
= "$dir$entry";
                if(
$recurse && is_readable("$dir$entry/")) {
                     
if($depth === false) {  $retval = array_merge($retval, getFileList("$dir$entry/", true));
                
}
                
elseif($depth > 0) {
                    $retval
= array_merge($retval, getFileList("$dir$entry/", true, $depth-1));
                    
}  
                }
            }
            
elseif(is_readable("$dir$entry")) {
                $retval[]
= "$dir$entry";
            
}
        }
        $d
->close();
        return
$retval;
}



/**
* getJavaScript
*
* Generates script tags.  Takes one parameter, a string or and array that contains
* the path(s) to javascript file(s).
*
* DO NOT INCLUDE A LEADING SLASH!!!
*
* @access    public
* @param    string or array
* @return    html string
*/

function getJavaScript($path, $html = NULL) {
    
// Loop through if array
    
if(is_array($path)){
        
foreach ($path as $js) {
            $html
.= "<script type='text/javascript' src='" . base_url() . "$js'>\n";
        
}
        
return $html;
    
}
    
    
// Not an array.  Include single file.
    
else{
        
return "<script type='text/javascript' src='" . base_url() . "$path'>";
    
}
}


/**
* getCSS
*
* Generates link tags for CSS.  Takes one parameter, a string or and array that contains
* the path(s) to external style sheet(s) relative to the base URL/public/css.
*
* DO NOT INCLUDE A LEADING SLASH!!!
*
* @access    public
* @param    string or array
* @return    html string
*/


function getCSS($path, $html = NULL) {
    
if(is_array($path)){
        
foreach($path as $css){
            $html
.= "<link href='" . base_url() . $css . "' rel='stylesheet' type='text/css' />\n";
        
}
        
return $html;
    
}
    
    
else {
        
return "<link href='" . base_url() . $path . "' rel='stylesheet' type='text/css' />";
    
}
}

/**
* getModular
*
* Loads module view(s).  Takes one parameter, a string or an array that contains
* the name of the module view file(s) in /system/application/views/modules.
*
* DO NOT INCLUDE A LEADING SLASH
*
*
* @access    public
* @param    string or array
* @return    html CodeIgniter View
*/


function getModular($moduleNames){
    
// if there are more than one...
    
if(is_array($moduleNames)){
        
foreach ($moduleNames as $module) {
            $this
->load->view("modules/" . $module);
        
}
    }
    
    
else {
        $this
->load->view("modules/" . $moduleNames);
    
}
}
Profile
 
 
Posted: 26 July 2007 11:19 PM   [ Ignore ]   [ # 64 ]  
Grad Student
Avatar
Rank
Total Posts:  74
Joined  12-20-2006
function load($tpl, $data = array(), $return = FALSE, $parse = FALSE) {
        $this
->set($data);
        foreach (
$this->parts as $name => $view) {
            $this
->vars[$name] = $this->CI->load->view($view, $this->vars, TRUE);
        
}
        
return (!$parse) ? $this->CI->load->view($tpl, $this->vars, $return) : $this->CI->parser->parse($tpl, $this->vars, $return);
    
}

The last line here allows the load function to optionally work with the CI parser engine.

Profile
 
 
Posted: 26 July 2007 11:30 PM   [ Ignore ]   [ # 65 ]  
Lab Technician
Avatar
RankRankRankRank
Total Posts:  1749
Joined  06-23-2006

Athfar, good idea.

I’ll add parsing functionality, but probably as a separate parse() function.

 Signature 

Mac OS X 10.4.10, Apache 1.3.3, PHP 5.2.3, CodeIgniter 1.5.x., baby!

Profile
 
 
Posted: 27 July 2007 12:56 AM   [ Ignore ]   [ # 66 ]  
Grad Student
Avatar
Rank
Total Posts:  74
Joined  12-20-2006
coolfactor - 26 July 2007 11:30 PM

Athfar, good idea.

I’ll add parsing functionality, but probably as a separate parse() function.

Yea, be sure to do something about the part() function too (I just ran into that lol)...

function part($name, $view, $render_now = FALSE, $parse = FALSE) {
        
if ($render_now) {
            $this
->vars[$name]  = (!$parse) ? $this->CI->load->view($view, $this->vars, TRUE) : $this->CI->parser->parse($tpl, $this->vars, TRUE);
        
} else {
            $this
->parts[$name] = $view;
        
}
    }

It could get scary having the set() variables “global” in all the different “parts” but this could also be a desirable effect.

Good job though, I’m using it smile

Profile
 
 
Posted: 27 July 2007 05:13 AM   [ Ignore ]   [ # 67 ]  
Lab Technician
Avatar
RankRankRankRank
Total Posts:  1749
Joined  06-23-2006

About parsing…

I use a variation of the View library for my own CI subframework and always use parsed templates. You made me realize that parsing support was missing from this public version of the View library. Sorry about that!

How about a $parse config variable instead? That’s how my version of the library handles things. CI’s Parser, which used, also handles non-parsed templates, so by putting the View library into parsing mode, you will get the best of both. That would let you use the single API without having to remember anything extra except to set the config variable to TRUE.

I’ll make that change and upload the new version.

 Signature 

Mac OS X 10.4.10, Apache 1.3.3, PHP 5.2.3, CodeIgniter 1.5.x., baby!

Profile
 
 
Posted: 27 July 2007 05:55 AM   [ Ignore ]   [ # 68 ]  
Lab Technician
Avatar
RankRankRankRank
Total Posts:  1749
Joined  06-23-2006

I’ve updated the View library (again) with the following changes:

Support for configuration file
The following features can be configured in a config/View.php configuration file, as detailed below.

Support for sending No-Cache headers to browser
The library can send no-cache headers to the browser:

$this->view->no_cache();

(I haven’t yet explored whether it’s possible to send replacement headers to “undo” previously-sent no-cache headers - anybody know?)

Configuration value in config/View.php for specifying cache timeout

$config['cache_timeout'] = 30;

Support for Parsed Templates
Not sure how this one got missed, but the library now supports parsing of template files. As you load each partial or the full view, the Parser library is invoked if in parsing mode.

Method #1 - set “parse” configuration value to TRUE in config/View.php

$config['parse'] = TRUE;

Method #2 - call set_parse_mode() function

$this->view->set_parse_mode(TRUE);  // defaults to TRUE, so parameter is optional
 Signature 

Mac OS X 10.4.10, Apache 1.3.3, PHP 5.2.3, CodeIgniter 1.5.x., baby!

Profile
 
 
Posted: 27 July 2007 11:09 AM   [ Ignore ]   [ # 69 ]  
Lab Technician
Avatar
RankRankRankRank
Total Posts:  1749
Joined  06-23-2006

I was having a shower and it suddenly occurred to me that I had the cache logic backwards in the latest version of this library. Setting the “cache” flag to TRUE would send the no-cache headers to the browser. Wonder where my head was this morning?

Anyway, I’ve updated the library so that setting “cache” to TRUE or calling set_cache_mode(TRUE) triggers CI’s cache mechanism. An additional configuration option was added to control the timeout of the cache, which defaults to 30 minutes. Disabling the cache setting in this library (which it is by default), sends the no-cache headers to the browser. My thinking here is that the caching of the browser should match the caching on the server, but I’d like your feedback on this. Maybe this is a little too aggressive?

Should the no-cache headers be sent for every view that is not being cached on the server? Normally, the browser would cache images, javascript, etc. by default.

Thanks.

 Signature 

Mac OS X 10.4.10, Apache 1.3.3, PHP 5.2.3, CodeIgniter 1.5.x., baby!

Profile
 
 
Posted: 27 July 2007 11:34 AM   [ Ignore ]   [ # 70 ]  
Lab Technician
Avatar
RankRankRankRank
Total Posts:  1163
Joined  08-06-2006

cf,

the browser cache is not the same category as the server cache so they should not be yoked.

the browser cache is like a “per session cache” while the default CI caching mechanism is a global cache.

 Signature 

imap_pop get email | site_migrate port sites | OOCalendar | PhotoBox2 gallery | CI/EE 2 word_limiter, yep, wrote it

Profile
 
 
Posted: 27 July 2007 12:21 PM   [ Ignore ]   [ # 71 ]  
Lab Technician
Avatar
RankRankRankRank
Total Posts:  1749
Joined  06-23-2006

Okay, thanks sophistry. I’ll separate the logic again. Too many coding hours lately…

 Signature 

Mac OS X 10.4.10, Apache 1.3.3, PHP 5.2.3, CodeIgniter 1.5.x., baby!

Profile
 
 
Posted: 27 July 2007 12:55 PM   [ Ignore ]   [ # 72 ]  
Lab Technician
Avatar
RankRankRankRank
Total Posts:  1163
Joined  08-06-2006

I believe that the view library is an important advance for CI and your efforts are much appreciated! The CI cache is not very flexible at this point. The main problem is that it caches the whole page.

With regards to server caching…
Al James has a recent thread on a cache library that allows caching PHP objects.
Al has also recently been busy with a template library called Sparks which he says might soon be combined with caching.

Maybe someone could figure out how to weave these two together into server cache-able ‘layoutable’ views demo code. I’m not suggesting building a huge library all in one, but just a few lines of demo code to show how these could be used together.

 Signature 

imap_pop get email | site_migrate port sites | OOCalendar | PhotoBox2 gallery | CI/EE 2 word_limiter, yep, wrote it

Profile
 
 
Posted: 28 July 2007 05:14 AM   [ Ignore ]   [ # 73 ]  
Grad Student
Rank
Total Posts:  76
Joined  06-17-2007

@coolfactor
Thank you for your efforts on this class.
For easy usage, would it be an option to add phpdoc style comments to the methods, similar to CI?

Regards

Wolfgang

Profile
 
 
Posted: 28 July 2007 08:39 AM   [ Ignore ]   [ # 74 ]  
Lab Technician
Avatar
RankRankRankRank
Total Posts:  1749
Joined  06-23-2006

I’ve updated the View library to correct the caching logic. The set_cache_mode() method was removed since it was pointless. Replacing it is the no_cache() method that Athfar had suggested. That method does two things:
(1) tells CI not to cache the view (in case it was previously scheduled for caching)
(2) tells the browser not to cache the view

I hope that is the correct behavior. You can always tell *just* CI to cache the view by using:

$this->view->cache(30);

which just calls CI’s Output::cache() method internally, but the parameter is optional and uses the configured “cache_timeout” value if not specified.

Note: the view is cached automatically just by specifying a timeout value in the config.

With the following, the view will be cached automatically for 30 minutes:

$config['cache_timeout']  = 30;

You can override any default caching by calling:

$this->view->cache(15);  // only cache for 15 minutes

phpDoc comments
I’ve also added phpDoc-style comments.

 Signature 

Mac OS X 10.4.10, Apache 1.3.3, PHP 5.2.3, CodeIgniter 1.5.x., baby!

Profile
 
 
Posted: 28 July 2007 10:44 AM   [ Ignore ]   [ # 75 ]  
Research Assistant
RankRankRank
Total Posts:  917
Joined  07-10-2006
sophistry - 27 July 2007 12:55 PM

Maybe someone could figure out how to weave these two together into server cache-able ‘layoutable’ views demo code. I’m not suggesting building a huge library all in one, but just a few lines of demo code to show how these could be used together.

As much as I respect Coolfactor’s skills and ideas, I think AI’s approach to using a separate Cache library is a good idea from a code reuse point of view—it leads to less code redundance in the framework, standardizes caching code, and should lead to less reading in the docs. This is one area where I hope EllisLabs does a bit a refactoring to the core. The use of cache groups also opens the door to some very fine grained caching approaches that might not seem immediately apparent.

Profile
 
 
   
5 of 12
5
 
Post Marker Legend
New Topic New posts Hot Topic Hot Topic with new posts New Poll New Poll Moved Topic Moved Topic Sticky Topic Sticky topic
Old Topic No new posts Hot Old Topic Hot Topic with no new posts Old Poll Old Poll Closed Topic Closed Topic Announcement Announcements
Theme
Change Theme
Visitor Statistics
The most visitors ever was 819, on March 11, 2010 11:15 AM
Total Registered Members: 120351 Total Logged-in Users: 58
Total Topics: 126476 Total Anonymous Users: 5
Total Replies: 665118 Total Guests: 424
Total Posts: 791594    
Members ( View Memberlist )
Newest Members:  jackmarioRanjanjoyMihai NorthThatchVagariPatient ShareNixnizviVadotlogikCariNet