2
\$\begingroup\$

I have the below script which returns CSS files based on production or development environment. The development section is fine; but for production I have to do 2 loops to get the files. Is there a cleaner/better way?

function get_css_files()
{
   $CI =& get_instance();
    $return = array();

    $css_files = array(
        array('path' =>'css/jquery.gritter.css', 'media' => 'all', 'group' => '1.css'),
        array('path' =>'css/jquery-ui.css', 'media' => 'all', 'group' => '1.css'),
        array('path' =>'css/bootstrap-select.css', 'media' => 'all', 'group' => '1.css'),
        array('path' =>'css/select2.css', 'media' => 'all', 'group' => '1.css'),
        array('path' =>'css/font-awesome.min.css', 'media' => 'all', 'group' => '1.css'),
        array('path' =>'css/jquery.loadmask.css', 'media' => 'all', 'group' => '1.css'),
        array('path' =>'css/token-input-facebook.css', 'media' => 'all', 'group' => '1.css'),
        array('path' =>'css/KeyTips.min.css', 'media' => 'all', 'group' => '1.css'),
        array('path' =>'css/bootstrap-colorpicker.min.css', 'media' => 'all', 'group' => '2.css'),
        array('path' =>'css/jquery.ml-keyboard.css', 'media' => 'all', 'group' => '2.css'),
    );
    if(!defined("ENVIRONMENT") or ENVIRONMENT == 'development')
    {
        $return = $css_files;
    }
    else
    {
        $groups = array();

        foreach($css_files as $css)
        {
            $groups[$css['group']] = TRUE;
        }

        foreach(array_keys($groups) as $css_group_file)
        {
            $return[] = array('path' =>"css/$css_group_file", 'media' => 'all');
        }
    }

    if(is_rtl_lang())
    {
        $return[] = array('path' =>'css/rtl.css', 'media' => 'all');
    }
    return $return;
}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ How dynamic is $css_files? Will this always be hard coded? How often will it change? If they change will changes be made manually in the code? \$\endgroup\$ Apr 2 '15 at 15:56
  • \$\begingroup\$ It won't change too often. It is a manual process when we add new files \$\endgroup\$ Apr 2 '15 at 16:08
1
\$\begingroup\$

One quick one.

if(!defined("ENVIRONMENT") or ENVIRONMENT == 'development')

If ENVIRONMENT has only two defined values e.g. 'development' and 'production' then use:

if(ENVIRONMENT != 'production')

For the Group loop:

foreach(array_keys($groups) as $css_group_file)

array_keys is not needed:

 foreach($groups as $css_group_file => $val)

As far as optimization of two loops to one, it does not matter as these two loops would execute in less than a millisecond, I would guess about about 400 microseconds.


I would rather see ENVIRONMENT equal to 0 instead of 'development'
and 1 instead of 'production'

This is so if it is undefined it will equate to zero with intval().

if (intval(ENVIRONMENT)){}

The following is rather unconventional but it is simple and fast.

Run this only when CSS files needs editing:

$css_files = array(
    array('path' =>'css/jquery.gritter.css', 'media' => 'all', 'group' => '1.css'),
    array('path' =>'css/jquery-ui.css', 'media' => 'all', 'group' => '1.css'),
    array('path' =>'css/bootstrap-select.css', 'media' => 'all', 'group' => '1.css'),
    array('path' =>'css/select2.css', 'media' => 'all', 'group' => '1.css'),
    array('path' =>'css/font-awesome.min.css', 'media' => 'all', 'group' => '1.css'),
    array('path' =>'css/jquery.loadmask.css', 'media' => 'all', 'group' => '1.css'),
    array('path' =>'css/token-input-facebook.css', 'media' => 'all', 'group' => '1.css'),
    array('path' =>'css/KeyTips.min.css', 'media' => 'all', 'group' => '1.css'),
    array('path' =>'css/bootstrap-colorpicker.min.css', 'media' => 'all', 'group' => '2.css'),
    array('path' =>'css/jquery.ml-keyboard.css', 'media' => 'all', 'group' => '2.css')
);
if(!defined("ENVIRONMENT") or ENVIRONMENT == 'development'){
   $fp = '/home/user/css/p0.ser','w');   
   fwrite($fp,serialize($css_files));
   fclose($fp);
   $css_files[] = array('path' =>'css/rtl.css', 'media' => 'all');
   $fp = '/home/user/css/p1.ser','w');   
   fwrite($fp,serialize($css_files));
   fclose($fp);
   $groups = array();
   foreach($css_files as $css){
     $groups[$css['group']] = TRUE;
   }
   foreach(array_keys($groups) as $css_group_file){
        $return[] = array('path' =>"css/$css_group_file", 'media' => 'all');
   }
   $fp = '/home/user/css/d0.ser','w');   
   fwrite($fp,serialize($return));
   fclose($fp);
   $return[] = array('path' =>'css/rtl.css', 'media' => 'all');
   $fp = '/home/user/css/d1.ser','w'); 
   fwrite($fp,serialize($return));
   fclose($fp);

New Production Function:

This is based on is_rtl_lang() returning a value of zero or one and

$CI =& get_instance();
$css_file = array(); 
$css_file ['production'][0]) = '/home/user/css/p0.ser';
$css_file ['production'][1]) = '/home/user/css/p1.ser';
$css_file ['development'][0]) = '/home/user/css/d0.ser';
$css_file ['development'][1]) ='/home/user/css/d1.ser' ;
return unserialize(file_get_contents($css_files[ENVIRONMENT][is_rtl_lang()]);   

If these more efficient changes were made:

From: ENVIRONMENT = 'production'; 
To:   ENVIRONMENT = 1 ;

From: ENVIRONMENT = 'development'; 
To:   ENVIRONMENT = 0 ;

Then:

$css_file [1][0]) = '/home/user/css/p0.ser';  // production without RTL
$css_file [1][1]) = '/home/user/css/p1.ser';  // production with RTL
$css_file [0][0]) = '/home/user/css/d0.ser';  // development without RTL
$css_file [0][1]) ='/home/user/css/d1.ser' ;  // development with RTL

unserialize(file_get_contents($css_files[intval(ENVIRONMENT)][is_rtl_lang()]);   

NOTE: intval() was added to $css_files[ENVIRONMENT]
to become: $css_files[intval(ENVIRONMENT)]

Where intval(ENVIRONMENT) takes care of the undefined condition.


Better Yet:

Seeing you are using PHP to populate the CSS links, there is an even better method.

Because each CSS file requires a round trip HTTP Request/Response, why not reduce it to one.
This is especially beneficial on a mobile phone Browser. To conserve battery a smartphone will drop the radio signal between requests. It can take seconds for the phone to reestablish the radio connection.
This is why it is important that each file loaded by the Browser contain Connection: keep-alive in the Request Header.

Furthermore because the Browser will not begin rendering until all the CSS is loaded, it is advantageous to bring it in with a single HTTP Request.

$css = file_get_contents('/home/user/public_html/css/css/jquery.gritter.css') . "\n";
$css .= file_get_contents('/home/user/public_html/css/css/jquery-ui.css') . "\n";
$css .= file_get_contents('/home/user/public_html/css/css/bootstrap-select.css') . "\n";
$css .= file_get_contents('/home/user/public_html/css/css/select2.css') . "\n";
$css .= file_get_contents('/home/user/public_html/css/css/font-awesome.min.css') . "\n";
$css .= file_get_contents('/home/user/public_html/css/css/jquery.loadmask.css') . "\n";
$css .= file_get_contents('/home/user/public_html/css/css/token-input-facebook.css') . "\n";
$css .= file_get_contents('/home/user/public_html/css/css/KeyTips.min.css') . "\n";
$css .= file_get_contents('/home/user/public_html/css/css/bootstrap-colorpicker.min.css') . "\n";
$css .= file_get_contents('/home/user/public_html/css/css/jquery.ml-keyboard.css') . "\n";
$fp = '/home/user/public_html/css/styles.css';
fwrite($fp,$css);
fclose($fp);
\$\endgroup\$
3
  • 1
    \$\begingroup\$ 'development' vs. 'production' is much clearer than magic values 0 and 1. And clearly the intention is to default to development, rather than crash if the constant is undefined. \$\endgroup\$ Apr 2 '15 at 18:30
  • \$\begingroup\$ @200_success I agree with you, but I would still use integers for a plethora of very valid reasons. I also included a solution where ENVIRONMENT = 'production' and ''development` for those that think like you. The integer values can be documented in code comments and user documentation. There are many published APIs that use integer values for parameters. And clearly if it is undefined and 'development ' equates to 0, intval(ENVIRONMENT) will default to 'development ' as stated in my post. That is why I used zero for development. \$\endgroup\$ Apr 2 '15 at 18:45
  • \$\begingroup\$ @200_success While I appreciate you taking the time to moderate, I have an issue with some of your comments and down votes. Not just on my posts but also on other's posts. Too often your comments are without merit as you do not take the time to understand the post. Like this post. In your comment here you said "And clearly the intention is to default to development, rather than crash if the constant is undefined", when I had stated the purpose of using an integer so the intval() would default to 'development' and I provided an alternate solution for numeric vs. string values. \$\endgroup\$ Apr 2 '15 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.