Welcome Guest, Not a member yet? Register   Sign In
Site library
#1

[eluser]dcheslow[/eluser]
It's nice to have site information in one place... stuff like company name, address, phone number, copyright, etc. Further, each site may have some number of hosts associated with it - only one of which is relevant at any given point in time. It's nice to be able to use EXACTLY the same code in development on localhost as on the testing server and the production server. I've found various ways of handling this... some people put the information in $GLOBALS, some put it in $config, some even put this stuff in a database table... none of those really met all my needs. So I came up with a simple Site class which I'll share here. By putting this class in a CI library I can put all the relevant information about the site in a config file. It looks like this:

Code:
<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

$config['domainname']= 'WiseGarage.com';
$config['companyname']= 'WiseGarage.com';
$config['postal']=array(
        '3404 Browning Street',
        'Victoria, BC  V8P 4E1',
        'CANADA',
        );
$config['phone']= '(250) 888-4161';
$config['email']= '[email protected]';
$config['firstlaunched']= 2008;
$config['offsets']=array(
        'javascript'=>'system/application/assets/javascript/',
        'flash'=>'system/application/assets/flash/',
        'image'=>'system/application/assets/siteimages/',
        'css'=>'system/application/assets/css/',
        'assetcache'=>'system/application/assets/cache/',
        'upload'=>'system/application/uploads/',
        );
$config['hosts'] = array(
    'localhost' => array(
        'baseurl' =>'http://localhost:8888/wisegarage/',
        'basepath'=>'/Applications/MAMP/htdocs/wisegarage/',
        'gspath'=>'/usr/local/bin/gs',
        'debug'=> TRUE,
        'cacheassets'=>TRUE),
    '216.198.218.141' => array(
        'baseurl' =>'http://216.198.218.141/~wisegara/',
        'basepath'=>'/home/wisegara/public_html/',
        'gspath'=>'gs',
        'debug'=> FALSE,
        'cacheassets'=>TRUE),
    'wisegarage.com' => array(
        'baseurl' =>'http://wisegarage.com/~wisegara/',
        'basepath'=>'/home/wisegara/public_html/',
        'gspath'=>'gs',
        'debug'=> FALSE,
        'cacheassets'=>TRUE),
    );

?>

I then autoload this library:

Code:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class Site
{
    protected $_ci;
    public $domainname= '';
    public $companyname= '';
    public $phone= '';
    public $email= '';
    public $postal='';
    public $paths=array();
    public $urls=array();
    public $debug = FALSE;
    public $cacheassets = FALSE;
    public $copyright = '';
    public $simplecopyright= '';
    public $myself = '';

    function __construct($config)
    {
        $this->_ci =& get_instance();
        // load up all the basics
        $this->domainname = $config['domainname'];
        $this->companyname = $config['companyname'];
        $this->phone = $config['phone'];
        $this->_ci->load->helper('url');
        $this->email = safe_mailto($config['email'],'Email '.$config['domainname']);
        // build the mailing address
        $this->postal = $this->companyname;
        foreach($config['postal'] as $thisaddressline)
        {
            $this->postal.='<br />'.$thisaddressline;
        }
        $this->postal.='<br />';
        // get the base url/path (and some other stuff) for whatever host we're using
        foreach($config['hosts'] as $thishost =>$hostconfig)
        {
              if(stristr($_SERVER['SERVER_NAME'],$thishost) !== FALSE)
            {
                foreach($hostconfig as $key=>$value)
                {
                    switch($key)
                    {
                        case 'debug':
                            $this->debug = $value;
                            break;
                        case 'baseurl':
                            $this->urls['base'] = $value;
                            break;
                        case 'basepath':
                            $this->paths['base'] = $value;
                            break;
                        case 'cacheassets':
                            $this->cacheassets = $value;
                            break;
                        default:
                            $this->paths[$key] = $value;            
                    }
                }
            }
        }
        // create all the other paths
        foreach($config['offsets'] as $thisoffsetname=>$thisoffset)
        {
            $this->paths[$thisoffsetname] = $this->paths['base'].$thisoffset;
            $this->urls[$thisoffsetname] = $this->urls['base'].$thisoffset;
        }
        $this->myself = $this->urls['base'].'index.php?/';

        // build the copyright notices
        $years='';
        $lastyear=(int) date('Y');
        for($thisyear=$config['firstlaunched'];$thisyear <= $lastyear; $thisyear++)
        {
            $years.=$thisyear;
            if($thisyear < $lastyear)
            {
                $years.=', ';
            }
        }
        $this->copyright = "Copyright {$years} &copy; all rights reserved by <a href='{$this->urls['base']}' >{$this->companyname}</a>";
        $this->simplecopyright = "Copyright {$years}, all rights reserved by {$this->companyname}";

    }

}
?&gt;

Now I can access information about the site using expressions like:

Code:
$this->site->companyname

and (more importantly)

Code:
$this->site->urls['image']

The class automagically figures out which server is being used and sets all the urls and paths accordingly. It even calculates a copyright notice that is always up-to-date ... sweet!

Hope someone finds this useful.

=dave=
#2

[eluser]xwero[/eluser]
When a library is loaded the method checks if a configuration file is present and loads it so you don't have to add it to the constructor manually.

For the paths i think you are better off creating an automatic base_url setting and add the directories to that base_url.

The main reason why i wouldn't use the library is because it's restrictive. For instance what if there are multiple email addresses i want to display? What if i want to display the copyright differently or even in other languages?

I can see how having a site data object makes sense but i think your contribution is too much focused on your needs.
#3

[eluser]Référencement Google[/eluser]
Quote:When a library is loaded the method checks if a configuration file is present and loads it so you don’t have to add it to the constructor manually.

Can you give an example of how to do that? How should I name the config file so it will be loaded automatically?
#4

[eluser]xwero[/eluser]
loader library snippet
Code:
function _ci_init_class($class, $prefix = '', $config = FALSE)
    {    
        $class = strtolower($class);
        
        // Is there an associated config file for this class?
        if ($config === NULL)
        {
            if (file_exists(APPPATH.'config/'.$class.EXT))
            {
                include(APPPATH.'config/'.$class.EXT);
            }
        }
The _ci_init_class is called in the _ci_load_class which is called in the library method so the example would be a application/config/library.php file if the library is named Library.
#5

[eluser]Référencement Google[/eluser]
Ho ok, thanks I didn't knew that functionality, that's cool.
#6

[eluser]esra[/eluser]
I think it is a nice first release. xwero's comment about language differences could be handled by loading a site_lang file in the constructor. For example, the site name, copyright settings and a few others could reside in a language file and the site class could populate those with language strings.

A default email address for a site is useful, I think. That email address as well as other email addresses might be better handled using a separate contacts agent which allowed email to be sent to multiple users.
#7

[eluser]dcheslow[/eluser]
Thanks to all for the comments. I forgot to mention that both the library and the config file should be named 'site.php' so that CI will do it's magic with autoloading.

So long as the language library is loaded before the site library, there is no problem with internationalizing. It's worth noting that "copyright" is not an international concept. Usually, the rest of the information managed by this class (company name, mailing address, etc.) does not get translated when internationalizing.

I have found it useful to have a single email address for the site AND to use a contacts library to manage email addresses for people/groups. I use the site email address in places like the page footer and the signature block of automatically generated email messages. If you want these emails to go to several individuals, it's easier to setup an email alias than to change the website.

It's a matter of business logic as to which bits of information are one-to-one with sites. Generally speaking, a site has only one company name, one mailing address, one (central) phone number, etc. This class is for these bits of information. The other thing the class does that I find very handy is allow me to specify different paths on different servers. Yes, it handles all the "base_url + offset" stuff, but it does a bit more. In the example configuration I posted, you can see that the ghostscript application ('gs') is located in one place on localhost and a different place on the production server. You don't need to do anything special to add application paths, just add them in the config file and you're ready to go.

I am definitely open to suggestions for improvement. Keep 'em coming...

Thanks,

=dave=
#8

[eluser]xwero[/eluser]
Now i know your open for improvement here are a few changes you can add

__construct should be replaced by Site to make the library php4 compatible

I think the urls and the paths should have a strict object syntax instead of a hybrid object/array syntax.
Code:
// create all the other paths
        foreach($config['offsets'] as $thisoffsetname=>$thisoffset)
        {
            $path = $thisoffsetname.'_path';
            $this->$path = $this->paths['base'].$thisoffset;
            $url = $thisoffsetname.'_url';
            $this->$url = $this->urls['base'].$thisoffset;
        }

You can check if the email is a string or an array and if it's an array you can do the same as for the urls and paths.

The address should be in an associative array to make it easier to get the parts. Now you have a hard coded way to display an address. I think it's better to provide a method to display your address. You could use a static template or you can add parameters to the method for each tag someone could use. As i see it that are 6 parameters: before_street, after_street, before_city, after_city, before_country, after_country

For the copyright you can also create a method.

The best of luck with your library
#9

[eluser]dcheslow[/eluser]
Excellent suggestions!

I moved buildaddress() and buildcopyright() out of the constructor just to make those logical operations a bit separate. I thought about breaking the address into an associative array but I really can't think of an actual use for the parts of the address. For example, when might you actually need to know the country of the site itself? Likewise with copyright - when would you ever want a copyright notice formatted in more than one way? In the interest of keeping the library simple but still useful, I did not make many changes to those parts. I did keep the address as an array... just in case you want it line-by-line.

I really liked the idea of getting rid of the arrays for urls and paths... it turned out to be just a bit more complicated. I did not want to append "_url" or "_path" to variable names. Rather, I wanted a syntax that was entirely logical ... not at all procedural. I ended up with this:

$this->site->urls->css
or
$this->site->paths->upload

which is about as logical as it can get. In order to get this syntax I needed to use a dynamic object class which is only slightly modified from this site http://www.sematopia.com/?p=150 . This class is PHP 5+ only, so that decided the suggestion of renaming the constructor. The Dynamicobject class is pretty cool, I suggest you read about it... many useful applications

So here's a revised version of libraries/site.php (config/site.php stays the same as above):

Code:
&lt;?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class Dynamicobject
{

    private $param = array();

    public function __construct() {}

    private function __get($name)
    {
        if (isset($this->param[$name]))
        {
            $res = $this->param[$name];
        }
        else
        {
            $res = false;
        }
        return $res;
    }

    private function __set($name, $val)
    {
        $this->param[$name] = $val;
        return TRUE;
    }

    private function __isset($name)
    {
        return isset($this->param[$name]);
    }

    private function __unset($name)
    {
        unset($this->param[$name]);
    }

    private function __call($name, $var) {}

}


class Site
{
    protected $_ci;
    public $domainname= '';
    public $companyname= '';
    public $phone= '';
    public $email= '';
    public $postal='';
    public $paths=null;
    public $urls=null;
    public $debug = FALSE;
    public $cacheassets = FALSE;
    public $copyright = '';
    public $simplecopyright= '';
    public $myself = '';
    public $firstlaunched='';
    public $address='';

    function __construct($config)
    {
        $this->_ci =& get_instance();
        // load up all the basics
        $this->domainname = $config['domainname'];
        $this->companyname = $config['companyname'];
        $this->firstlaunched = $config['firstlaunched'];
        $this->phone = $config['phone'];
        $this->_ci->load->helper('url');
        $this->email = safe_mailto($config['email'],'Email '.$config['domainname']);
        // build the mailing address
        $this->postal = $config['postal'];
        $this->buildaddress();
        // get the base url/path (and some other stuff) for whatever host we're using
        $this->urls = new Dynamicobject();
        $this->paths = new Dynamicobject();
        foreach($config['hosts'] as $thishost =>$hostconfig)
        {
              if(stristr($_SERVER['SERVER_NAME'],$thishost) !== FALSE)
            {
                foreach($hostconfig as $key=>$value)
                {
                    switch($key)
                    {
                        case 'debug':
                            $this->debug = $value;
                            break;
                        case 'baseurl':
                            $this->urls->base=$value;
                            break;
                        case 'basepath':
                            $this->paths->base=$value;
                            break;
                        case 'cacheassets':
                            $this->cacheassets = $value;
                            break;
                        default:
                            $this->paths->$key = $value;            
                    }
                }
            }
        }
        // create all the other paths
        foreach($config['offsets'] as $thisoffsetname=>$thisoffset)
        {
            $this->paths->$thisoffsetname = $this->paths->base.$thisoffset;
            $this->urls->$thisoffsetname = $this->urls->base.$thisoffset;
        }
        $this->myself = $this->urls->base.'index.php?/';
        // build the copyright notice
        $this->buildcopyright();
    }
    
    function buildcopyright()
    {

        // build the copyright notices
        $years='';
        $lastyear=(int) date('Y');
        for($thisyear=$this->firstlaunched;$thisyear <= $lastyear; $thisyear++)
        {
            $years.=$thisyear;
            if($thisyear < $lastyear)
            {
                $years.=', ';
            }
        }
        $this->copyright = "Copyright {$years} &copy; all rights reserved by <a href='{$this->urls->base}' >{$this->companyname}</a>";
        $this->simplecopyright = "Copyright {$years}, all rights reserved by {$this->companyname}";        
    }
    
    function buildaddress()
    {
        $this->address = $this->companyname;
        foreach($this->postal as $thisaddressline)
        {
            $this->address.='<br />'.$thisaddressline;
        }
          $this->address.='<br />';
        
    }

}
?&gt;
#10

[eluser]xwero[/eluser]
Instead of dynamicobject i would use the php native stdClass. Your code would be
Code:
// get the base url/path (and some other stuff) for whatever host we're using
        $this->urls = new stdClass();
        $this->paths = new stdClass();
and you would not need the dynamicobject class.

I think you should make the library php4 compatible. Only the _ci variable is is protected the rest is public and that is the same as var. The main reason for making the library php 4 compatible is because CI is.




Theme © iAndrew 2016 - Forum software by © MyBB