Part of the EllisLab Network
This thread is a discussion for the wiki article: Modularity in CodeIgniter PHP5
   
1 of 2
1
Modularity in CodeIgniter PHP5
Posted: 16 December 2008 12:19 PM   [ Ignore ]  
Grad Student
Avatar
Rank
Total Posts:  74
Joined  02-26-2008

Hey guys! I’d love to hear what you think about this new plugin I’ve made. Do you think it is useful or not? Any ideas for improvement are welcome.

—Jonathon

Plugin Introduction

I’ve become sick and tired of CodeIgniter’s $this-centeredness and I want to use static PHP5 classes to access core CodeIgniter objects such as libraries, models, view, and db. So, I have written a very simple set of wrapper classes.

Advantages:
* No more calling get_instance() when you need to access the framework inside a model, library, helper, or view
* More concise syntax
* Support for multiple database connections

Requirements:
* CodeIgniter 1.5+
* PHP5+

Installation:
This is a plugin so no core hacking is required. Simply download modular_pi.zip and extract it into your application/plugins folder. Load it just like any other plugin.

How to use the Modularity Plugin

Views

# old way
$this->load->view('myview'$data);
# new way
View::show('myview'$data);

# old way
$pagetext $this->load->view('myview'$dataTRUE);
# new way
$pagetext View::parse('myview'$data); 

Libraries

# old way
$this->load->library('mylibrary');
$this->library->do_something();

# new way
Libs::e('mylibrary')->do_something();  // the library automatically loads if needed 

Models

# old way
$this->load->model('mydatamodel');
$this->mydatamodel->do_something();

# new way
Models::e('mydatamodel')->do_something();  // the model automatically loads if needed 

Databases

# old way - default database
$this->load->database();
$query $this->db->query($sql);

# new way
$query DB::h()->query($sql);  // the database automatically loads if needed

# old way - multiple database connections
$dbh1 $this->load->database('db1'TRUE);
$dbh2 $this->load->database('db2'TRUE);
$query1 $dbh1->query($sql);
$query2 $dbh2->query($sql);

# new way
$dbh1 DB::h('db1')->query($sql);
$dbh2 DB::h('db2')->query($sql); 

Inside libraries, helpers, or views

# old way
$CI =& get_instance();
$CI->load->model('mymodel');
$CI->mymodel->do_something();

# new way
Models::e('mymodel')->do_something(); 
 Signature 

[ Cron bootstrapper ] [ Modularity ] [ Sitemaps ] [ Query Browser ] [ Paging Simplified ] [ jonathonhill.net ]

Profile
 
 
Posted: 16 December 2008 12:42 PM   [ Ignore ]   [ # 1 ]  
Sr. Research Associate
Avatar
RankRankRankRankRank
Total Posts:  3176
Joined  06-11-2007

Good work! Can definitely see the advantages here, but I’m slightly put off by the e() and h() static methods. What do they stand for and what do they do?

 Signature 

————————
Blog | Twitter | GitHub | BitBucket
————————-
PyroCMS - open source modular CMS built with CodeIgniter
PancakeApp - Simple, hosted invoicing/w project management

Profile
 
 
Posted: 16 December 2008 12:48 PM   [ Ignore ]   [ # 2 ]  
Grad Student
Avatar
Rank
Total Posts:  74
Joined  02-26-2008

I’m open to ideas for that, but e() would be ‘execute’ and h() would be ‘handle’ (as in database handle).

 Signature 

[ Cron bootstrapper ] [ Modularity ] [ Sitemaps ] [ Query Browser ] [ Paging Simplified ] [ jonathonhill.net ]

Profile
 
 
Posted: 16 December 2008 02:11 PM   [ Ignore ]   [ # 3 ]  
Sr. Research Associate
Avatar
RankRankRankRankRank
Total Posts:  3176
Joined  06-11-2007

Might be an idea to throw in an alisa method for that then. Short syntax available, but longer for us who like readable code.

 Signature 

————————
Blog | Twitter | GitHub | BitBucket
————————-
PyroCMS - open source modular CMS built with CodeIgniter
PancakeApp - Simple, hosted invoicing/w project management

Profile
 
 
Posted: 16 December 2008 02:15 PM   [ Ignore ]   [ # 4 ]  
Lab Assistant
RankRank
Total Posts:  166
Joined  01-30-2008

If i am correct using your method autoloading wouldn’t be necessary anymore. (for most of the cases).
Why not use the same method name instead of differnt ones (e(), parse(), h())?

Profile
 
 
Posted: 16 December 2008 02:30 PM   [ Ignore ]   [ # 5 ]  
Grad Student
Avatar
Rank
Total Posts:  74
Joined  02-26-2008
freshface - 16 December 2008 07:15 PM

If i am correct using your method autoloading wouldn’t be necessary anymore. (for most of the cases).
Why not use the same method name instead of differnt ones (e(), parse(), h())?

You are correct that most autoloading would be unnecessary.

I wouldn’t want to name them all the same thing because they don’t all do the same thing. e() fetches a library or model, h() fetches a database connection. parse() returns a parsed view as a string, show() displays the view.

 Signature 

[ Cron bootstrapper ] [ Modularity ] [ Sitemaps ] [ Query Browser ] [ Paging Simplified ] [ jonathonhill.net ]

Profile
 
 
Posted: 17 December 2008 08:20 AM   [ Ignore ]   [ # 6 ]  
Sr. Research Associate
Avatar
RankRankRankRankRank
Total Posts:  3176
Joined  06-11-2007
freshface - 16 December 2008 07:15 PM

If i am correct using your method autoloading wouldn’t be necessary anymore. (for most of the cases).
Why not use the same method name instead of differnt ones (e(), parse(), h())?

Why not use the same method name instead of differnt ones (e(), parse(), h())?

I think he meant to use the same names as the CI methods they are replacing, but that’s is not going to be possible in this case.

e(), h() etc are methods in the new classes that are used to call other functions. It needs to go to a method so the class can be passed the parameters needed to run anything… if that makes any sense.

Basically e and h just try to find $this or a property of $this such as $this->my_model so you can do some method chaining to find the rest. This could be achieved with some Object Overloading by passing constants, but the headache-to-benefit ratio for me is not there right now.

 Signature 

————————
Blog | Twitter | GitHub | BitBucket
————————-
PyroCMS - open source modular CMS built with CodeIgniter
PancakeApp - Simple, hosted invoicing/w project management

Profile
 
 
Posted: 17 December 2008 08:51 AM   [ Ignore ]   [ # 7 ]  
Grad Student
Avatar
Rank
Total Posts:  74
Joined  02-26-2008

When PHP5.3 is released, I plan to re-write the class to use the __callStatic() magic methods. That would allow you to use syntax like this:

Models::mymodel()->do_something(); 

instead of:

Models::e('mymodel')->do_something(); 

If PHP5.3 were to support the use of __isset() in static context, you could do this:

Models::$mymodel->do_something(); 

The whole point is namespacing models and libraries into their own namespace, and accessing them globally. You can’t reference $this everywhere, that’s why you have to call get_instance(). Static classes are available globally. I would love to see CI integrate more usage of static classes but they can’t until they drop PHP4. I believe Kohana, which is PHP5, does use some but I have not taken time to learn it. I also get the feeling that Kohana is not quite as mature as CI is.

Of course, you could design your libraries and models as static classes themselves, but you would not be able to load it using the normal $this->load->model(‘mymodel’) method. You’d have to stick it in a helper or manually include the file. Then you could just do:

Mymodel::do_something(); 

But then you lose the namespacing. Whenever PHP5.3 comes out, you’ll be able to assign an arbitrary namespace and call it like this:

Models::Mymodel::do_something(); 
 Signature 

[ Cron bootstrapper ] [ Modularity ] [ Sitemaps ] [ Query Browser ] [ Paging Simplified ] [ jonathonhill.net ]

Profile
 
 
Posted: 17 December 2008 09:42 AM   [ Ignore ]   [ # 8 ]  
Sr. Research Associate
RankRankRankRankRank
Total Posts:  4785
Joined  07-14-2006

Kohana is preparing for namespaces but that version is pushed forward because of the whole discussion in the php mailinglists about the use of double colons for both namespaces and class referencing. Then going for the forward slash to identify namespaces. I haven’t followed it further.

I have to agree with pyromaniac that the methods that are public have to be descriptive. e() could be initialize() and maybe you add a load() method that doesn’t initializes the library/model because now you have to use load->helper or load->plugin. 

Although i like to reduce the typing, your plugin obscures the way the framework works. Therefor bugs will be harder to spot. I thing this is the biggest reason not to use your plugin.

Profile
 
 
Posted: 17 December 2008 09:53 AM   [ Ignore ]   [ # 9 ]  
Grad Student
Avatar
Rank
Total Posts:  74
Joined  02-26-2008

Would this be better?

Libs::get('mylibrary')->do_something();
Models::get('mymodel')->do_something();
DB::conn('dbgroup')->query($sql); 

xwero, was the obscurity in the method names or in something else?

We could add plugin and helper loading classes:

Helpers::load('myhelper');
Plugins::load('myplugin'); 

That would merely load the plugins and helpers, but there’s no need for a Helpers::get(‘myhelper’)->do_something() type syntax because helpers and plugins aren’t classes.

 Signature 

[ Cron bootstrapper ] [ Modularity ] [ Sitemaps ] [ Query Browser ] [ Paging Simplified ] [ jonathonhill.net ]

Profile
 
 
Posted: 17 December 2008 10:20 AM   [ Ignore ]   [ # 10 ]  
Sr. Research Associate
RankRankRankRankRank
Total Posts:  4785
Joined  07-14-2006

With obscuring i meant that the classes are linked to a superobject while your plugin make them seem like independent objects. But now i remember i Kohana you do

$model = new Model(); 

So there is the link with the superobject also obscured.

But now i’m starting to wonder about another thing

$this->load->library('form_validation');
            
        
$this->form_validation->set_rules('username''Username''required');
        
$this->form_validation->set_rules('password''Password''required');
        
$this->form_validation->set_rules('passconf''Password Confirmation''required');
        
$this->form_validation->set_rules('email''Email''required');
            
        if (
$this->form_validation->run() == FALSE)
        
{
            $this
->load->view('myform');
        
}
        
else
        
{
            $this
->load->view('formsuccess');
        

is transformed into

Libs::e('form_validation')->set_rules('username''Username''required');
        
Libs::e('form_validation')->set_rules('password''Password''required');
        
Libs::e('form_validation')->set_rules('passconf''Password Confirmation''required');
        
Libs::e('form_validation')->set_rules('email''Email''required');
            
        if (
Libs::e('form_validation')->run() == FALSE)
        
{
            View
::show('myform');
        
}
        
else
        
{
            View
::show('formsuccess');
        

Maybe you like the last style better but even with the short method name there is not that much of a change in typing.

Profile
 
 
Posted: 17 December 2008 10:29 AM   [ Ignore ]   [ # 11 ]  
Grad Student
Avatar
Rank
Total Posts:  74
Joined  02-26-2008

@xwero: What does it matter if the superobject ($this) is obscured?

But if it does matter, you could just wrap the superobject in a static class like this:

class CI {
  
public static $_superobject;
  
  public static function 
core() {
    
if(!is_object(self::$_superobject)) {
      self
::$_superobject =& get_instance();
    
}
    
return self::$_superobject;
  
}
}

// use it like this
CI::core()->form_validation->set_rules(...); 
 Signature 

[ Cron bootstrapper ] [ Modularity ] [ Sitemaps ] [ Query Browser ] [ Paging Simplified ] [ jonathonhill.net ]

Profile
 
 
Posted: 17 December 2008 05:01 PM   [ Ignore ]   [ # 12 ]  
Research Assistant
Avatar
RankRankRank
Total Posts:  727
Joined  08-03-2006

Umm, not to be anti classes or static methods, but for shorter syntax this can be used:

function Model($name, ...)
{
    
// return the model
}

// Then it can be used as this:
$users Model('user')->find_all();

Lib('validation')->...
Helper('inflector'); // load inflector 

This is much shorter + it can be implemented in PHP 4, too!

I have even wondered if I should write a modification to CI that does this (and some more things).

 Signature 

RapidDataMapper: My new ORM, is now released!

IgnitedRecord: Old ORM

MPTtree: A model to handle trees in a database.

YAYParser - Yet Another YAML Parser

Profile
 
 
Posted: 17 December 2008 05:06 PM   [ Ignore ]   [ # 13 ]  
Grad Student
Avatar
Rank
Total Posts:  74
Joined  02-26-2008

Duh, why didn’t I think of that! Thanks!

What “other things” did you have in mind for your mod?

 Signature 

[ Cron bootstrapper ] [ Modularity ] [ Sitemaps ] [ Query Browser ] [ Paging Simplified ] [ jonathonhill.net ]

Profile
 
 
Posted: 17 December 2008 05:14 PM   [ Ignore ]   [ # 14 ]  
Research Assistant
Avatar
RankRankRank
Total Posts:  727
Joined  08-03-2006

Among other things, a fully cascading filesystem and more modular database (so the DB() function can be used like Model() and Lib()).’

Maybe we should collaborate and make an alternative loader class with all those modifications?

 Signature 

RapidDataMapper: My new ORM, is now released!

IgnitedRecord: Old ORM

MPTtree: A model to handle trees in a database.

YAYParser - Yet Another YAML Parser

Profile
 
 
Posted: 17 December 2008 05:16 PM   [ Ignore ]   [ # 15 ]  
Grad Student
Avatar
Rank
Total Posts:  74
Joined  02-26-2008

I’d love to! How do you suggest we proceed? PM me if you want to e-mail me direct.

 Signature 

[ Cron bootstrapper ] [ Modularity ] [ Sitemaps ] [ Query Browser ] [ Paging Simplified ] [ jonathonhill.net ]

Profile
 
 
   
1 of 2
1