PHP AmazonSes作为一个抽象类给use带来了致命错误


PHP Amazon Ses as an abstract class gives use fatal error

我正在使用亚马逊简单电子邮件服务,并试图将其实现为一个抽象类,这样我就可以根据需要在整个过程中使用它。

问题

使用时出现了问题,我无法解决如何在不产生错误的情况下要求使用Ses作为抽象类所需的文件和类。

require 'lib/aws/aws-autoloader.php';
use Aws'Common'Enum'Region;
use Aws'Ses'SesClient;
abstract class simpleemail {
    function sendSesEmail($to, $subject, $body, $bodyHtml){
        try {   
            $client = SesClient::factory(array(
                'key' => "",
                'secret' => "",
                'region' => Region::US_EAST_1
            ));
            $send = $client->sendEmail(array(
                'Source' => 'Name <no-reply@contact.com>',
                'Destination' => array('ToAddresses' => array($to)),
                'Message' => array('Subject' => array('Data' => $subject), 'Body' => array('Html' => array('Data' => $bodyHtml)))));
            return true;
        }
        catch(Exception $e){
            echo $e->getMessage();
            return false;
        }
    }
}

错误消息

Fatal error: Class 'Aes'Ses'SesClient' not found in ....

我已经尝试将use更改为require,但随后得到:

require 'lib/aws/Aws/Common/Enum/Region.php';
require 'lib/aws/Aws/Ses/SesClient.php';

Fatal error: 'SesClient' not found in ...

解决方案

我如何使用/需要在抽象类中工作所需的文件?

这不起作用:

abstract class simpleemail
{
    public function sendSesEmail()
    {
        use Aws'Common'Enum'Region;
        use Aws'Ses'SesClient;
        //...
    }
}

use语句基本上是导入,在编译时进行处理,因此不能确定它们的作用域。它们必须移动到外部范围(类之外)
如果要确定它们的范围,则必须、手动require或使用class_alias
查看我对此问题的回答以了解更多详细信息。与以往一样,更多的细节可以在php.net 上找到

旁注:

  • 请遵循如PHP-图所描述的编码标准。他们不是官方的,但是Zend,Symfony。。。事实上,所有主要参与者都订阅了它们
  • 请进入的habbit,始终指定访问修饰符(publicprotectedprivate
  • 当像创建$client = SesClient::factory那样创建实例时,请将它们指定给一个属性,以便只创建一次实例。目前,每个方法调用都会一次又一次地创建相同的实例。太糟糕了
  • 使用属性时:将它们包含在类定义中
  • 您正在实例上调用sendEmail,并将返回值分配给$send。你不检查返回值,也不返回它。要么忽略返回值,要么返回它,这样它就可以被检查了
  • 永远不要使用require,如果必须的话,可以使用require_once。当两次执行同一块代码时,使用require可能会导致错误:重新定义函数/类。如果时间至关重要,您可以选择require(因为require_once会导致更多开销),但您必须知道自己在做什么
  • 不要使用require自动加载器,使用spl_autoloader_register
  • 记住:抽象类不能实例化,只能实例化它们的子类。。。子级还可以重写抽象类中声明的方法。将关键方法声明为final

所以,答案是:

use Aws'Common'Enum'Region;
use Aws'Ses'SesClient;
abstract class simpleemail
{
    protected $client = null;
    final public function sendSesEmail()
    {
        $client = $this->getClient();//lazy-loads the client instance
        return $client->sendEmail(/* ... */);//return the result
    }
    //lazy-loader
    protected function getClient()
    {
        if ($this->client === null)
        {
            $this->client = SesClient::factory(array(
                'key' => "",
                'secret' => "",
                'region' => Region::US_EAST_1
            ));
        }
        return $this->client;
    }
}