Welcome Guest, Not a member yet? Register   Sign In
Adding simple class
#1

[eluser]ariok[/eluser]
I all

I need some help trying add a simple class into my application.
I would like to know if is it possibile to INCLUDE a class without use load->library.

Example 1: If i need to create more than one instance of an object what i have to do ?
with load->library i could create a single instance of my class at once.

Example 2: If i need to include a class into a library what i have to do?
I would like to create object in standard way.. ( $obj = new myClass() ) .

thank you Big Grin
#2

[eluser]BizComputing[/eluser]
It's funny that you should ask this question as I just completed porting a class into CI and was wrestling with the same question.

I am new to CI so bear with me if I'm totally off the reservation, but here goes.

I found 2 ideas that I am pursuing right now:

1) create an __autoload magic function in index.php. Plus of this is that I don't need to worry about require/include, just use and go. Negative of this is that it is PHP5 only.

2) Use load_class. This function is part of Common.php. This file is the first thing included by CI so should be available anywhere you want it. It takes 2 arguments, $class & $instantiate. From what I can tell, I should be able to call this with my class name and FALSE for instantiation. This will then follow the standard pathing etc. that any library class follows, so, if I drop my class into my application/library folder, I should be golden. My concerns about this approach is that Common is not documented so my concern is if my own use of load_class may break in some future release of CI.

I'm leaning toward #2, will report back what kind of results I get.
#3

[eluser]BizComputing[/eluser]
Possibly good news. I tested the load_class idea, and it worked fantastic.

Word of warning: make sure you pass the FALSE for no instantiation, otherwise CI will attempt to instantiate and will choke if your class name doesn't start with the CI_ prefix.

My concern still remains that I'm using an internal undoc'd CI function and possibly will break my app on future versions of CI. Maybe one of the CI team can comment on the use of internal functions like load_class.
#4

[eluser]Nick Husher[/eluser]
You could place the classes within a helper and do $this->load->helper('class_structure').

It might not be the best practice, but I have a file that handles user creation, editing, and deletion that looks a bit like this:
Code:
class User_model extends Model {
  function new_user() { return new User(); }
  // etc...
}

class User {
  // user functions & data
}
class User_collection {
  // user collection functions & data
}
The class User (and User_collection) is now available to any controller that I load my user_model file on.
#5

[eluser]xwero[/eluser]
Include the class in your controller and do it like you are used to. It may not look nice but it works.
#6

[eluser]BizComputing[/eluser]
Including the class in my controller would not work since the class is designed for an internally written framework. The only changes I made were to allow the class to "see" CI and use the CI resources rather than the resources from the internal framework. I really didn't want to change the constructor to auto detect if the 1st argument is an array etc. since this class has no use bound to a controller. The load_class('custom_class',FALSE) I detailed above works well and I think honors the spirit of CI.
#7

[eluser]BizComputing[/eluser]
xwero, I just realized I read into your answer, when you said include, I assumed you were refering to using load->library(). If that were the case, then my previous post applies. As well as the arguments I stated there there is also the issue of having the waste of an unused instance.

I see now that you were most likely talking about using the php include or require directive right within the controller.

Yes, that would work, but, aside from "not looking nice", it goes against the spirit of CI where CI is able to track and manipulate all the code resources you utilize.

Nick Husher's suggestion of packaging the class as a helper would also work since helpers are simply loaded rather than instantiated. My dislike for this idea though is the confusion it brings. CI makes the distinction that a helper is procedural so coding a class def within a helper may work, it is not intuitive. His other suggestion of "tail gating" a model or controller once again would work, but again leads to confusion.

I develop large custom applications where we are making the transition to building on CI. I realize that there will be places I will have to do things in a less than desirable way, but the more I can keep to the CI spirit, then, the cleaner and easier to follow my code becomes and with all the expansion and maint I have to constantly do, clean code will be a Godsend.
#8

[eluser]nocash[/eluser]
Quote:EDIT: It's been suggested that the code in this post is abusive and a very naughty, naughty boy. Make sure to read the rest of the thread for a better method.

You can try this if you like, it's something I made after reading the forums/guide/wiki looking for an answer this question. Details on usage are after the code.

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

class MY_Loader extends CI_Loader {

    function MY_Loader()
    {
        parent::CI_Loader();
    }
    
    function instance($class = '', $params = NULL)
    {
        if ($class == '')
        {
            return FALSE;
        }
        
        return $this->_my_load_class($class, $params);
    }
    
    function _my_load_class($class, $params = NULL)
    {    
        // Get the class name
        $class = str_replace(EXT, '', $class);

        // We'll test for both lowercase and capitalized versions of the file name
        foreach (array(ucfirst($class), strtolower($class)) as $class)
        {
            $subclass = APPPATH.'libraries/'.config_item('subclass_prefix').$class.EXT;

            // Lets search for the requested library file and load it.
            $is_duplicate = FALSE;        
            for ($i = 1; $i < 3; $i++)
            {
                $path = ($i % 2) ? APPPATH : BASEPATH;    
                $filepath = $path.'libraries/'.$class.EXT;
                
                // Does the file exist?  No?  Bummer...
                if ( ! file_exists($filepath))
                {
                    continue;
                }
                
                // Safety:  Was the class already loaded by a previous call?
                if (in_array($filepath, $this->_ci_classes))
                {
                    $is_duplicate = TRUE;
                    log_message('debug', $class." class already loaded.");
                    return $this->_my_init_class($class, '', $params);
                }
                
                include($filepath);
                $this->_ci_classes[] = $filepath;
                return $this->_my_init_class($class, '', $params);
            }
        } // END FOREACH
        
        // If we got this far we were unable to find the requested class.
        // We do not issue errors if the load call failed due to a duplicate request
        if ($is_duplicate == FALSE)
        {
            log_message('error', "Unable to load the requested class: ".$class);
            show_error("Unable to load the requested class: ".$class);
        }
    }
    
    function _my_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);
            }
        }
        
        if ($prefix == '')
        {
            $name = (class_exists('CI_'.$class)) ? 'CI_'.$class : $class;
        }
        else
        {
            $name = $prefix.$class;
        }
        
        // Set the variable name we will assign the class to    
        $classvar = ( ! isset($this->_ci_varmap[$class])) ? $class : $this->_ci_varmap[$class];
                
        // Instantiate the class        
        $CI =& get_instance();
        if ($config !== NULL)
        {
            $CI->$classvar = new $name($config);
        }
        else
        {        
            $CI->$classvar = new $name;
        }
        
        return $CI->$classvar;
    }    

}

?&gt;

It's basically the library function and a couple others copied out of the Loader.php in the common directory of CodeIgniter, then modified to return the instantiated class. To use it, create a file in your application's library directory called MY_Loader.php and copy the code into it, then create your custom class using the normal CI naming conventions (ie. 'Ninethousand.php' for a class named 'Ninethousand').

Then you can do some awesomeness like

Code:
$awesome = $this->load->instance('ninethousand');

or if you're feeling mega-awesome you can be like

Code:
$things[] = 'Something';
$things[] = 'Something else';

$awesome = $this->load->instance('ninethousand', $things);

$stuff[] = 'Data';
$stuff[] = 'Junk';

$another = $this->load->instance('ninethousand', $stuff);

I only just finished writing it so it's probably not perfect, but it seems to be working well for me.[/b]
#9

[eluser]nocash[/eluser]
So, despite all that lovely code I posted above, I think I found an easier way to do this. Take your pick.

Basically, just throw your class into a library file and load it like you would normally, ie:

Code:
&lt;?php $this->load->library('someclass'); ?&gt;

Then you can simply...

Code:
&lt;?php $foo = new Someclass(); ?&gt;

I only just started doing it that way, but haven't had any problems so far. It's pretty similar to the piggyback method, but a bit cleaner.
#10

[eluser]Rick Jolly[/eluser]
Man, that is an abuse of the class loader. Just take xwero's advice and use include()/require(). That's what the loader does - and then it creates an instance which you don't use.

If you follow a file/class naming convention (see Pear and the Zend Framework), then writing an autoload function is where it's at.




Theme © iAndrew 2016 - Forum software by © MyBB