Part of the EllisLab Network
   
 
CI 1.5 - init files
Posted: 15 November 2006 11:30 PM   [ Ignore ]  
Lab Assistant
Avatar
RankRank
Total Posts:  130
Joined  04-14-2006

I’ve been trying to work around this, but can’t come up with anything clean… really, the init files need to go back in.

For the ADODB class, it has a function (ADONewConnection()) that parses the dsn, and generates the adodb object based on that .. eg, a dsn of “mysql://....” will load the class Adodb_mysql.

In CI, without calling that method, there is really no clean way to load the class. I was originally thinking that a class called Ado (so I can get $this->ado) could extend the main Adodb class, but since the class depends on the DSN, it’s not really possible.

I noticed a new _ci_varmap variable inside the Loader class (among some other cleanups, nice job Rick), so I was initially thinking that it would be good to add a method to allow the config files to call (though .. i’m iffy on config files calling functions..) that could add something to that varmap array, so classes could be created with a variable name of something else.. but really, it’s not as clean as the old init method.

I’m going to suggest that init go back in (though, with a slightly different implementation.. i will post a patch shortly) so that if there is an init file for a class, it gets called.. and otherwise, CI automatically generates as 1.5 does now.

init just made it really simple to integrate 3rd party libraries - in most cases, it was just a matter of creating an init file, and the library could be used. Now, it requires the library be coded in a certain way, and if it’s not, that it be extended and have a constructor to generate it properly - if that’s even possible (..it’s not for ADOdb).

 Signature 

CIForge.com - CodeIgniter Community Source Hosting

Profile
 
 
Posted: 16 November 2006 04:21 AM   [ Ignore ]   [ # 1 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  254
Joined  10-04-2006

I have to say that init files were very clever to me too.
I do not know why it was deleted (surely a good reason) but it allowed many things.

Perhaps is it possible to create init file only when needed, ect.

 Signature 

Sylvain Gourvil
PHP Developer
French scuba divingMotivation and team building

Profile
 
 
Posted: 16 November 2006 05:45 AM   [ Ignore ]   [ # 2 ]  
Research Assistant
RankRankRank
Total Posts:  970
Joined  04-13-2006

Hi Greg.
In a very general sense - setting aside the specifics of ADODB for a moment - isn’t a generic Factory class the “correct” way to instantiate a third-party class library? I’ve used Vincent Oostindie’s Eclipse library here and there within CI using an object Factory. I’m no expert, but this way makes more sense to me than having to write init files.

Profile
 
 
Posted: 16 November 2006 03:50 PM   [ Ignore ]   [ # 3 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  130
Joined  04-14-2006

Martin - Yeah, it probably is.. but where do you call it? You could just do it in controller code, if you want to get an object to use there. But if you want to attach that object to the CI instance to pass around between controllers/views/models, it becomes a bit more difficult. It’s nice to utilize the standard CI way of loading libraries ($this->load->library(‘whatever’);) for ALL libraries..

That said, here’s my patch:

Index: Loader.php
===================================================================
---
Loader.php  (revision 167)
+++
Loader.php  (working copy)
@@ -
680,29 +680,51 @@

                        return
$this->_ci_init_class($class, config_item('subclass_prefix'), $params);
                
}
-
+
+               
// First search for an init file - if found, we let the init file create the object
+               // For backwards compatibility with CI <= 1.4.1, we look for lowercase filenames as well
+               $init_search_path = array(
+                       
APPPATH.'init/init_'.$class.EXT,
+                       
APPPATH.'init/init_'.strtolower($class).EXT,
+                       
BASEPATH.'init/init_'.$class.EXT,
+                       
BASEPATH.'init/init_'.strtolower($class).EXT,
+               );
+               foreach (
$init_search_path as $path)
+               
{
+                       if (file_exists($path))
+                       
{
+                               // found an init file, include it and we're done.
+                               include($path);
+
+                               
//TODO : possible check for $CI->$class, and only return if it's set?
+
+                               return;
+                       
}
+               }
+
                
// Lets search for the requested library file and load it.
-               $is_duplicate = FALSE;
-               for (
$i = 1; $i < 3; $i++)
+               
$is_duplicate = FALSE;
+               
$lib_search_path = array(
+                       
APPPATH.'libraries/'.$class.EXT,
+                       
BASEPATH.'libraries/'.$class.EXT,
+               );
+               foreach (
$lib_search_path as $path)
                
{
-                       $path = ($i % 2) ? APPPATH : BASEPATH;
-                       
$fp = $path.'libraries/'.$class.EXT;
-
                        
// Does the file exist?  No?  Bummer...
-                       if ( ! file_exists($fp))
+                       if ( !
file_exists($path))
                        
{
                                
continue;
                        
}

                        
// Safety:  Was the class already loaded by a previous call?
-                       if (in_array($fp, $this->_ci_classes))
+                       if (
in_array($path, $this->_ci_classes))
                        
{
                                $is_duplicate
= TRUE;
                                continue;
                        
}

-                       include($fp);
-                       
$this->_ci_classes[] = $fp;
+                       include(
$path);
+                       
$this->_ci_classes[] = $path;
                        return
$this->_ci_init_class($class, '', $params);
                
}

@@ -759,7 +781,7 @@
                else
                
{
                        $CI
->$classvar = new $name;
-               
}
+               }
        }

        
// --------------------------------------------------------------------

The observant reader will notice that I changed the existing code to load libraries as well .. it still does the same thing, just with a slightly different method (in the future, or even now, we could add strtolower() versions to the search path, to allow loading libraries with all-lowercase filenames, which is much more common on linux systems).

What this does, is first look in application/init/ and then system/init/ for an init_<name>.php file. If it exists, it includes it, and doesn’t try to make an instance of the class. If it can’t find an init file, then it automatically creates the object (as was new in 1.5).

 Signature 

CIForge.com - CodeIgniter Community Source Hosting

Profile
 
 
Posted: 16 November 2006 05:51 PM   [ Ignore ]   [ # 4 ]  
Research Assistant
RankRankRank
Total Posts:  970
Joined  04-13-2006
Greg MacLellan - 16 November 2006 03:50 PM

It’s nice to utilize the standard CI way of loading libraries ($this->load->library(‘whatever’);) for ALL libraries..

Agreed. I do see the problem. I expect there are several different approaches to third-party library inclusions floating around here, with none of them being a one-size-fits-all solution.
I don’t have anything better to suggest, as my “third-party” needs aren’t yet great enough to warrant spending much time on it.

Profile
 
 
Posted: 17 November 2006 03:21 PM   [ Ignore ]   [ # 5 ]  
Grad Student
Avatar
Rank
Total Posts:  80
Joined  10-09-2006

Grey,

I can’t seem to patch using patch p1 < patch

It give me an error (well 2) and doesn’t apply the patch.

 Signature 

http://www.totali.co.nz - Real IT
http://www.oscar.school.nz - Internet Filtering

Profile
 
 
Posted: 17 November 2006 05:10 PM   [ Ignore ]   [ # 6 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  130
Joined  04-14-2006

Sorry, I did the diff in the libraries/ directory, you’ll probably have to apply from there

 Signature 

CIForge.com - CodeIgniter Community Source Hosting

Profile
 
 
Posted: 03 December 2006 01:00 AM   [ Ignore ]   [ # 7 ]  
Summer Student
Total Posts:  8
Joined  11-14-2006

I agree with Martin. I also think a factory method should be the way to go. For my own purpose, I modified the Loader as follows around line 750:

// Instantiate the class        
        
$CI =& get_instance();
        if (
$config !== NULL)
        
{
            
//If block added by JFB (2006-11-16)
            
if (is_callable($name.'::factory')) {
                $CI
->$classvar =& call_user_func(array($name, 'factory'), $config);
            
} else {
                $CI
->$classvar = new $name($config);
            
}
        }
        
else
        
{        
            
//If block added by JFB (2006-11-16)
            
if (is_callable($name.'::factory')) {
                $CI
->$classvar =& call_user_func(array($name, 'factory'));
            
} else {
                $CI
->$classvar = new $name;
            
}
        }

However, this is not the entirely clean. The factory is inside the class itself that is getting generated by the factory. I think a cleaner way would be to agree on a convention like:

If the library file contains a variable called $factory_class and a class $factory_method, then we use the specified factory to instantiate the class, otherwise, we use ‘new’

or something along those lines. The factory could be generated by a second class this way.

Cheers!

JF

Profile
 
 
Posted: 28 December 2006 09:10 PM   [ Ignore ]   [ # 8 ]  
Research Assistant
RankRankRank
Total Posts:  915
Joined  07-10-2006

plugins/
...core (core replacement libraries)
...extensions/ (the MY_ libraries)
...factories/ (the current approach)
...libraries/ (third-party solutions using init approach)
.......adodb/
.......DOMit/
.......Rapyd/
.......etc./

Our existing plugins seem like another flavor of helper to me. Maybe the solution is a more entensible plugin architecture that can be extended using interface classes that define new flavors of plugins. The plugin architecture should have the smarts to determine what interfaces are available (via config, directory recursion, or by other means). Then the framework become infinitely extensible.

Profile
 
 
   
 
 
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 719, on June 06, 2008 10:16 AM
Total Registered Members: 66430 Total Logged-in Users: 37
Total Topics: 84793 Total Anonymous Users: 4
Total Replies: 455060 Total Guests: 245
Total Posts: 539853    
Members ( View Memberlist )
Newest Members:  Dylan1978X_franbaguasllogocsaturkeyPeter BryanttherendStudioGeorgiaJZeerfedeghe