2

I'm trying to call my library "Phpmailer" in the controller. I'm aware that there is a framework library to perform this task, however I still prefer PHPMailer. I followed a tutorial on integrating the library to the framework in version 3.0.0, obviously that would give some conflict. How to call my PHPMailer library in Codeigniter 4.0.0?

Tutorial: https://www.codexworld.com/codeigniter-send-email-using-phpmailer-gmail-smtp/

My library:

<?php
namespace App\Libraries;
use CodeIgniter\Libraries; 
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

defined('BASEPATH') or exit('No direct script access allowed');

class Phpmailer {

    public function load(){
        require_once APPPATH.'ThirdParty/PHPMailer/Exception.php';
        require_once APPPATH.'ThirdParty/PHPMailer/PHPMailer.php';
        require_once APPPATH.'ThirdParty/PHPMailer/SMTP.php';
        
        $mail = new PHPMailer;
        return $mail;
    }
}

My controller:

<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use App\Libraries\Phpmailer;

class Retrieve{

    public function send($email){

        $this->load->library('phpmailer'); //line 10
        $mail = $this->phpmailer->load();
        
        // SMTP configuration
        [...]
    }
}

The retrieve function ienter image description heres being called by another method, so it is working. The problem is that my library doesn't load. I get the following error:

ErrorException
Undefined property: App_Controllers_Retrieve: $load
APPPATH/Controllers_Retrieve.php : 10 - CodeIgniter_Debug_Exceptions->errorHandler

[1]: https://i.stack.imgur.com/O49B7.png
[2]: https://i.stack.imgur.com/xUUIQ.png

Tavinho
  • 21
  • 1
  • 3
  • 1
    Having your own class and PHPMailer using a name differing only in case seems unwise. Give PHPMailer an alias to avoid confusion. The error looks like a problem with class naming, location, and loading than anything to do with PHPMailer. Do you not have the option of using composer? It’s so much nicer than this. – Synchro Dec 06 '20 at 09:45

1 Answers1

0

The error itself is simple but I suspect there are bigger issues behind it.

Undefined property: App_Controllers_Retrieve: $load

This isn't a namespacing problem, you're trying to access something that doesn't exist.

$this->load-> ... //line 10 is attempting to access the property load of $this (the Controller), which doesn't exist as far as you've shown us.

There's no real one line fix for this. How you're trying to 'load' the library into the Controller isn't what you want to be doing (check out the Services class in CI4, I think that's what you're imagining).

This is the easiest way, in my opinion:

Give the Library a constructor. Create/store the PHPMailer object inside of it and contain the work of doing emails to the Library itself. For example:

  <?php
  namespace App\Libraries;
  use PHPMailer\PHPMailer\PHPMailer;
  use PHPMailer\PHPMailer\Exception;

  defined('BASEPATH') or exit('No direct script access allowed');

  class Phpmailer {

    private $mailer;

    function __construct(){
      $mailer = new PHPMailer\PHPMailer\PHPMailer();
    }
    //Example - do some work
    public function send(){
      
    
      // SMTP configuration
      ...

      if ($this->mailer->send())
      {
        ...
      }

    }

    ...
  }

Big note here: If you don't change the name of your Library, you will likely have to reference the actual PHPMailer by its full namespace: e.g. new PHPMailer\PHPMailer\PHPMailer();

Then your Controller can just create a new instance of your library whenever it needs that library to do work.

<?php
  namespace App\Controllers;
  use App\Libraries\Phpmailer;

  class Retrieve extends BaseController {

    public function send($email){

      $mailLibrary = new Phpmailer();
      $mailLibrary->send();

    }
}

Rather than useing CodeIgniter\Controller directly, have your Controller class(es) extend BaseController instead. Then if you need to add things to your Controllers' parent class, you're not touching the framework's 'system' files.

If that library is something you want to have all the time, you can instead make it a class property of your Controller and create it upon construction of the Controller itself, so it's always there.

This assumes that you've got the actual PHPMailer where it needs to be and the CI framework is autoloading. If you haven't installed CI/PHPMailer via Composer, I would seriously suggest that you move your project to an install that was. Doing so will save your project a lifelong technical debt and make namespacing things much easier.

parttimeturtle
  • 1,125
  • 7
  • 22