XF 2.2 Find user and send email issues

FoxSecrets

Active member
I am implementing a function to send email to the user and I got some questions regarding that:

1) How to find forum user according to the username from specific table. How to make this comparison?

2) What are the parameters of setTemplate? Can I send more than one parameter to template ? Any related documentation?

Code:
public function actionSendEmail(ParameterBag $params)
    {           
        $purchase = $this->assertPurchaseExists($params->license_id);

        $mail = \XF::app()->mailer()->newMail();
      
        $username = $purchase->user_name;
        $user = \XF::app()->find('XF:User', $member->username == $username );
      
        $mail->setToUser($user);
        $mail->setTemplate('my_email_template', [
            'purchase' => $purchase
        ]);
  
        $mail->queue();
    }
 
Last edited:
1) How to find forum user according to the username from specific table. How to make this comparison?
As usernames can change, I'd recommend storing the user ID on the table. You can look up the user ID from the username when saving your entity, and define a relation to XF:User. Then you would be able to do something like $yourEntity->User.

When storing user IDs and usernames, you should also add appropriate listeners for the user_content_change_init and user_delete_clean_init events to ensure changes are propagated to your data when users are merged, renamed, or deleted.

2) What are the parameters of setTemplate? Can I send more than one parameter to template ? Any related documentation?
It sets which email template to use and passes an array of parameters (variables) available to the template, much the same as rendering a view. You can add whatever parameters you like in the array:

PHP:
$mailer->setTemplate('some_template', [
    $one => 'one',
    $two => 'two',
]);
 
As usernames can change, I'd recommend storing the user ID on the table. You can look up the user ID from the username when saving your entity, and define a relation to XF:User. Then you would be able to do something like $yourEntity->User.
You mean like this?
Code:
$user = \XF::app()->find('XF:User', $purchase->User );
I'm getting the exception:
Code:
ErrorException: [E_USER_WARNING] Accessed unknown getter 'User'
When storing user IDs and usernames, you should also add appropriate listeners for the user_content_change_init and user_delete_clean_init events to ensure changes are propagated to your data when users are merged, renamed, or deleted.
Good point. I'll do that.
 
I'm getting the exception:
You'd need to define the relation on your entity structure:

PHP:
$structure->relations = [
    // ...
    'User' => [
        'entity' => 'XF:User',
        'type' => self::TO_ONE,
        'conditions' => 'user_id',
        'primary' => true,
    ],
    // ...
];
 
Now I'm getting ErrorException: [E_WARNING] Array to string conversion in src/XF/Mvc/Entity/Manager.php at line 894

Is this correct? It inspected {{dump($user);}} but nothing was returned

Code:
$user = \XF::app()->find('XF:User', $purchase->User);
 
If you already have the user relation, you don't need to query for the entity:
PHP:
$purchase = $this->assertPurchaseExists($params->license_id, ['User']); // eager-load (join) the relation

// ...

$mail->setToUser($purchase->User);
 
You're right, shame on me! Now I'm getting an exception in template 😢: LogicException: Template mail:my_email_template did not render to anything. It must provide either a text or HTML body.

I've written as text, why it's not rendering in this case?

Code:
$mail->setTemplate('my_email_template', [
            'purchase' => $purchase,
            'user' => $purchase->User
        ]);

my_email_template:

Code:
Hi {$user.username}!

Here is your purchase {$purchase.purchase_id}:
Product: {$purchase.product_name}
 
Did you create the template as an email template (ie. /admin.php?templates/add&style_id=0&type=email)?

Also, not important at all and really a matter of preference, but maybe worth noting that you can access relations in the template directly (ie. $purchase.User.username). Also email templates implicitly receive a $toUser parameter for the user who the email is being sent to.
 
I created as admin template 😖 omg. I changed to email now, I guess it worked!
I said "guess" because I've not received any email so far.
How can I make sure it worked? How can I popup success message in XF in a try/catch maybe?
 
Mail is queued so it's not send immediately, but it should work as long as your environment is otherwise able to send emails. Not sure if it's of any help, but I use Mailtrap (via SMTP) for development purposes.
 
I have used this in the past to write emails to the server, added to the config.php file.

It's quick and easy and works with email disabled using $config['enableMail'] = false; .

PHP:
$c->extend('mailer.transport', function()
{
    return \XF\Mail\Mailer::getTransportFromOption('file', [
        'path' => \XF::getRootDirectory() . '/_temp'
    ]);
});
 
Is it being submitted via an AJAX form? If so, you can return a redirect and a flash message will automatically be shown prior to redirecting:
PHP:
// you can customize the message by passing a second argument
return $this->redirect($this->buildLink('some/link'));

Otherwise you can just return a message:
PHP:
return $this->message(\XF::phrase('your_changes_have_been_saved'));
 
Top Bottom