Jump to content

Inclusion (require/include) of libraries/files in a hook


a-ok
 Share

Recommended Posts

If I am wanting to require some PHP (PHP libraries or a PHP file) in a hook within my init.php file, is this possible? Below is a snippet...

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

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

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

		// Require relevent libraries
		require_once('../api/sendgrid/sendgrid-php.php');

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

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

		ob_start();
			require_once '../api/confirmation__email--admin.php';
			$email_admin_body = ob_get_contents();
		ob_end_clean();

		ob_start();
			require_once '../api/confirmation__email--customer.php';
			$email_customer_body = ob_get_contents();
		ob_end_clean();

 

Link to comment
Share on other sites

Yes you can.

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

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

    if($page->template == 'user') {
        // Require relevent libraries
        $wft = new WireFileTools();
        $wft->include('sendgrid-php/sendgrid-php.php');
        $from = new \SendGrid\Email("Example User", "test@example.com");
        $subject = "Sending with SendGrid is Fun";
        $to = new \SendGrid\Email("Example User", "test@example.com");
        $content = new \SendGrid\Content("text/plain", "and easy to do anywhere, even with PHP");
        $mail = new \SendGrid\Mail($from, $subject, $to, $content);

        $apiKey = getenv('SENDGRID_API_KEY');
        $sg = new \SendGrid($apiKey);
        $response = $sg->client->mail()->send()->post($mail);
        
	// dump SendGrid object with TracyDebugger
	bd($mail);
    }
});

 

  • Like 1
Link to comment
Share on other sites

1 hour ago, flydev said:

Yes you can.


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

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

    if($page->template == 'user') {
        // Require relevent libraries
        $wft = new WireFileTools();
        $wft->include('sendgrid-php/sendgrid-php.php');
        $from = new \SendGrid\Email("Example User", "test@example.com");
        $subject = "Sending with SendGrid is Fun";
        $to = new \SendGrid\Email("Example User", "test@example.com");
        $content = new \SendGrid\Content("text/plain", "and easy to do anywhere, even with PHP");
        $mail = new \SendGrid\Mail($from, $subject, $to, $content);

        $apiKey = getenv('SENDGRID_API_KEY');
        $sg = new \SendGrid($apiKey);
        $response = $sg->client->mail()->send()->post($mail);
        
	// dump SendGrid object with TracyDebugger
	bd($mail);
    }
});

 

Thanks for the help! Where does $wft->include() run from? My /api/ folder is in the root beside /site/ and /wire/ can I specify $config->urls->root?

Link to comment
Share on other sites

@flydev: hey there! Just checking, but is there a particular benefit to using WireFileTools instead of PHP's own include() or require()?

Haven't used it much myself, so mostly curious. From the first look it seems to me that regular include() or require() would be more efficient and possibly also easier to grasp, but it's entirely possible that I'm missing something important here :)

Link to comment
Share on other sites

Just now, teppo said:

@flydev: hey there! Just checking, but is there a particular benefit to using WireFileTools instead of PHP's own include() or require()?

Haven't used it much myself, so mostly curious. From the first look it seems to me that regular include() or require() would be more efficient and possibly also easier to grasp, but it's entirely possible that I'm missing something important here :)

For one... my question. It doesn't seem to like using include or require in the hook...

Link to comment
Share on other sites

9 minutes ago, oma said:

For one... my question. It doesn't seem to like using include or require in the hook...

Actually require_once() works just fine for your example. I'm not sure what kind of a problem you're having, but I'm pretty sure that it's not related to require_once() not working in a hook, at least.

One issue I can spot right away is your comparison, where "if ($page->template == user) {" should probably be "if ($page->template == 'user') {". It also seems that you've omitted some closing curly braces, but if that wasn't even supposed to be a fully working code sample, so perhaps this was intentional :)

  • Like 1
Link to comment
Share on other sites

1 minute ago, teppo said:

Actually require_once() works just fine for your example. I'm not sure what kind of a problem you're having, but I'm pretty sure that it's not related to require_once() not working in a hook, at least.

One issue I can spot right away is your comparison, where "if ($page->template == user) {" should probably be "if ($page->template == 'user') {". It also seems that you've omitted some closing curly braces, but not sure if this is supposed to be a full code sample or if that was intentional.

Thanks! Yep was just intentional to show you a bit of the code... sorry! I think you're right about require_once() but unsure what the path should be when running from init.php if the /api/ folder is on the same level as /site/ and /wire/

2 minutes ago, adrian said:

A standard php include works fine for me in a hook. Any chance it's a path problem?

Thanks again @adrian – see above. Must be a path thing...

Link to comment
Share on other sites

Just now, adrian said:

The easiest thing with paths is to make use of $config->paths->root.


include($config->paths->root.'sendgrid-php/sendgrid-php.php');

 

I did try this but it didn't work which made me think that perhaps includes/requires couldn't be set in the hook...

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

 

1×	
PHP Notice: Undefined variable: config in /Users/***/Sites/Sites/spink/site/init.php:26
2×	
PHP Notice: Trying to get property of non-object in /Users/***/Sites/Sites/spink/site/init.php:26
1×	
PHP Warning: require_once(/api/sendgrid/sendgrid-php.php): failed to open stream: No such file or directory in /Users/***/Sites/Sites/spink/site/init.php:26

 

Link to comment
Share on other sites

Just now, oma said:

PHP Notice: Undefined variable: config

Not sure what version of PW you are running, but that should work in 3.x.

However, try this which should work in all versions.

wire('config')->paths->root

 

Link to comment
Share on other sites

3 minutes ago, oma said:

I did try this but it didn't work which made me think that perhaps includes/requires couldn't be set in the hook...


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

 


1×	
PHP Notice: Undefined variable: config in /Users/***/Sites/Sites/spink/site/init.php:26
2×	
PHP Notice: Trying to get property of non-object in /Users/***/Sites/Sites/spink/site/init.php:26
1×	
PHP Warning: require_once(/api/sendgrid/sendgrid-php.php): failed to open stream: No such file or directory in /Users/***/Sites/Sites/spink/site/init.php:26

 

Try $this->config->paths->root instead :)

... or the wire() function, as @adrian suggested above.

Link to comment
Share on other sites

3 minutes ago, teppo said:

Try $this->config->paths->root instead :)

Thanks guys... not sure how I didn't figure that. Why wouldn't $config work in this instance?

4 minutes ago, adrian said:

Not sure what version of PW you are running, but that should work in 3.x.

However, try this which should work in all versions.


wire('config')->paths->root

 

I'm on 3.0.61

Link to comment
Share on other sites

Also does PW use a send_mail function?

Call to undefined function ProcessWire\send_email() 

As I'm using my own?

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);
		}

 

Link to comment
Share on other sites

2 minutes ago, oma said:

Also does PW use a send_mail function?

No - you are experiencing a namespace issue - looks like the function is being defined in the global namespace, but you are calling it from within the ProcessWire namespace. 

  • Like 1
Link to comment
Share on other sites

Just now, adrian said:

No - you are experiencing a namespace issue - looks like the function is being defined in the global namespace, but you are calling it from within the ProcessWire namespace. 

Ah so it would explain this too?

Screen Shot 2017-08-09 at 20.55.40.png

Link to comment
Share on other sites

@oma Call SendGrid like that : new \SendGrid(); 

(As Adrian said, its a namespace issue)

 

 

@teppo I used WireFileTools just for the example, the bénéfit of this class is that it provide the ProcessWire API to the object. 

Sorry for the short answer, i am on mobile.

  • Like 2
Link to comment
Share on other sites

29 minutes ago, flydev said:

@oma Call SendGrid like that : new \SendGrid(); 

(As Adrian said, its a namespace issue)

 

 

@teppo I used WireFileTools just for the example, the bénéfit of this class is that it provide the ProcessWire API to the object. 

Sorry for the short answer, i am on mobile.

Thanks for that, @flydev. It appears to work when I don't use the send_mail function... seems to work fine with your example. Any thoughts? I'm not getting any errors.

$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 = "XXX"; // Lucy

		// Set email confirmation settings
		$email_admin = 'XXX';
		$email_customer = $page->email;
		$email_admin_subject = "You added a new user $page->name";
		$email_customer_subject = 'Your login details';
		$email_customer_body = '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);
    }

});

 

Link to comment
Share on other sites

32 minutes ago, oma said:

It appears to work when I don't use the send_mail function... seems to work fine with your example

Sorry but I do not understand, could you explain a bit more please ?
Where do you first defined the send_mail () function ? (its not a ProcessWire or SendGrid function). If I assume you defined the function in, for example, _func.php, its normal you got an error of an undefined function. Just assuming...

In your last code snippet, everything look fine (I would have defined the function outside the hook).

Link to comment
Share on other sites

Sorry @flydev if I'm not being clear. I meant the 'send_email()' function as seen in my snippet. My code is exactly as the snippet looks but when dumping the result global $mail; bd($mail); with this example, as opposed to yours, it's returning NULL and not sending the email... no errors though.

Link to comment
Share on other sites

I understand now what you mean by no error.  There is one last error, which can be seen if you dump the variable $response. You could see that SendGrid return an error code which can be something like that :

statusCode => 401
body => "{"errors":[{"message":"Permission denied, wrong credentials","field":null,"help":null}]}"

The reason is that the global $sgAPIKey in the function is not getting the value from the $sgAPIKey defined with the key (from some reason that someone might explain here..)

To solve the issue, just set your API key in the function directly.

[...]
function send_email($from_email, $to_email, $subject, $body) {
	$sgAPIKey = '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'; // Lucy
[...]

 

  • Like 1
Link to comment
Share on other sites

8 hours ago, flydev said:

The reason is that the global $sgAPIKey in the function is not getting the value from the $sgAPIKey defined with the key (from some reason that someone might explain here..)

The reason for that is that the global keyword always refers to the global scope, i.e. the highest scope possible. In this case $gsAPIKey is first defined in a function scope, not in the global scope.. so no help from the global keyword :)

You should either define $sgAPIKey within send_email(), as shown in the example above, or you could define it earlier and pass it as an additional param to the function.

  • Like 3
Link to comment
Share on other sites

21 hours ago, flydev said:

I understand now what you mean by no error.  There is one last error, which can be seen if you dump the variable $response. You could see that SendGrid return an error code which can be something like that :


statusCode => 401
body => "{"errors":[{"message":"Permission denied, wrong credentials","field":null,"help":null}]}"

The reason is that the global $sgAPIKey in the function is not getting the value from the $sgAPIKey defined with the key (from some reason that someone might explain here..)

To solve the issue, just set your API key in the function directly.


[...]
function send_email($from_email, $to_email, $subject, $body) {
	$sgAPIKey = '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'; // Lucy
[...]

 

Apologies for the late reply. This makes sense... thanks for helping! How would you manage to dump $response? I can't seem to dump in either in a message or in Tracy to check the response.

12 hours ago, teppo said:

The reason for that is that the global keyword always refers to the global scope, i.e. the highest scope possible. In this case $gsAPIKey is first defined in a function scope, not in the global scope.. so no help from the global keyword :)

You should either define $sgAPIKey within send_email(), as shown in the example above, or you could define it earlier and pass it as an additional param to the function.

Thanks so much!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...