Jump to content
iwato

How to Automate an HTTPRequest with PHP

Recommended Posts

BACKGROUND:  I have a PHP generator that creates a newsletter from an HTML template with data obtained from a MySQL database.  My current plan is to include with the generator an automated mailing function using PHPMailer.  I intend to use this generator to consummate to kinds of mailing functions -- mass and individual.  The individual mailing:  when a user opens an account he automatically receives an automatically generated newsletter with information designed for first users. In this newsletter he has the option of subscribing on a more permanent basis or declining further receipt of future newsletters.

TWO TRIGGERS:  The code that triggers the mailing of the first newsletter will come from the user and must be automated.  The code that triggers a mass mailing to all subscribers must come from me and must be manual.  This latter trigger can be resolved easily with a simple link and attached query statement.  It is the automated trigger coming directly from the user that is problematic.

THE DILEMMA:  When the user applies for an account, he receives a verification email with a link  to a PHP processor that matches the hash that he received in the email with the one created and inserted into a database when he signed up for the account.  It is this PHP processor that must provide the information to the newsletter generator and trigger the new account holder's first mailing of the newsletter.  The trigger must be automated.

QUESTION: Although it is relatively easy to write Javascript that automatically triggers an HTTPRequest object to the newsletter generator, I am having trouble finding a simple PHP routine that will do the same.  Have you any suggestions?

Roddy

Share this post


Link to post
Share on other sites

If both the newsletter generator and the verification page are on the same server then there's no need for any HTTP requests. Just write PHP code on the verification page that manipulates the newsletter database.

Share this post


Link to post
Share on other sites

My goal is to use the same page with directives from two different sources (triggers):  one from the verification page that is on the server,  and one from a form that is situated locally.  A receiving $_POST variable on the generator page would not care from which source the request was made.

Is it more understandable now?

Roddy

 

Share this post


Link to post
Share on other sites

It's over-complicated.  Write a function that sends the email, and call the same function from both locations.  The function that sends the email should not be concerned with where the input values come from.  Its job is to send the email, not gather input data.  In one place you can get them from post data, in other place you can get them from a database or hard-code them or whatever you want to do.  Anything that needs to be changed in how the email gets sent should be passed to the function as a parameter.  Try to make generic functions that are generally usable in as many situations as possible instead of requiring something like post data to always be present.  Keep it simple.

Share this post


Link to post
Share on other sites
Quote

Write a function that sends the email, and call the same function from both locations.  The function that sends the email should not be concerned with where the input values come from.  Its job is to send the email, not gather input data.

 Excuse me, but what could be simpler than generating the template and email on the same page and not caring from where the instruction comes?

Roddy

p.s.  Just to be clear, I am referring to the email that sends the newsletter, not the verification email that calls the generator to process the template and mail the letter.

Edited by iwato

Share this post


Link to post
Share on other sites

You save yourself the trouble of making an HTTP request from your server to your own server. It's like walking out the front door of your house and getting into the back door in order to go from the living room to the kitchen. In technical terms it's slow and marginally less secure.

Your program should be broken into several modules, each being able to interact with each other within the same environment. You could break your program into a generate_template($vars) function and a verify_email($address, $code) function among others that do different tasks, then you would do the following:

$verified = verify_email($_POST['email'], $_POST['verification_code']);
if($verified) {
  $vars = [
    'title' => 'Something',
    'name' => 'Something'
  ];
  $to = $_POST['email'];
  $subject = 'Email subject';
  $body = generate_template($vars);
  send_an_email($to, $subject, $body);
}

This is, of course, very simplified, but the  verify_email(), generate_template(), send_an_email() functions can be used anywhere on your site, just put them in a file and include the file where needed. I usually make more complex programs and use objects with properties and methods rather than just functions. These objects can be used on many different pages, each page just has to include the objects that it needs.

  • Thanks 1

Share this post


Link to post
Share on other sites

What could be simpler?  Not creating a new HTTP request with all of the overhead that comes with it just to send an email.  Why the heck are you requiring an HTTP request to send an email?  What does an HTTP request have to do with sending email?  Why have you introduced that requirement?

Share this post


Link to post
Share on other sites

INGOLME:  I will need some time to figure out whether I can pull off what you are suggesting easily.  Certainly I know how to write and implement a PHP function, but am known to run into problems of scope on occasion.  Also, your suggestion confounds the verification process with the mailing process on the same page -- an idea that, from my most humble technological viewpoint, appears more complicated.  

The other connection (trigger) between my local form and remote processing page necessitates, of course, an HTTPRequest.  There is no getting around this.

JSG:  

Quote

Why the heck are you requiring an HTTP request to send an email?

Because  the information required to send the email is produced on a different page.

Quote

  What does an HTTP request have to do with sending email? 

See above.

Quote

Why have you introduced that requirement?

Please read my BACKGROUND, TRIGGER, and DILEMMA notes carefully.  I believe that the answer can be found there.

Share this post


Link to post
Share on other sites

Please read my BACKGROUND, TRIGGER, and DILEMMA notes carefully.  I believe that the answer can be found there.

Sorry, but I don't see it.  I see one of two things happening.  Either the user creates an account and immediately gets the newsletter emailed, or they click on the link in the email to verify their account and then the newsletter gets emailed.  In both of those cases PHP is already running and there is zero need to send an HTTP request to start a different PHP script.  The request is an unnecessary restraint that you've added.  You CAN do it that way, it's just the long and inefficient route like Ingolme suggested with the house analogy.  Here's another analogy: if I want to go to my neighbor's house, I can either walk out my front door, turn to that house, and go there, or I can turn the opposite direction and walk completely around the block to get to the house from the other side.  I've ended up at the same place, but one of those ways is longer and less efficient if my only goal was to get to my neighbor.  You already have PHP running.  You do not need to send a request to your own server of all things just to have PHP do something else, you can just have it do that directly.  And that sentence is true regardless of the thing you're trying to do.  That's why I'm hesitant to just tell you how to send a request, because it's not designed correctly.  It may be easier to point out how and why if you want to show the relevant code.  If you just want to know how to send a request we can tell you, but the reason we have these conversations is because we don't think you're designing it the best way you can and that's what we're trying to help with.

Because  the information required to send the email is produced on a different page.

This sounds like a symptom of the problem - you're not designing things to be modular enough.  Your function to send the email should be able to take the input data however it is generated, it shouldn't require a specific process to gather the data.  You should be able to gather the data any way you want and then call the same function to do the actual work, and that function should be agnostic to how the data was gathered.  This is a core principle of efficient program design.  Programming is less about creating huge complex things, and more about creating small things which each do one task well, and then combining those small things into the bigger parts.  That's how you end up with something that is easy to extend, reuse, and maintain going forward.  That's what we're trying to help you with.  If you don't care about that, then use cURL to send the request and be done with it.  I just think you're making it harder on yourself.

Share this post


Link to post
Share on other sites
$verified = verify_email($_POST['email'], $_POST['verification_code']);
if($verified) {
  $vars = [
    'title' => 'Something',
    'name' => 'Something'
  ];
  $to = $_POST['email'];
  $subject = 'Email subject';
  $body = generate_template($vars);
  send_an_email($to, $subject, $body);
}

If I have understood correctly, you are suggesting the creation of three functions

generate_template()
send_an_email()

and then a routine that executes the generate_template() and send_an_email(), if the value of  verify_email is Boolean true.

What I am unclear about is the nature of the following expression

verify_email($_POST['email'], $_POST['verification_code']);

 Is verify_email() a  function, an array, or an object or some combination of these?  If  it is a function, is it one that I can call independently of $verified.  What would I be creating exactly.

Roddy 

Share this post


Link to post
Share on other sites

It's a function where he's passing the email address and verification code, and storing the return value in $verified.  Presumably that would be a boolean return value for whether or not the email is valid.

Share this post


Link to post
Share on other sites

JSG: 

Quote

That's why I'm hesitant to just tell you how to send a request, because it's not designed correctly.

Thank you for the hesitation.  I have understood your hesitance well.

Quote

You should be able to gather the data any way you want and then call the same function to do the actual work, and that function should be agnostic to how the data was gathered.  This is a core principle of efficient program design.  Programming is less about creating huge complex things, and more about creating small things which each do one task well, and then combining those small things into the bigger parts.

This is, indeed, what I am attempting to do.  Simply, my idea was to do it on its own separate page.  Up until this point my preference for compartmentalization has been webpages.  The reason for this has been one of order.  In short, each page is its own entity that can be accessed at will and neatly listed on an index page for easy reference.  Accordingly, most functions that I write are written and entered on two separate pages:  one in HTML with a highlighted explanation as to how the function works and what tasks it can perform, and the other written only in the language of the function that can be included anywhere at will.  The organizing principle here is the same as above.

You appear to be pushing me in the direction of efficiency.  Efficiency with an important  cost, namely, my organizational strategy that has served me so well up until now. I foresee a painful adjustment.

Share this post


Link to post
Share on other sites
Quote

It's a function where he's passing the email address and verification code, and storing the return value in $verified.  Presumably that would be a boolean return value for whether or not the email is valid.

Can I now access that function anywhere, or is it dependent on the variable whose return value it contains?

Share this post


Link to post
Share on other sites

Up until this point my preference for compartmentalization has been webpages.

This is a strategy that the vast majority of PHP developers do not choose.  The reason is because you have added the requirement for a new request in order to use those parts and, probably more importantly, they do not run in the same environment.  The new request is a brand new environment not connected in any way to the current PHP environment other than whatever values you sent with the request.  If instead you just include the other files and execute functions directly then everything is running in the same environment.  Everything has access to all of the data from the original request sent by the user, all of the variables are still available, etc.

Can I now access that function anywhere, or is it dependent on the variable whose return value it contains?

Once you declare a function you can execute it from any scope in the same environment, all functions are global.  Functions are not dependent on what you choose to do with the return value.

Share this post


Link to post
Share on other sites

As a basic example, this is a file which is included by every endpoint in our application:

<?php

define('LMS_DEBUG', ('development' == '##DEV##'));
define('LMS_VERSION', '9.6.0');

error_reporting(E_ALL ^ E_STRICT);
ini_set('error_log', __DIR__ . '/error.log');

require_once 'FirePHPCore/fb.php';

$php_command_line = strpos(php_sapi_name(), 'apache') === false && (strpos(php_sapi_name(), 'cgi') !== false || strpos(php_sapi_name(), 'cli') !== false);

/** @var array $config */
require_once 'global.config.php';

// check for SSL and update http_root if necessary
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
    $config['http_root'] = str_replace('http://', 'https://', $config['http_root']);
}

// If pw_version is not set, use default of 3
if (!isset($config['pw_version'])) {
    $config['pw_version'] = 3;
}

date_default_timezone_set($config['timezone']);
if (!$php_command_line) {
    session_name('lms8');
    $cookie_info = session_get_cookie_params();
    session_set_cookie_params($cookie_info['lifetime'], '/', $config['cookie_domain'], $cookie_info['secure'], $cookie_info['httponly']);
}

require_once 'functions.global.php';

require_once 'class.db.php';
$db = new tc_lms_database($config['db_host'], $config['db_user'], $config['db_pass'], $config['db_name']);

require_once 'class.pdo.php';
$pdo = new tc_lms_pdo($config['db_host'], $config['db_user'], $config['db_pass'], $config['db_name']);

require_once 'factory.passwordhash.php';

require_once 'class.lang.php';
$lang = new tc_lms_lang();

if (!$php_command_line) {
    require_once 'class.session.php';
    $sess = new tc_lms_session();
} else {
    $sess = null;
}

require_once 'class.userfield.php';
require_once 'class.userfields.php';
$uf = new tc_lms_userfields();

require_once 'class.config.php';
$opts = new tc_lms_config();

require_once 'class.datacache.php';
$cache = new tc_lms_datacache($config['cache_timeout']);

require_once 'class.lms.global.php';
$global = new tc_lms_global($db, $pdo, $lang, $sess, $uf, $opts, $cache);
if (!is_null($sess)) {
    require_once 'factory.userpermissions.php';
    $perms = tc_lms_permissionsFactory::build($global, $sess);
    $global->setPerms($perms);
}

require_once 'functions.usergroups.php';
require_once 'functions.images.php';
require_once 'functions.content.php';
require_once 'functions.learning_tracks.php';
require_once 'functions.emails.php';
require_once 'functions.dates.php';
require_once 'functions.change.logs.php';
require_once 'Json.php';

// Set Html Purifier @link http://htmlpurifier.org/docs
require_once __DIR__ . '/htmlpurifier-4.8.0/library/HTMLPurifier.auto.php';
$html_purifier_config = HTMLPurifier_Config::createDefault();
$html_purifier_def = $html_purifier_config->getHTMLDefinition(true);  // Turn off caching.
$html_purifier_def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');  // White list target attribute for links.
$html_purifier = new HTMLPurifier($html_purifier_config);


if (!empty($_GET['theme'])) {
    $config['ext_theme'] = $_GET['theme'];
    $sess->set_val('ext_theme', $config['ext_theme']);
}

// auto-launch content

if (!empty($_GET['cid']) && count($_GET) == 1) { // only redirect to content if it's the only parameter, otherwise it's used for reports and other things
    $sess->set_val('auto_launch_cid', $_GET['cid']);
    $sess->redirect($config['http_root']);
}

// auto-register for class
if (!empty($_GET['creg'])) {
    $sess->set_val('auto_register_class', $_GET['creg']);
    $sess->redirect($config['http_root']);
}

// auto-register for webinar
if (!empty($_GET['wreg'])) {
    $sess->set_val('auto_register_web', $_GET['wreg']);
    $sess->redirect($config['http_root']);
}

// The other content types are defined in global.config.php. This has to be defined here to avoid manually updated every client
define('CONTENT_TYPE_MULTISCO', 6);
$config['content_types'][6] = 'Bundled Content';

define('BADGE_SHERLOCK_HOLMES', 1);   // Searched for content in the Search field
define('BADGE_VANITY', 2);            // Changed profile image
define('BADGE_STUDENT', 3);           // Completed a content item
define('BADGE_HONOR_STUDENT', 4);     // Completed 10 content items
define('BADGE_SCHOLAR', 5);           // Completed 100 content items
define('BADGE_CERTIFIED', 6);         // Completed a content item which contains a certificate

$config['max_regfields'] = 64;
// Regular expression to match field1 - field64.
define('USER_FIELDS_PREG', '/^field(\d|[12345]\d|60|61|62|63|64)$/');

// auto-search for class sessions
if (!empty($_GET['cs'])) {
    $sess->set_val('auto_search_class', $_GET['cs']);
    $sess->redirect($config['http_root']);
}

What all of those values mean aren't important, but starting from the top it defines a few constants or variables, and then it starts including other files (global.config.php, functions.global.php, class.db.php, etc).  If it includes a class definition file then it creates a new object of that class, and it includes all of the files which define the various global functions for the application.

What this means is that we can create a new PHP file and include this single file - global.init.php - and after that the new PHP code has access to every object and every function used in the entire application (other than the smaller functions defined in individual PHP files just for use in that one file).  One of those files, for example, is functions.emails.php, so any new PHP file that includes this init file can use all of the email functions to send email or anything else.  It can instantly use the database without trying to connect again, it has access to all of the config settings, everything.  It doesn't need to send any external requests, it just includes this one file, everything gets defined, and then it can do whatever it needs to do.

Share this post


Link to post
Share on other sites
Quote

Once you declare a function you can execute it from any scope in the same environment, all functions are global.  Functions are not dependent on what you choose to do with the return value.

Please allow me to restate my question:  Is the function  verify_email( ) -- as written in Ingolme's snippet -- properly declared?  Or, has she assumed its prior existence and not written its full declaration as a heuristic expedient?

Share this post


Link to post
Share on other sites

None of the functions are defined, these are examples of using functions to keep your other code short and clean.  No one knows how you're going to verify the email other than you, those details are left to you.

Share this post


Link to post
Share on other sites

verify_email() is just an example function, which I would expect you to declare in a file that will be included on any page that needs to make use of it. I don't know what's supposed to go in that function or even if the number of arguments I created is correct, since I don't know the full requirements of your application. It's up to you to break your program into reusable parts that each work on their own.

 

Share this post


Link to post
Share on other sites

Yes, Ingolme and JSG, I have gotten the message and have figured out a way to catalogue the functions.   Simply it will take more time.  In effect, it is a short-term sacrifice for the long term.  Unfortunately, these short-term sacrifices for the long-term are very expensive -- well, at least, for me, anyway..

in the end, I am surprised that you have not recommended that I create classes. 

Please find below a copy of my code, review it, and then tell me which of the approaches given below the code would be the most appropriate and why.
Please understand that this code only assembles the data from the database -- little more.  Your answer will likely guide me in assembling the entire package.

<?php
/************************************************************
Set up PHP error reporting.
*************************************************************/
	ini_set('display_errors', 1);
	ini_set('display_startup_errors', 1);
	error_reporting(E_ALL);
/************************************************************
Manual entry of letter number.
*************************************************************/
/*	$letter_no = 2;
	echo $letter_no;
	echo "<br /><span style='color:blue;'>\$param_val</span><span style='color:red;'>: The number of the newsletter that generates the retrieval of the data necessary to fill the template that becomes the newsletter.</span>";
	echo '<hr>';
*/	
/************************************************************
The Test for a Valid $_GET Request (Automated Variable Assignment of the Number of the Current Edition)
*************************************************************/
	if ($_SERVER["REQUEST_METHOD"] == "GET") {
		if (empty($_GET['letter_no'])) {
			$error_msg = "Please submit an edition number for the newsletter that you desire.";
		} else {
			$letter_no = filter_var($_GET['letter_no'], FILTER_VALIDATE_INT);
			amass_data($letter_no);
		/*********************************************************************************************
		Close Test for the presence of a proper edition number.
		*********************************************************************************************/
		}
	/*********************************************************************************************
	Close Test for Proper a HTTPRequest
	*********************************************************************************************/
	}
	/*********************************************************************************************
	Create the amass_data() Funtion with Prepared SQL Statments
	*********************************************************************************************/
	function amass_data($letter_no) {			
		/************************************************************
		Establish a connection with the database and set the character set.
		*************************************************************/
			define('_HOST_NAME','baha.lunarbreeze.com');
			define('_DATABASE_NAME','...');
			define('_DATABASE_USER_NAME','...');
			define('_DATABASE_PASSWORD','...');
			$mysqli_obj = new MySQLi(_HOST_NAME,_DATABASE_USER_NAME,_DATABASE_PASSWORD,_DATABASE_NAME);
			if($mysqli_obj->connect_errno) {
				die("ERROR : -> ".$mysqli_obj->connect_error);
			}
		/************************************************************
		Set the Character Set of Database Communication to UTF-8
		*************************************************************/
			if(!$mysqli_obj->set_charset("utf8")) {
				printf("Error loading character set utf8: %s\n", $mysqli_obj->error);
				exit();
			}
		/*********************************************************************************************
		Select (With a Prepared Statement) the data from the Sevengates _letter and _qa data tables that corresponds to the designated letter number. 
		*********************************************************************************************/
			$sql = "SELECT letter.*, qa.qa_question, qa.qa_answer
						FROM sevengates_letter AS letter
						JOIN sevengates_qa AS qa
							ON qa.letter_no = letter.letter_no
							WHERE letter.letter_no =?";

			$mysqli_stmt = $mysqli_obj->stmt_init();
			$mysqli_stmt->prepare($sql);
			$mysqli_stmt->bind_param('i', $letter_no);
			$mysqli_stmt->execute();
			$meta = $mysqli_stmt->result_metadata();
			while ($field = $meta->fetch_field()) {
				$params[] = &$row[$field->name];
			}
			call_user_func_array(array($mysqli_stmt, 'bind_result'), $params);
			while ($mysqli_stmt->fetch()) {
				foreach($row as $key => $val) {
					$c[$key] = $val;
				}
				$prelim_result[] = $c;
			}
			$mysqli_stmt->free_result();
			//$mysqli_obj->close();
			foreach ($prelim_result as $arr) {
				foreach ($arr as $name => $value){
					echo $name . ': ' . $value . '<br />';
					$letter_results[$name] = $value;
				}
			}
			echo "<span style='color:blue;'>\$letter_results</span><span style='color:red;'>: Selected data from the designated Seven Gates newsletter data</span>";
			echo '<hr>';
		/*********************************************************************************************
		Extract the number of the most recently posted newsletter data.
		*********************************************************************************************/
			$letter_no = $letter_results['letter_no'];
			echo '$letter_results["letter_no"] = '. $letter_no;
			echo "<br /><span style='color:red;'>The just requested Seven Gates edition number.</span>";
			echo '<hr>';
		/*********************************************************************************************
		Next Newsletter Preview from Current Letter Edition
		*********************************************************************************************/
			$next_letter_no = $letter_no + 1;
			echo '$next_letter_no' . ': ' . $next_letter_no . '<br />';
			echo '$letter_results["next_title"] = '. $letter_results['next_title'] . '<br />';
			echo '$letter_results["next_letter"] = '. $letter_results['next_letter'] . '<br />';
			echo "<span style='color:blue;'>\$next_result</span><span style='color:red;'>:  Selected preview data for next Seven Gates newsletter taken from the current letter archive.</span>";
			echo '<hr>';
		/*********************************************************************************************
		Next Newsletter Preview from Next Letter Edition
		*********************************************************************************************/
			$result = [];
			$params = [];
			$row = [];
			$c = [];
			$prelim_result = [];
			$sql = "SELECT letter_title, letter_abstract FROM sevengates_letter WHERE letter_no = ?";
			$mysqli_stmt = $mysqli_obj->stmt_init();
			$mysqli_stmt->prepare($sql);
			$mysqli_stmt->bind_param('i', $next_letter_no);
			$mysqli_stmt->execute();
			$meta = $mysqli_stmt->result_metadata();
			while ($field = $meta->fetch_field()) {
				$params[] = &$row[$field->name];
			}
			call_user_func_array(array($mysqli_stmt, 'bind_result'), $params);
			while ($mysqli_stmt->fetch()) {
				foreach($row as $key => $val) {
					$c[$key] = $val;
				}
				$prelim_result[] = $c;
			}
			$mysqli_stmt->free_result();
			//Print and store preview data obtained from the next letter archive.
			foreach ($prelim_result as $arr) {
				foreach ($arr as $name => $value){
					echo $name . ': ' . $value . '<br />';
					$nextletter_results[$name] = $value;
				}
			}
			echo '<span style="color:blue;">$nextletter_results</span><span style="color:red;">:  Selected preview data for next Seven Gates newsletter obtained from the next letter archive.</span>';
			echo '<hr>';
		/*********************************************************************************************
		Discover (With a Prepared Statement) the podcasts associated with the most recently posted newsletter data
		*********************************************************************************************/
			$params = [];
			$prelim_result = [];
			$row = [];
			$c = [];
			$podcasts = [];
			$sql = "SELECT podcast_ref FROM sevengates_podref WHERE letter_no = ?";
			$mysqli_stmt = $mysqli_obj->stmt_init();
			$mysqli_stmt->prepare($sql);
			$mysqli_stmt->bind_param('i', $letter_no);
			$mysqli_stmt->execute();
			$meta = $mysqli_stmt->result_metadata();
			while ($field = $meta->fetch_field()) {
				$params[] = &$row[$field->name];
			}
			call_user_func_array(array($mysqli_stmt, 'bind_result'), $params);
			while ($mysqli_stmt->fetch()) {
				foreach($row as $key => $val) {
					$c[$key] = $val;
				}
				$prelim_result[] = $c;
			}
			$mysqli_stmt->free_result();
		//	$mysqli_obj->close();
		/*********************************************************************************************
		Extract the value for each referenced podcast, assign to it a unique name, and create from this unique name and associated value an array whose elements are the name-value pairs for each referenced podcast.
		*********************************************************************************************/
			$i = 1;
			foreach ($prelim_result as $arr) {
				foreach ($arr as $name => $value) {
					$name = $name . '_' . $i;
					$podcasts[$name] = $value;
				}
				$i++;
			}
			$pc_total = count($podcasts);
		//Display $pc_total
			echo '<span style="color:blue;">$pc_total</span>:  There are <span style="color:red;">' . $pc_total . '</span> podcasts associated with the Seven Gates Newsletter No. ' . $letter_no;
			echo '<hr>';
		/*********************************************************************************************
		Retrieve data (With a Prepared Statement) from the named fields of the just discovered podcasts.
		*********************************************************************************************/
			$prelim_result = [];
			foreach ($podcasts as $name => $value) {
				$params = [];
				$c = [];
				$row = [];
				$mysqli_stmt = $mysqli_obj->stmt_init();
				$sql = "SELECT item_podtype, podcast_no_item, item_title, item_description, item_guid FROM rss2_podcast_item WHERE podcast_no_item = ?";
				$mysqli_stmt->prepare($sql);
				$mysqli_stmt->bind_param('i', $value);
				$mysqli_stmt->execute();
				$meta = $mysqli_stmt->result_metadata();
				while ($field = $meta->fetch_field()) {
					$params[] = &$row[$field->name];
				}
				call_user_func_array(array($mysqli_stmt, 'bind_result'), $params);
				while ($mysqli_stmt->fetch()) {
					foreach($row as $key => $val) {
						$c[$key] = $val;
					}
				}
				$prelim_result[] = $c;
				$mysqli_stmt->free_result();
			}
		//	print_r($prelim_result);
			$mysqli_stmt->free_result();
			//$mysqli_obj->close();
			foreach ($prelim_result as $arr) {
				foreach ($arr as $name => $value){
					echo $name . ': ' . $value . '<br />';
					$pc_results[$name] = $value;
				}
				echo '<br />';
			}
			echo '<span style="color:blue;">$pc_results</span><span style="color:red;">:  Data retrieved from the above named podcasts.</span>';
			echo '<hr>';
		/*********************************************************************************************
		Close the amass_data() function.
		*********************************************************************************************/			
		}
?>
<?php
/*	require_once("/Users/kiusau/vendor/autoload.php");
	$lipsum = new joshtronic\LoremIpsum();				
	var_dump(class_exists('joshtronic\LoremIpsum', false));
	require_once("../../_utilities/php/page.php");
	$start = "<!DOCTYPE html>";
	$end = "</html>";
	$page = new Page("./newsletter_template.php", $start, $end);
	$page->parse("./newsletter_template.php");
	$tags = array(
		'letter_no' => $result['letter_no'],
		'letter_title' => $result['letter_title'],
		'letter_link' => $result['letter_link'],
		'letter_abstract' => $result['letter_abstract'],
		'date' => $result['submission_date'],
		'revision' => $result['revision_date'],
	);
	$page->replace_tags($tags);
	$page->output();
*/
?>

What are the advantages and disadvantages of each approach and why?
Which would you recommend, if any?

  • Leave the code as is and simply include or require it where  necessary.
  • Write the whole thing as a single class and convert the functions into methods.
  • Write a new class for each function

Roddy

Share this post


Link to post
Share on other sites

If you want to create classes for everything that's great, I was focused on trying to get you to separate everything in the first place.  A reasonable class structure is probably the best option in nearly every situation, so if you're comfortable with that then do it.  You can create, for example, a podcast class with everything you need to do with them, a podcast factory class for creating or getting individual or lists of podcasts, etc.

About the code, the first thing I would do is move some of those things out into a generic include file for every page.  Things like error reporting settings, database connectivity settings, and other things that are not for specific pages should go into a single include file.  The point being that you only have 1 place to make changes if you need to adjust any of those.  You don't want to go searching through a bunch of files if your database password changed.

It looks like you need a newsletter class.  Another principle of good design is that you generally want functions to do one thing.  I think that function in particular would be better if it returned all of the data instead of sent everything to the browser (although it looks like you're mostly printing things just to see what's going on), because you may have a place where you want to get newsletter data but not send it to a browser.  So it should return the data instead of using echo, and then whatever called the function can either load a template to print it to the browser, or maybe load an email template, or whatever else. 

If you broke that function above up into a class for a newsletter, it looks like some of the methods might be things like getQA, getNextPreview, getPodcasts, etc.  Maybe the getPodcasts method would return an array of podcast objects that correspond with the newsletter.  You would also have get/set methods for each of the database fields or other properties that make up the object (getId, getTitle, getAbstract, etc).

  • Thanks 1

Share this post


Link to post
Share on other sites

Yes, you have understood correctly.  I echo as a means to insure that I am getting what it is that i am after.  Already, I have created the functions that I will convert into methods, and each has a return value corresponding to what I have echoed. 

Eight years have passed since I created my first PHP class, but I took very good notes.  Your suggestion about the get and set methods reminded of something I had forgotten.  And, your suggestion with regard to the error and connectivity code excites me, as I recently changed my password and discovered that it was a very time-consuming process to call up all the files containing connectivity code.  

So, once again, thank you kindly for your help.

Roddy

Share this post


Link to post
Share on other sites

Please review the following code and make any suggestions that might improve it.
Please understand that all functions and variables can be called and yield the proper results.

	class Newsletter {
		public $letter_no;
		public $mysqli_obj;
		public $pc_total;
		public $podcasts;
		public function __construct($letter_no, $mysqli_obj) {
			$this->letter_no = $letter_no;
			$this->mysqli_obj = $mysqli_obj;
		}
		
		public function get_letter() {
			$mysqli_obj = $this->mysqli_obj;
			$letter_no = $this->letter_no;
			$sql = "SELECT letter.*, qa.qa_question, qa.qa_answer
						FROM sevengates_letter AS letter
						JOIN sevengates_qa AS qa
							ON qa.letter_no = letter.letter_no
							WHERE letter.letter_no =?";

			$mysqli_stmt = $mysqli_obj->stmt_init();
			$mysqli_stmt->prepare($sql);
			$mysqli_stmt->bind_param('i', $letter_no);
			$mysqli_stmt->execute();
			$meta = $mysqli_stmt->result_metadata();
			while ($field = $meta->fetch_field()) {
				$params[] = &$row[$field->name];
			}
			call_user_func_array(array($mysqli_stmt, 'bind_result'), $params);
			while ($mysqli_stmt->fetch()) {
				foreach($row as $key => $val) {
					$c[$key] = $val;
				}
				$prelim_result[] = $c;
			}
			foreach ($prelim_result as $arr) {
				foreach ($arr as $name => $value){
					$letter_results[$name] = $value;
				}
			}
			return $letter_results;
		}

		public function get_nextletter() {
			$letter_no = $this->letter_no;
			$mysqli_obj = $this->mysqli_obj;
			$next_letter_no = $letter_no + 1;
			$sql = "SELECT letter_no, letter_title, letter_abstract FROM sevengates_letter WHERE letter_no = ?";
			$mysqli_stmt = $mysqli_obj->stmt_init();
			$mysqli_stmt->prepare($sql);
			$mysqli_stmt->bind_param('i', $next_letter_no);
			$mysqli_stmt->execute();
			$meta = $mysqli_stmt->result_metadata();
			while ($field = $meta->fetch_field()) {
				$params[] = &$row[$field->name];
			}
			call_user_func_array(array($mysqli_stmt, 'bind_result'), $params);
			while ($mysqli_stmt->fetch()) {
				foreach($row as $key => $val) {
					$c[$key] = $val;
				}
				$prelim_result[] = $c;
			}
			$mysqli_stmt->free_result();
			foreach ($prelim_result as $arr) {
				foreach ($arr as $name => $value){
					$nextletter_results[$name] = $value;
				}
			}
			return $nextletter_results;
		}
		
		public function get_podcasts() {
			$letter_no = $this->letter_no;
			$mysqli_obj = $this->mysqli_obj;
			$sql = "SELECT podcast_ref FROM sevengates_podref WHERE letter_no = ?";
			$mysqli_stmt = $mysqli_obj->stmt_init();
			$mysqli_stmt->prepare($sql);
			$mysqli_stmt->bind_param('i', $letter_no);
			$mysqli_stmt->execute();
			$meta = $mysqli_stmt->result_metadata();
			while ($field = $meta->fetch_field()) {
				$params[] = &$row[$field->name];
			}
			call_user_func_array(array($mysqli_stmt, 'bind_result'), $params);
			while ($mysqli_stmt->fetch()) {
				foreach($row as $key => $val) {
					$c[$key] = $val;
				}
				$prelim_result[] = $c;
			}
			$i = 1;
			foreach ($prelim_result as $arr) {
				foreach ($arr as $name => $value) {
					$name = $name . '_' . $i;
					$podcasts[$name] = $value;
				}
				$i++;
			}
			$this->pc_total = count($podcasts);
			return $podcasts;
		}
		
		public function get_podcast_data($podcasts) {
			$mysqli_obj = $this->mysqli_obj;
			$this->podcasts = $podcasts;
			$prelim_result = [];
			$c = [];
			$row = [];
			$podcast_results = [];
			foreach ($podcasts as $name => $value) {
				$params = [];
				$mysqli_stmt = $mysqli_obj->stmt_init();
				$sql = "SELECT item_podtype, podcast_no_item, item_title, item_description, item_guid FROM rss2_podcast_item WHERE podcast_no_item = ?";
				$mysqli_stmt->prepare($sql);
				$mysqli_stmt->bind_param('i', $value);
				$mysqli_stmt->execute();
				$meta = $mysqli_stmt->result_metadata();
				while ($field = $meta->fetch_field()) {
					$params[] = &$row[$field->name];
				}
				call_user_func_array(array($mysqli_stmt, 'bind_result'), $params);
				while ($mysqli_stmt->fetch()) {
					foreach($row as $key => $val) {
						$c[$key] = $val;
					}
				}
				$prelim_result[] = $c;
				$mysqli_stmt->free_result();
			}
			foreach ($prelim_result as $arr) {
				foreach ($arr as $name => $value){
					$pc_result[$name] = $value;
				}
				$podcast_results[] = $pc_result;
			}
			return $podcast_results;
		}
	}

Roddy

Share this post


Link to post
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

×