Page 1 of 1

Swift and my own extension loading

Posted: Thu Jul 13, 2006 9:00 am
by shiznatix
Alright here is what I am trying to do. I am making my own small framework and I want to be able to load extensions into a class which essentially is like loading feyd's SHA256 and d11wtq's Swift and whatever other 3rd party libraries I might want to use. Now this was easy with feyd's stuff (although I had to make it php5 compatable) but d11wtq's style of stuff is difficult. Here is what I want to be able to do:

Code: Select all

<?php

class MailerController extends Base
{
    public function __construct()
    {
    }

    public function Mailer()
    {
        $mailer = $this->LoadExtension('Swift', array('Swift', 'Swift/Swift_SMTP_Connection'), array('Swift', 'Swift_SMTP_Connection'), array('', 'smtp.YOUR-ISP.com'));
    }
}

?>
and then I want to be able to use $mailer just like the documentation says to. Seams easy enough if I just put the file in the first array to require, then the class to initiate in the second array for each file, then the params that I would put in when initiating the class in the 3rd array. The first parameter there 'Swift' is just the folder its located in.

Now here is where the problems come in! Swift has to first require swift.php, then the smtp_connection.php BUT it then has to initiate the smtp_connection class before the swift class while passing the instance of the smtp_class to the swift initiation...

maybe that did not make sence but look at it from here: http://www.swiftmailer.org/documentation/5#view

now here is what I tried with my LoadExtension method:

Code: Select all

public function LoadExtension($extension, $files, $classes, $params)
    {
        if (is_array($files))
        {
            foreach ($files as $key => $val)
            {
                require_once './Extensions/'.$extension.'/'.$val.'.php';

                if ('' !== $classes[$key])
                {
                    if ('' !== $params[$key])
                    {
                        //really don't know if this will even work the way I want it to
                        $tmp[] = new $classes[$key]($params[$key]);
                    }
                    else
                    {
                        $tmp[] = new $classes[$key];
                    }
                }
            }
        }
        else
        {
            require_once './Extensions/'.$extension.'/'.$files.'.php';
        }


    }
but obviously that does not work because of the order of things changes and the params are instances of the other classes.

Now this is not picking on d11wtq because if I was just going to use it once in one place then I would just do it all manually, no problems but this is more of a situation that might come up often and I don't want to have to copy / paste a whole bunch of code every time, I just want to be able to use my handy LoadExtension() method and if something needs changed then it's easier.

What my question is: is there a clean, simple way to do such a thing as what I want to do? Does anyone have any ideas on how to make something like my LoadExtension() method work with different libraries and whatnot so no matter what kind of structure (within reason) it requires to load it, I still can with the same method? OR should I just give up and just copy/paste the code every time?

Posted: Thu Jul 13, 2006 9:13 am
by Chris Corbyn
Perhaps you could build a simple wrapper class for each library you want to load since I iamgine you'll come acorss this same issue in a number of libraries (JP Graph being one).

You're adding another amount of coding to do initally but you'll only have to do it once for each library.

So it would be something like:

Code: Select all

$base->loadExtension(new Swift_Loader);
Swift_Loader could then do any pre-setup stuff it needs. You'd do the same sort of thing for each library:

Code: Select all

$base->loadExtension(new SHA256_Loader);

Posted: Thu Jul 13, 2006 10:34 am
by Jenk
Without wanting to drag the thread off topic - could you not modify the classes to instantiate an object of their subclass' if one is not provided to the constructor? Thus you can still pass an existing one, but if you don't it will create a new one.. or is this a no no?

Code: Select all

<?php

class Foo
{
    private $sub;

    public function __construct ($obj = null) 
    {
        if (is_null($obj)) {
            $this->sub = new Bar;
        } else {
            $this->sub = $obj;
        }
    }
}

?>
Though this could conflict with the interfaces..

Posted: Thu Jul 13, 2006 1:12 pm
by shiznatix
d11wtq, i like the idea. i will look into that tomorrow.

jenk, sorry but yes, thats a no no. nice idea though :D

Posted: Thu Jul 13, 2006 1:48 pm
by Christopher
Simple PEAR naming convention would ease your problem. The fact that the class 'Swift_SMTP_Connection' is in 'Swift/Swift_SMTP_Connection.php' instead of 'Swift/SMTP/Connection.php' makes things harder with Service Locators and autoloaders. Better would be to rename the class just put it in 'Swift/Connection/SMTP.php' or just 'Swift/Smtp.php'

Posted: Thu Jul 13, 2006 1:50 pm
by shiznatix
arborint wrote:Simple PEAR naming convention would ease your problem. The fact that the class 'Swift_SMTP_Connection' is in 'Swift/Swift_SMTP_Connection.php' instead of 'Swift/SMTP/Connection.php' makes things harder with Service Locators and autoloaders. Better would be to rename the class just put it in 'Swift/Connection/SMTP.php' or just 'Swift/Smtp.php'
take notes d11wtq :P

*ducks*

Posted: Thu Jul 13, 2006 4:48 pm
by Chris Corbyn
arborint wrote:Simple PEAR naming convention would ease your problem. The fact that the class 'Swift_SMTP_Connection' is in 'Swift/Swift_SMTP_Connection.php' instead of 'Swift/SMTP/Connection.php' makes things harder with Service Locators and autoloaders. Better would be to rename the class just put it in 'Swift/Connection/SMTP.php' or just 'Swift/Smtp.php'
I shall bear that in mind ~arborint :)

Posted: Fri Jul 14, 2006 1:47 am
by shiznatix
next question on this matter is how to get an array to be seperate inputs into a function. i think i might have to use some variable variables but I don't know how to use those really and maybe there is a easier way. Here is what I mean:

Code: Select all

public function Swift($ConnectionType = 'smtp', $params)
{
    switch (strtolower($ConnectionType))
    {
        case 'smtp':

            require('./Extensions/Swift/Swift.php');
            require('./Extensions/Swift/Swift/Swift_SMTP_Connection.php');

            if (is_array($params))
            {
                $mailer = new Swift(new Swift_SMTP_Connection(
                    for ($i = 0; $i < count($params); $i++)
                    {
                        $params[$i].',';
                    }
                ));
            }
            else
            {
                $mailer = new Swift(new Swift_SMTP_Connection($params));
            }

            return $mailer;

            break;
    }
}
notice that for loop in there... ya obviously that does not work but thats the idea that I need to use. Anyone have any ideas on how to do that?

Posted: Fri Jul 14, 2006 3:57 am
by shiznatix
never mind that is getting too complicated for how simple i want it. don't worry about this.

Posted: Fri Jul 14, 2006 4:08 am
by Chris Corbyn
call_user_func() I think. But yeah I think you've gone over-complex.