Processwire / API钩子(函数内的PHP函数)

时间:2017-08-09 21:41:05

标签: php email sendgrid

我正在使用ProcessWire API编写一个钩子...这是一个非常常见的做法,它具有强大的API。

以下作品完全正常......

$this->addHookAfter('Pages::saved', function(HookEvent $event) {

    $arguments = $event->arguments();
    $page = $event->arguments(0);

    if ($page->template == 'user') {

        // Require relevent libraries
        require_once($this->config->paths->root . 'api/sendgrid/sendgrid-php.php');

        // SendGrid API init
        $sgAPIKey = "XXXX";

        // Set email confirmation settings
        $email_admin = 'test@example.com';
        $email_customer = $page->email;
        $email_admin_subject = "You added a new user $page->name";
        $email_customer_subject = 'Your login details';

        $from = new \SendGrid\Email("Example User", $email_admin);
        $subject = "Sending with SendGrid is Fun";
        $to = new \SendGrid\Email("Example User", $email_customer);
        $content = new \SendGrid\Content("text/plain", "and easy to do anywhere, even with PHP");
        $mail = new \SendGrid\Mail($from, $subject, $to, $content);

        $sg = new \SendGrid($sgAPIKey);
        $response = $sg->client->mail()->send()->post($mail);

        // Dump SendGrid object with TracyDebugger
        bd($mail);
    }

});

但是,只要我添加一个发送电子邮件的功能(为了设置两个单独的发送邮件功能(一个用于管理员,一个用于客户),它根本不起作用。没有错误......只是$ mail返回NULL。

$this->addHookAfter('Pages::saved', function(HookEvent $event) {

    $arguments = $event->arguments();
    $page = $event->arguments(0);

    if ($page->template == 'user') {

        // Require relevent libraries
        require_once($this->config->paths->root . 'api/sendgrid/sendgrid-php.php');

        // SendGrid API init
        $sgAPIKey = "XXXX";
        // Set email confirmation settings
        $email_admin = 'test@example.com';
        $email_customer = $page->email;
        $email_admin_subject = "You added a new user $page->name";
        $email_customer_subject = 'Your login details';
        $email_customer_body = 'This is a test';

        function send_email($from_email, $to_email, $subject, $body) {
            global $sgAPIKey;
            $from = new \SendGrid\Email(null, $from_email);
            $to = new \SendGrid\Email(null, $to_email);
            $content = new \SendGrid\Content("text/html", $body);
            $mail = new \SendGrid\Mail($from, $subject, $to, $content);
            $sg = new \SendGrid($sgAPIKey);
            $response = $sg->client->mail()->send()->post($mail);
        }

        send_email($email_admin, $email_customer, $email_customer_subject, $email_customer_body);

        // Dump SendGrid object with TracyDebugger
        global $mail;
        bd($mail);
    }

});

有什么理由说这样的功能不起作用?是因为从技术上讲,函数内部有一个函数吗?我至少会认为它会返回一个错误。

1 个答案:

答案 0 :(得分:0)

PHP中允许函数内部的函数,但是您遇到的问题更多的是作用域的问题。该函数完成后,$mail不再在范围内,这意味着您无法再访问该变量。

一种可能的解决方案是在函数完成时返回该变量,如下所示:

function send_email($from_email, $to_email, $subject, $body) {
        global $sgAPIKey;
        $from = new \SendGrid\Email(null, $from_email);
        $to = new \SendGrid\Email(null, $to_email);
        $content = new \SendGrid\Content("text/html", $body);
        $mail = new \SendGrid\Mail($from, $subject, $to, $content);
        $sg = new \SendGrid($sgAPIKey);
        $response = $sg->client->mail()->send()->post($mail);
        return $mail;
}

这样,当您执行该功能时,您可以将其设置为变量。

另外,我注意到您尝试使用global关键字来访问该$mail变量。这不仅仅是不好的做法,它在这种情况下永远不会起作用。 global关键字用于使global命名空间中的变量可访问。典型用法如下:

$global_variable = "foobar";
class Foo {
  public static function test() {
    return $global_variable;
  }
  public static function test_two() {
    global $global_variable;
    return $global_variable;
  }
}
echo(Foo::test()); //echoes nothing, since in scope, the variable is not set
echo(Foo::test_two()); //echoes 'foobar', since we told PHP to put it in scope

TLDR: global关键字使全局范围内的变量在本地范围内可见。