Using Zend Framework from Yii

Yii provides many excellent solutions with which you can build an application. Still, you probably will need more. One of the best places to look is Zend Framework classes. These are of high quality and solve many tasks, such as using Google APIs or working with e-mails.

In this recipe, we will see how to use the Zend_Mail package to send e-mails from the Yii application. We will use both a simple approach of using the whole framework and will also implement a custom autoloader that will allow us to use only Zend_Mail and its dependencies.

Getting ready

Before we begin this recipe, we need to have a few things in place.

  1. Create a fresh application by using yiic webapp.
  2. Download the Zend Framework 1 code (the minimal version is enough) from the following URL:

    http://framework.zend.com/downloads/latest

    In this recipe, we have used Version 1.11.6.

  3. Extract library/Zend from the downloaded archive to protected/vendors/Zend.

How to do it...

Carry out the following steps:

  1. We will create a simple controller that will send an e-mail. Create protected/controllers/MailtestController.php as follows:
    <?php
    class MailtestController extends CController
    {
      public function actionIndex()
      {
        $mail = new Zend_Mail('utf-8'),
        $mail->setHeaderEncoding(Zend_Mime::ENCODING_QUOTEDPRINTABLE);
        $mail->addTo("[email protected]", "Alexander Makarov");
        $mail->setFrom("[email protected]", "Robot");
        $mail->setSubject("Test email");
        $mail->setBodyText("Hello, world!");
        $mail->setBodyHtml("Hello, <strong>world</strong>!");
        $mail->send();
    
        echo "OK";
      }
    }
  2. Now try to run mailtest/index and verify that it doesn't work:
    How to do it...
  3. This means that the Yii autoloader failed to include the Zend_Mail class. This is expected because it knows nothing about the Zend Framework's naming convention. So logically, we have the following two solutions to this:
    • Include classes explicitly
    • Create our own autoloader
  4. We will now start with including classes. All Zend Framework classes do have the require_once statements for all dependencies. These statements rely on adding an additional PHP include path and look like the following:
    require_once 'Zend/Mail/Transport/Abstract.php';
  5. When using Yii::import to import a directory, it works the same way as adding a directory into the PHP include path, so we can solve our problem as follows:
    class MailtestController extends CController
    {
      public function actionIndex()
      {
        Yii::import('application.vendors.*'),
        require "Zend/Mail.php";
    
        $mail = new Zend_Mail('utf-8'),
        $mail->setHeaderEncoding(Zend_Mime::ENCODING_QUOTEDPRINTABLE);
        // change to your email
        $mail->addTo("[email protected]", "Alexander Makarov");
        $mail->setFrom("[email protected]", "Robot");
        $mail->setSubject("Test email");
        $mail->setBodyText("Hello, world!");
        $mail->setBodyHtml("Hello, <strong>world</strong>!");
        $mail->send();
    
        echo "OK";
      }
    }
  6. Now it will send an e-mail properly without any error. This method will work if you don't have too many Zend Framework classes used. If you are using it heavily, then you will have to include a lot that will add unnecessary complexity. Now, let's use Zend_Loader_Autoloader to achieve this.
  7. The best place to add another autoloader is in the index.php bootstrap. This way, you will be able to autoload classes during the whole execution flow:
    // change the following paths if necessary
    $yii=dirname(__FILE__).'/../framework/yii.php';
    $config=dirname(__FILE__).'/protected/config/main.php';
    
    // remove the following lines when in production mode
    defined('YII_DEBUG') or define('YII_DEBUG',true);
    // specify how many levels of call stack should be shown // in each log message
    defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
    
    require_once($yii);
    $app = Yii::createWebApplication($config);
    
    // adding Zend Framework autoloader
    Yii::import('application.vendors.*'),
    require "Zend/Loader/Autoloader.php";
    Yii::registerAutoloader(array('Zend_Loader_Autoloader','autoload'), true);
    
    $app->run();
  8. Now we can remove the following lines from MailtestController:
    Yii::import('application.vendors.*'),
    require "Zend/Mail.php";

    And it will still work fine without any errors, meaning that Zend Framework autoloading now works.

How it works...

Let's review what is going on behind the scenes and how it works, starting with the first way. We have used Yii::import, which, when used like Yii::import('path.alias.*'), behaves like adding another PHP include path. As there was no autoloader in Zend Framework originally, it has all the necessary require_once calls. So, if you use a single component, such as Zend_Mail, you don't need more than one require_once.

The second method doesn't force you to use a single require statement. As Yii allows using multiple autoloaders and in the latest versions Zend Framework has its own autoloader, we can use it in our application. The best time to do this is right after the application bootstrap was loaded, but the application was not run. To achieve this, we break Yii::createWebApplication($config)->run() into two separate statements in index.php and insert an autoloader initialization between these:

Yii::import('application.vendors.*'),
require "Zend/Loader/Autoloader.php";
Yii::registerAutoloader(array('Zend_Loader_Autoloader', 'autoload'), true);

We still need Yii::import('application.vendors.*') because Zend Framework classes will continue to use require_once. Then, we require an autoloader class and add it to the end of the PHP autoloading stack by using Yii::registerAutoloader with the second argument set to true.

See also

  • The Customizing the Yii autoloader recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.73.125