Link to home
Start Free TrialLog in
Avatar of Crazy Horse
Crazy HorseFlag for South Africa

asked on

send html emails using a view as the content

In my base controller I have this code which checks if there is a view and then displays it. I want to modify this to use for sending an email. I basically want to create views which contain html content for sending the mails. But trying to access it normally as if I were displaying a view doesn't quite work. This is the code for displaying the views on the website.

	public function view($view, $data = []) {
		// check for view file
		if(file_exists('../app/views/' . $view . '.php')) {
			require_once '../app/views/' . $view . '.php';
		} else {
			die('View does not exist');
		}
	}

Open in new window


To display a view, I would just do this in my controller:

$this->view('pages/contact-us');

Open in new window


When I am trying to send email, I want to just send the view into the email body.

$html = $this->view('pages/email');
//other variables go here

$send = new Email();
$send->sendMail($html, $subject, $setFrom, $addReplyTo, $addAddress, $altBody);

Open in new window


Doing this fails. I think I need to just return the view but not sure how to do this.
ASKER CERTIFIED SOLUTION
Avatar of Steve Bink
Steve Bink
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Crazy Horse

ASKER

@Steve, thanks for your comments. I am not using a framework like Laravel etc. so I should be able to do whatever I like, provided I know what to actually do :)

Before you answered, I had progressed slightly. I created a new method in my core controller like this.

public function getView($view, $data = []) {
if(file_exists('../app/views/' . $view . '.php')) {
     return file_get_contents('../app/views/' . $view . '.php');
} else {
    die('View does not exist');
}

Open in new window


And then did this in the controller:

$html = $this->getView('pages/contact-email', $data);

Open in new window


The plain html content is now displaying in the emails which is great but not the php. If I try this in the view:

<?php echo $data['name']; ?>

Open in new window


nothing shows up php wise, just the html and missing gaps where there should be dynamic values.

$data is just the values from the form in an array eg:

$data = [
 
  'name' => $_POST['name']

];

Open in new window

That's because file_get_contents() doesn't actually execute PHP - it just returns the contents of the file as text.  You should still continue to use require/include to make sure the code runs.  Any variables in the calling scope should be available within the file, which means accessing $data directly should work fine.
I took a look at ob_start() and got it to work by doing this. Is it an acceptable way?


public function getView($view, $data = []) {
	if(file_exists('../app/views/' . $view . '.php')) {
		ob_start();
		require '../app/views/' . $view . '.php';
		return ob_get_clean();

	} else {

		die('View does not exist');
	}
}

Open in new window


I would have preferred to do what you said here but couldn't figure out how.

Edit the view class to support the separate rendering function.  If this is your framework, this would be my recommended path.  If this is a third-party framework, you should think long and hard about doing this.
Based on your usage of require/include to create your view output, I'm guessing you don't have an actual view class.  That would make it much harder to pursue that option.

Your ob_start() example is right on the nose.