Just spent a good amount of time trying to figure out why a class I created by extending Swift_Mailer in order to wrap the send() function was not working.
Turns out the ::newInstance() call mentioned here (and elsewhere) in the docs -- http://swiftmailer.org/docs/sending-quickref -- returns a Swift_Mailer instance, not my extended class. I simply replaced the instantiation of my class from 'my_class::newInstance($transport)' to 'new my_class($transport)' which is the standard way of doing things in PHP. You may wish to note everywhere in the documentation where it might be relevant that one must either use the standard way of creating new objects, or override newInstance(), when creating classes that extend parts of Swift. It'd be helpful to people who are not familiar with the newInstance() idiom.
newinstance() unfriendly in simple inheritance situations
Moderators: Chris Corbyn, General Moderators
-
gmorehoudh
- Forum Commoner
- Posts: 50
- Joined: Tue Mar 04, 2008 1:49 pm
Re: newinstance() unfriendly in simple inheritance situations
Either that or introduce a configuration parameter to allow the user to substitute a class name
- Chris Corbyn
- Breakbeat Nuttzer
- Posts: 13098
- Joined: Wed Mar 24, 2004 7:57 am
- Location: Melbourne, Australia
Re: newinstance() unfriendly in simple inheritance situations
This is a problem with PHP and lack of late static binding. PHP 5.3 will allow what you were doing to work correctly.
Everywhere I use newInstance() in Swift Mailer, the "new" keyword can be used too, I just advertise the use of newInstance() for a couple of reasons:
1) It's more likely to scale if I need to change the way the object is created
2) It's the only way you can chain off of the constructor, which I do quite a bit in the documentation.
I'll add something to the docs to mention that the new keyword is also allowed.
On a side note, Swift Mailer is designed so that you shouldn't have to override the send() method and if you're doing this to say, write the mail to a database instead then the "best" course of action is to use composition and write a new Transport. Transports are really simple:
If your intention is to add some logic before or after an extisting transport runs then just wrap it:
Everywhere I use newInstance() in Swift Mailer, the "new" keyword can be used too, I just advertise the use of newInstance() for a couple of reasons:
1) It's more likely to scale if I need to change the way the object is created
2) It's the only way you can chain off of the constructor, which I do quite a bit in the documentation.
I'll add something to the docs to mention that the new keyword is also allowed.
On a side note, Swift Mailer is designed so that you shouldn't have to override the send() method and if you're doing this to say, write the mail to a database instead then the "best" course of action is to use composition and write a new Transport. Transports are really simple:
Code: Select all
interface Swift_Transport {
function start();
function stop();
function isStarted();
function send(Swift_Mime_Message $message);
}Code: Select all
$myTransport = new MyTransport(new Swift_SmtpTransport(...));
/* ....
Class MyTransport ....
function send(Swift_Mime_Message $message)
{
$this->doSomething();
return $this->_delegate->send($message);
}
...
*/-
gmorehoudh
- Forum Commoner
- Posts: 50
- Joined: Tue Mar 04, 2008 1:49 pm
Re: newinstance() unfriendly in simple inheritance situations
Thanks Chris, I will take a look at doing it this way. We are adding logic to divert outbound mail to ourselves if the code is running on one of our development workstations as opposed to the production server.
-
gmorehoudh
- Forum Commoner
- Posts: 50
- Joined: Tue Mar 04, 2008 1:49 pm
Re: newinstance() unfriendly in simple inheritance situations
Say, what's that _delegate bit in there?
- Chris Corbyn
- Breakbeat Nuttzer
- Posts: 13098
- Joined: Wed Mar 24, 2004 7:57 am
- Location: Melbourne, Australia
Re: newinstance() unfriendly in simple inheritance situations
The _delegate bit is the transport that the work will be delegated togmorehoudh wrote:Say, what's that _delegate bit in there?
Code: Select all
class MyTransport implements Swift_Transport {
private $_delegate;
public function __construct(Swift_Transport $delegate) {
$this->_delegate = $delegate;
}
public function isStarted() {
return $this->_delegate->isStarted();
}
public function start() {
return $this->_delegate->start();
}
public function stop() {
return $this->_delegate->stop();
}
public function send(Swift_Mime_Message $message) {
$this->_doSomething(); //Customized behaviour
return $this->_delegate->send($message); //Delegation
}
private function _doSomething() {
echo "Hey, I've customized this send() thingy";
}
}
$delegate = Swift_SmtpTransport::newInstance('localhost', 25);
$mailer = new Swift_Mailer(new MyTransport($delegate));