1

The Laravel 5.3 Mailer class is configured as a singleton according to this article https://laravel-news.com/allowing-users-to-send-email-with-their-own-smtp-settings-in-laravel

Let's assume a user in a requests sets Mail::setSwiftMailer to a different server in order to send mails via his mailserver/account.

$transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 465, 'ssl');
$transport->setUsername('your_gmail_username');
$transport->setPassword('your_gmail_password');

$gmail = new Swift_Mailer($transport);

// Set the mailer as gmail
Mail::setSwiftMailer($gmail);

Does this affect other users? As far as I understood, the usual singleton characteristics do not apply in PHP http://blog.gordon-oheim.biz/2011-01-17-Why-Singletons-have-no-use-in-PHP/

A Singleton created in one Request lives for exactly that request. A Singleton created in another Request done at the same time will still be a completely different instance. And it will occupy it’s own memory. Those instances are not linked to each other. They are completely isolated, because PHP is a Shared-Nothing architecture. You do not have one single unique instance, but many similar instances in parallel processes.

So does changing the mailserver for the singleton function change the mailserver for other users?

Does changing the Laravel config affect the other users? I assume at least here the answer is yes.

Config::set('mail', ['driver' => $mail->driver, 'host' => $mail->host, 'port' => $mail->port, ...]);
Jo42
  • 23
  • 5
  • Seems you already have found your answer _...A Singleton created in one Request lives for exactly that request. A Singleton created...._ – B001ᛦ Jun 19 '19 at 11:38
  • Ok, I just needed to know for sure as this would be a major problem. And I actually do not really understand the singleton concept in PHP then. – Jo42 Jun 19 '19 at 11:41
  • Here you can find a good example and usecase. https://phpenthusiast.com/blog/the-singleton-design-pattern-in-php – Vikash Pathak Jun 19 '19 at 11:47
  • Possible duplicate of [Simultaneous Requests to PHP Script](https://stackoverflow.com/questions/1430883/simultaneous-requests-to-php-script) – Blackbam Jun 19 '19 at 11:53

2 Answers2

0

In conventional php every request is a different instance. nothing in inherited (variable wise) from an instance to another (from a request to another).

In the same instance, the mailer is a singleton during its lifespan

N69S
  • 16,110
  • 3
  • 22
  • 36
  • What exactly do you mean by conventional php? PHP in general? Or are there configurations that might behave differently? – Jo42 Jun 19 '19 at 11:44
  • You can launch a PHP process that doesn't die (keep on listening) via command. for example to serve a websocket port. it's not conventional but doable. – N69S Jun 19 '19 at 13:15
0

Have a look at the most simple Singleton implementation:

class Singleton {
    protected static $_instance = null;

    public static function newInstance()
    {
        if (null === self::$_instance)
        {
            self::$_instance = new self;
        }
        return self::$_instance;
    }

    // disallowed
    protected function __clone() {}

    // disallowed
    protected function __construct() {}
}

It makes sure that only one instance of this exists within this one and single request.

So your Swift_SmtpTransport is a Singleton:

$transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 465, 'ssl');

This means that every instance of Swift_SmtpTransport is the one you have just created (for this request) (this does not mean that you can not change the properties - maybe the instance has getters and setters to be called after it has been created).

And now lets see what you have already found out:

A Singleton created in one Request lives for exactly that request.

So it is per request and the request does also not affect other requests. So no, I do not think that other users are affected. Not even if you change the config as per single request.

For more information also read: Simultaneous Requests to PHP Script - for each request a new independent process is forked which does not have anything to do with the others. The only thing is that they may block each other.

The documentation of Laravel says:

Configuration values that are set at run-time are only set for the current request, and will not be carried over to subsequent requests.

Blackbam
  • 17,496
  • 26
  • 97
  • 150
  • 1
    Thanks for clarification on the config change. I was very unsure about that part. – Jo42 Jun 19 '19 at 11:53
  • The only exception of this would be if the config is shared across the multiple independent instances (e.g. if it is a file on the server which is read by fopen / fclose or e.g. a database). But the laravel dynamic config should live within its own interpreter process. – Blackbam Jun 19 '19 at 11:57
  • @Jo42 Also read this: https://stackoverflow.com/questions/40952224/laravel-configset-persist-through-requests - the config (as we found out) does not persist, but if you want to persist then use the database or environment variables). – Blackbam Jun 19 '19 at 12:05