Mysql
 sql >> Base de données >  >> RDS >> Mysql

Créer un système de newsletter avec PHP et MySQL

Aujourd'hui, nous allons construire un système de newsletter en utilisant PHP avec un arrière-plan MySQL. Le didacticiel couvrira la création d'un système permettant plusieurs listes de newsletters et l'envoi de messages à des listes spécifiques.

Hé les gars, nous allons donc construire un système de newsletter assez complexe, alors commençons ! Vous allez avoir besoin de deux ressources pour le projet.

  • L'ensemble d'icônes Silk sera utilisé pour ajouter une touche visuelle à l'application.
  • Le Swift PHP Mailer sera utilisé pour envoyer nos e-mails.

Étape 1 :Créer le squelette de l'application

Lorsque je démarre un projet, j'aime mettre en page les dossiers avant de commencer à coder, alors faisons-le maintenant. Tout d'abord, créez le répertoire global du projet. Ensuite, créez un dossier nommé admin dans votre dossier de projet. Ensuite, dans le dossier admin, ajoutez deux dossiers nommés media et swift. Enfin, créez un dossier nommé images dans le répertoire multimédia. En outre, vous pouvez placer le dossier Swift lib dans le dossier Swift que nous avons créé. Vous pouvez également copier les six icônes de soie que nous utiliserons :

  • bullet_green.png
  • bullet_red.png
  • supprimer.png
  • email_go.png
  • trouver.png
  • page_edit.png

Je vais structurer le reste du didacticiel sur la création du CRUD :créer, lire, mettre à jour et supprimer pour quatre de nos six modèles. Une autre sera modifiée par d'autres actions, et la sixième, nous ne créerons pas les actions CRUD.

Maintenant, créons d'abord notre base de données, et nos tables seront créées progressivement plus tard. Nous allons maintenant commencer à coder. De plus, à titre indicatif, je supposerai que nous travaillerons avec des fichiers dans notre dossier admin, sauf indication contraire, car la plupart du code se trouve dans ce dossier.

Étape 2 :Configuration de l'application

Chaque application aura un certain type de fichier de configuration, et nous allons créer le nôtre maintenant. Allez-y et créez un fichier nommé config.php et ajoutez ce qui suit :

# admin/config.php  

Ainsi, la première section configure nos variables de base de données, alors assurez-vous de la modifier afin qu'elle commence par votre configuration locale. Notre prochain texte de présentation définit certains attributs d'e-mail que nous utiliserons plus tard. La dernière section démarre notre session afin que nous puissions y accéder, nécessite notre fichier classes.php (nous le créerons en une seconde), définit les valeurs par défaut pour certaines options de mise en page, puis définit le rapport d'erreurs sur 0 pour arrêter les avertissements gênants . Cependant, si vous semblez avoir des problèmes, essayez de commenter cette ligne.

Maintenant, allez-y et créez notre fichier classes.php et ajoutez :

# admin/classes.php prepare($sql) or die('error'); $stmt->execute(); $meta =$stmt->result_metadata(); while ($field =$meta->fetch_field()) { $parameters[] =&$row[$field->name]; } $résultats =tableau(); call_user_func_array(array($stmt, 'bind_result'), $parameters); while ($stmt->fetch()) { foreach($row as $key => $val) { $x[$key] =$val; } $résultats[] =$x ; } retourne $résultats ; $résultats->fermer(); $lien->fermer(); } function count_query($query) { $link =new mysqli(DB_SERVER, DB_USER, DB_PASSWORD, DB_NAME) or die('Il y a eu un problème de connexion à la base de données.'); if($stmt =$link->prepare($query)) { $stmt->execute(); $stmt->bind_result($result); $stmt->fetch(); retourne $résultat ; $stmt->fermer(); } $lien->fermer(); } function check_username_and_pw($u, $pw) { $link =new mysqli(DB_SERVER, DB_USER, DB_PASSWORD, DB_NAME) or die('Il y a eu un problème de connexion à la base de données.'); $query ="SELECT * FROM utilisateurs WHERE username =? AND password =? LIMIT 1" ; if($stmt =$link->prepare($query)) { $p =md5($pw); $stmt->bind_param('ss', $u, $p); $stmt->execute(); $stmt->bind_result($id, $username, $pw); if($stmt->fetch()) { $_SESSION['authorized'] =true ; $_SESSION['nom d'utilisateur'] =$nom d'utilisateur ; retourner vrai ; } sinon { renvoie faux ; } $stmt->fermer(); } $lien->fermer(); } 

C'est un énorme morceau de code, et je vais le parcourir. Notre première fonction gère le moment où l'utilisateur publie notre connexion, puis envoie les données à notre fonction check_username_and_pw. Notre fonction connected_in renvoie simplement si un utilisateur est connecté. Notre fonction login_required vérifie si nous sommes connectés et, si ce n'est pas le cas, nous renvoie à la page de connexion.

La fonction suivante nommée simplement query() effectue une requête sur notre base de données et a été créée par Jeffrey Way. J'ai ajouté les fonctions de création de lien et de fermeture pour le rendre encore plus facile. Notre prochaine fonction que j'ai créée spécialement pour que nous puissions exécuter facilement COUNT requêtes SQL, et notre fonction check_username_and_pw vérifie si nous pouvons trouver un utilisateur avec le même e-mail et le même mot de passe haché MD5, et si c'est le cas, définit nos variables de session.

Étape 3 :Mise en page de l'application

Notre prochain fichier sur lequel nous allons travailler est notre fichier layout.php, alors allez-y et créez-le. Dans notre section principale, nous déclarons simplement nos déclarations XHTML habituelles. Si vous le remarquez, nous ajoutons automatiquement le titre de la page à une autre chaîne pour notre titre. Ensuite, nous avons une feuille de style (allez-y et créez-la également dans notre dossier multimédia). Après quoi, nous ouvrons notre balise body et vérifions si nous voulons une mini mise en page, et si c'est le cas, ajoutons une classe. Ensuite, nous avons notre en-tête, puis vérifions si nous voulons notre navigation, et si nous le faisons, nous montrons nos onglets. J'ai également ajouté un moyen d'ajouter une classe actuelle pour chaque onglet. Nous avons également un lien de déconnexion, puis notre conteneur div. En cela, nous ajoutons une balise h3 avec notre titre, puis faisons écho à notre contenu.

# admin/layout.php      » mon application de newsletter     class="mini"> 
  
  

Maintenant, nous allons créer notre page index.php juste pour pouvoir styliser. Ouvrez index.php et ajoutez :

# admin/index.php statistiques actuelles Notre page d'accueil ! EOF ; inclure 'layout.php' ; ?>

Donc, dans ce cas, nous avons besoin de notre fichier de configuration, configurons notre titre, puis configurons notre variable de contenu, puis nous avons besoin en dernier de notre fichier de mise en page. Lorsque vous l'ouvrez pour la première fois, il devrait ressembler à :

Ouvrez maintenant notre feuille de style. J'aime utiliser les styles de réinitialisation et de typographie 960.gs, compressés dans TextMate. Ainsi, le haut de mon fichier CSS ressemble à :

# admin/media/style.css /* reset */ html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a, abbr,acronyme,adresse,gros,cite,code,del,dfn,em,police,img,ins,kbd,q,s,samp,strike,strong,sub,sup,tt,var,b,u,i, center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0; contour:0;font-size:100%;vertical-align:baseline;background:transparent}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before ,blockquote:after,q:before,q:after{content:'';content:none}:focus{outline:0}ins{text-decoration:none}del{text-decoration:line-through}table{border -collapse:collapse;border-spacing:0} /* typographie */ body{font:13px/1.5 Helvetica,Arial,'Liberation Sans',FreeSans,sans-serif}a:focus{outline:1px dotted invert}hr{ border:0 #ccc solid;border-top-width:1px;clear:both;height:0}h1{font-size:25px}h2{font-size:23px}h3{font-size:21px}h4{font -size:19px}h5{font-size:17px}h6{font-size:15px}ol{list-style:de cimal}ul{list-style:square}li{margin-left:30px}p,dl,hr,h1,h2,h3,h4,h5,h6,ol,ul,pre,table,address,fieldset{margin :10px 0;}

Commençons par styliser nos éléments principaux, ajoutez donc les styles suivants :

# admin/media/style.css #header {width :85 % ; margin:0 auto;} #header h1 a {text-decoration:none; color:#000;} #container {width:85%; arrière-plan :#111 ; marge :5px automatique ; couleur :#fff ; rembourrage :10 px ; }

Maintenant, votre page devrait ressembler à :

Maintenant, si nous stylisons les onglets avec un arrière-plan de navigation, puis un arrière-plan de survol sur chacun des liens, vous devriez voir :

# admin/media/style.css /* tabs */ #nav {margin:0 auto 2px;padding:10px;width:85%; background:#444;} #nav a { rembourrage:12px 10px; marge :0 ; couleur :#fff ; décoration de texte :aucune ; text-align:center;} #nav a.current, #nav a:hover {background:#111;} #nav span.right {float:right;}

Maintenant, pendant que nous travaillons sur le fichier, continuez et ajoutez les styles suivants pour notre mini mise en page, les entrées de formulaire, les tableaux, les liens volumineux et nos messages d'erreur et de réussite.

# admin/media/style.css body.mini #header {width :30 % ; text-align:center;} body.mini #container {width:30%;} /* form */ form input.text {width:95%; font-size:16px;} form textarea {width:95%; hauteur:100%;} /* tableau */ tableau {largeur:98%; aligner le texte :à droite ; bordure:rgb(128,128,128); taille de police :12 px ; marge :5px 10px ; color:#000;background:#fff;} table th {background-color:rgb(229, 229, 229); bordure :1px solide RVB (187, 187, 187); rembourrage :3px 6px ; font-weight:normal; color:#000;} table tr td {border :1px solid rgb(221, 221, 221); padding:3px 6px;} table tr:hover {background-color:rgb(240, 240, 240);color:#000;} /* a */ a.large {padding:5px; couleur :#000 ; arrière-plan :#eee ; décoration de texte :aucune ; margin:5px;} a.large.right {float:right;} a.large:hover, a.large.current {background:#444; color:#fff;} /* messages */ #message {margin :5px 10px ; rembourrage :4px; display:block;text-align:center;} #message.error {background:#FFEBE8;border:1px solid #CC0000;color:#CC0000;} #message.success {border:solid 1px #349534; fond :#C9FFCA;couleur :#008000;}

Ce sont des styles que j'aime utiliser dans tous mes projets. Maintenant que nous avons terminé la mise en page, nous allons passer à l'authentification.

Étape 4 :Authentification

Nous allons travailler avec un système d'authentification très simple. Créez un login.php et placez ce qui suit à l'intérieur :

# admin/login.php  



EOF ; inclure 'layout.php' ; ?>

Je vais vous expliquer chaque partie du code. Nous avons d'abord besoin de notre fichier de configuration. Ensuite, nous vérifions si nous sommes connectés, et si nous le sommes, nous redirigeons vers la maison. Ensuite, nous définissons le titre et nos options de mise en page. Ensuite, nous vérifions si nous avons un POST et si le POST avait un nom d'utilisateur et un mot de passe, et si c'est le cas, nous appelons la fonction validate_user à partir de notre fichier de classes. Nous définissons ensuite la variable error sur nos erreurs de session, puis nous configurons notre formulaire et affichons toutes les erreurs. Nous allons maintenant créer notre page de déconnexion, alors créez logout.php et mettez-y ce qui suit :

# admin/logout.php 

Nous avons à nouveau besoin de notre fichier de configuration, définissons notre session sur un tableau vide, puis détruisons notre session et redirigeons vers notre page de connexion. Maintenant que vous avez fait tout cela, votre page de connexion devrait ressembler à :

Nous allons également créer un enregistrement d'utilisateur (et notre table) afin que nous puissions ajouter la logique d'authentification et que vous puissiez afficher les pages avec le code à venir. Créer un utilisateur avec le nom d'utilisateur d'admin et un mot de passe de secret. Pour ajouter ceci, exécutez ce SQL :

CREATE TABLE `users` ( ​​`id` int(10) AUTO_INCREMENT, `username` varchar(50), `password` varchar(32), PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET utf8; INSERT INTO `users` (`id`, `username`, `password`) VALUES ('1', 'admin', '5ebe2294ecd0e0f08eab7690d2a6ee69');

Étape 5 :Newsletters

J'ai conçu cette application pour qu'elle soit très flexible. Je voulais que vous (l'utilisateur) puissiez créer et gérer autant de newsletters que vous le souhaitez. Donc, d'abord, nous devons créer notre table de base de données. Voici le code SQL de l'export sur mon application de démonstration :

 CREATE TABLE `newsletters` ( ​​`id` int(10) AUTO_INCREMENT, `name` varchar(50), `description` varchar(255), `visible` varchar(10), PRIMARY KEY (`id`) ) ENGINE=Jeu de caractères par défaut MyISAM utf8 ;

Alors maintenant que nous avons notre tableau des newsletters, nous allons créer les pages pour chaque action. Créez quatre fichiers nommés :newsletters.php, newsletters_delete.php, newsletters_edit.php et newsletters_new.php. Ouvrez d'abord newsletters.php :

# admin/newsletters.php supprimer
' ; $elink ='modifier 
' ; if($row['visible'] =="1") {$visible ='';} else {$visible ='';} $table .="".$row['id']."".$row['name'] ."".$row['description']."$visible".$dlink." ".$elink."\n" ; } $message =message_erreur(); $content =<<nouvelle newsletter »
 $message  $table 
nom description visible
EOF ; inclure 'layout.php' ; ?>

Donc, ce fichier a la même sensation de base que notre page de connexion. Nous avons besoin de notre configuration, assurez-vous que nous sommes connectés, définissez notre titre. Ensuite, nous utilisons notre fonction query() pour effectuer une requête SELECT afin de trouver toutes nos newsletters. Nous définissons ensuite l'onglet actuel pour notre mise en page. Après avoir parcouru le tableau renvoyé par notre requête et créé la disposition de la table. Ensuite, nous appelons une fonction encore inconnue et créons notre page. Avant de pouvoir afficher la page, vous devrez ajouter ce qui suit à votre fichier classes.php pour gérer facilement nos messages d'erreur :

# admin/classes.php // Affiche les messages d'erreur function error_messages() { $message =''; if($_SESSION['success'] !='') { $message =''.$_SESSION['success'].''; $_SESSION['succès'] =''; } if($_SESSION['error'] !='') { $message =''.$_SESSION['error'].''; $_SESSION['error'] =''; } renvoie $message ; } 

Bien que vous n'ayez probablement aucune donnée, lorsque vous aurez quelques enregistrements, cela ressemblera à :(bien qu'un peu moins écrasé)

Nous allons maintenant travailler sur notre nouvelle action, alors ouvrez newsletters_new.php et ajoutez ce qui suit :

# admin/newsletters_new.php query($sql) or die($link->error); $stmt->fermer ; $_SESSION['success'] ="Newsletter ajoutée."; header('Emplacement :newsletters.php'); } $title ="nouvelle newsletter" ; $content =<< 


EOF ; inclure 'layout.php' ; ?>

J'espère donc que vous avez remarqué le motif en haut de chacun de nos fichiers. Nous avons d'abord besoin de notre fichier config.php, puis nous nous assurons que nous sommes connectés, puis définissons notre onglet actuel, puis nous ajoutons une logique supplémentaire pour gérer les POST, puis nous définissons notre titre, notre contenu, puis rendons la page. La section POST est assez simple à comprendre donc je vais l'expliquer rapidement.

Nous vérifions d'abord si un élément avec le nom de soumis a été envoyé. C'est le champ caché que nous avons après le bouton d'envoi. Ensuite, nous créons un lien vers notre base de données en utilisant les variables de notre fichier de configuration. Ensuite, nous créons notre requête d'insertion SQL, en utilisant nos variables POSTées. Ensuite, nous interrogeons (pas notre fonction) la base de données, et si une erreur est générée, nous affichons l'erreur renvoyée. Ensuite, nous fermons la requête, puis nous définissons notre message de réussite, puis nous redirigeons vers la page de liste. Votre page devrait ressembler à :

Ensuite, nous allons travailler sur notre page d'édition et ajouter ce qui suit :

# admin/newsletters_edit.php query($sql) or die($link->error); $stmt->fermer ; $_SESSION['success'] ="Newsletter édité."; header('Emplacement :newsletters.php'); } $title ="modifier la newsletter" ; $id =(entier) $_GET['id'] ; $results =query("SELECT * FROM newsletters WHERE id='".$id."' LIMIT 1"); $nom =$resultats[0]['nom'] ; $description =$resultats[0]['description'] ; $visible =($results[0]['visible'] =="1") ? 'coché="coché"' :''; $content =<< 


='hidden' value='$id' name='id' />

EOF ; inclure 'layout.php' ; ?>

Comme tous nos fichiers, nous commençons avec le même bloc. Après notre bloc POST (dont je parlerai dans une seconde), nous définissons id sur notre identifiant demandé, en nous assurant qu'il s'agit d'un entier. Nous utilisons ensuite notre fonction de requête pour trouver la newsletter avec laquelle nous travaillons et définissons quelques variables sur les résultats renvoyés. Vous pouvez demander pourquoi nous avons mis un [0] avant de demander chaque valeur, et la raison est que la fonction de requête renvoie un tableau de tous les enregistrements, et chaque enregistrement est un tableau, nous devons donc accéder au premier tableau dans notre variable de résultats . La ligne où nous définissons la variable visible ifs est en fait une instruction if/else compressée. la partie if est le ==1, alors si c'est vrai, la variable est définie sur cochée, sinon sur rien. Ensuite, nous avons notre formulaire.

Notre bloc POST est très similaire à notre nouvelle page et commencera toujours de la même manière sur le reste de nos pages. Nous vérifions ensuite si la case à cocher était cochée et définissons à nouveau une variable ici. Ensuite, nous avons notre requête UPDATE, exécutons à nouveau la requête, définissons notre message de réussite, puis redirigeons vers la maison. Voici à quoi ressemble le formulaire et le message affiché après modification :

La dernière page de cette section est la plus facile, car c'est la page de suppression. Ouvrez le fichier et collez-le comme suit :

# admin/newsletters_delete.php query($sql) or die($link->error); if($link->affected_rows) { $_SESSION['success'] ="Newsletter supprimée."; } else { $_SESSION['error'] ='Rien supprimé.'; } header('Emplacement :newsletters.php');

Dans ce bloc, nous avons besoin de notre configuration, assurez-vous que nous sommes connectés, puis enregistrez l'identifiant demandé dans une variable, créez une connexion MySQL, configurez notre requête SQL, puis exécutez la requête. Nous vérifions ensuite si une ligne a été affectée et définissons un message de manière appropriée. Nous redirigeons ensuite vers la page des newsletters. Félicitations, vous avez terminé la première des quatre sections CRUD. Ensuite, nous allons travailler sur le CRUD pour nos templates.

Étape 6 :Modèles

Notre application permettra également plusieurs modèles, tous stockés dans la base de données. Tout d'abord, créons notre table de base de données :

 CREATE TABLE `templates` ( `id` int(10) AUTO_INCREMENT, `name` varchar(50), `columns` tinyint(5), `body` text, PRIMARY KEY (`id`) ) ENGINE=MyISAM CHARET PAR DÉFAUT utf8 ;

Nous avons une colonne d'identification à incrémentation automatique, une colonne de nom, une colonne de colonnes pour enregistrer le nombre de colonnes (l'application ne s'adapte qu'à 2 colonnes, ce qui devrait être suffisant, mais peut facilement être étendu. Cela pourrait également être utilisé pour différentes sections .), et notre corps. Comme la dernière fois, nous devons créer chacune de nos pages, et nous aurons une page templates.php, ainsi que templates_new.php, templates_edit.php, templates_delete.php et templates_preview.php. Nous allons d'abord travailler sur notre fichier templates.php, alors ouvrez-le et collez :

# admin/templates.php aperçu
' ; $dlink ='supprimer
' ; $elink ='edit 
' ; $table .="".$ligne['id']."".$ligne['nom']."".$ ligne['colonnes']."".$plink." ".$dlink." ".$elink."\n" ; } $message =message_erreur(); $content =<<nouveau modèle »
 $message  $table 
nom colonnes
EOF ; inclure 'layout.php' ; ?>

Encore une fois, nous commençons par les bases. Nous préformons ensuite une requête pour trouver tous nos modèles. Nous parcourons ensuite chaque tableau dans des modèles et nous créons une table. Nous recevons ensuite nos messages d'erreur (et de réussite), puis notre contenu. Votre page devrait ressembler à :

Maintenant, en passant à notre nouvelle page, collez ce qui suit :

# admin/templates_new.php query($sql) or die($link->error); $stmt->fermer ; $_SESSION['success'] ="Modèle ajouté."; header('Emplacement :templates.php'); } $title ="nouveau modèle" ; $content =<< 



Utilisez %content% pour une mise en page à une seule colonne, %leftcol% et %rightcol% pour une mise en page à deux colonnes.

EOF ; inclure 'layout.php' ; ?>

Donc, encore une fois, nous avons notre même en-tête. Notre POST crée à nouveau une connexion MySQL, puis nous créons notre requête et utilisons mysql_real_escape_string pour autoriser tous les caractères dans l'enregistrement, puis nous exécutons notre requête, définissons notre message de réussite et redirigeons vers notre liste de modèles. Si vous regardez notre formulaire, je demande également que des variables soient insérées pour notre contenu, et je vous montrerai comment cela entre en jeu plus tard lorsque nous associons un message à un modèle. Votre page devrait ressembler à :

Ensuite, nous allons travailler sur notre page d'édition. Si vous l'avez remarqué, une grande partie de ce code est copiée et collée dans toutes les mêmes actions, alors simplifiez-vous la tâche.

# admin/templates/edit.php query($sql) or die($link->error); $stmt->fermer ; $_SESSION['success'] ="Modèle modifié."; header('Emplacement :templates.php'); } $title ="modifier le modèle" ; $id =(entier) $_GET['id'] ; $results =query("SELECT * FROM templates WHERE id='".$id."' LIMIT 1"); $nom =$resultats[0]['nom'] ; $templatedata =stripslashes(htmlspecialchars($results[0]['body'])); $content =<< 



Use %content% for a single column layout, %leftcol% and %rightcol% for a two column layout.

EOF; include 'layout.php'; ?>

We start with the same intro, then our POST block, our title, then our requested id. After, we try and find the template we are working with, then sets three variables so that we can inset them into our content block. We also convert all of the tags we stored to HTML characters so everything will display. When looking at our POST block, you will notice we create our link, then our query and again use mysql_real_escape_string to save everything, execute our query, and then set our message, and redirect to our templates list. Your edit page (with a sample record) should look like:

Now we will create another delete page, so open up our delete page and paste in:

# admin/templates_delete.php query($sql) or die($link->error); if($link->affected_rows) { $_SESSION['success'] ="Template deleted."; } else { $_SESSION['error'] ='Nothing deleted.'; } header('Location:templates.php');

I hope you have picked up the pattern here, this is a very simple page. Now we are going to work on an extra page that is not part of the CRUD spectrum; we are going to create a preview page. The binoculars in the action part on the table is the link for each one (in a new window). So open up our preview page. The page is very simple, we find our template and echo the data, and then append a javascript close button. The code looks like:

# admin/templates_preview.php   

And an example preview looks like:

Now we have finished with our Templates, we are ready to move onto the next step!

Step 7:Subscribers

So now we are going to work with our subscribers! We are going to create two tables. The first:

CREATE TABLE `subscribers` ( `id` tinyint(10) AUTO_INCREMENT, `name` varchar(50), `email` varchar(50), PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET utf8;

Refers to each subscriber, and the second:

CREATE TABLE `subscriptions` ( `id` tinyint(10) AUTO_INCREMENT, `subscriber_id` tinyint(10), `newsletter_id` tinyint(10), PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET utf8;

Creates a table for our many-to-many relationship with our newsletters. A subscriber can have multiple subscription to newsletters, so they can subscribe to multiple ones, and each newsletter can have many subscribers. To create the most dynamic solution, we have a linking table.

Let's first create our files. The files we are going are going to have are subscribers.php, subscribers_delete.php, and subscribers_edit.php. Our create action will be created later for the front-end. First open up subscribers.php and paste in:

# admin/subscribers.php delete
'; $elink ='edit
'; $table .=''.$row['id'].''.$row['name'].''.$row['email'].''.$dlink.' '.$elink.''; } $message =error_messages(); $content =<<   name email   $table  EOF; include 'layout.php'; ?>

We have basically the same listing pages as before, except this time we will be finding our subscribers. Your page (with some sample data) should look like:

Now we will move on to our edit page:

# admin/subscribers_edit.php query($sql) or die($link->error); $stmt->close; foreach($_POST['newsletter'] as $n) { if($n['exists'] !='1' &&$n['subscribe'] =="true") { // If we want to subscribe but the record doesnt exist $nlid =$n['nlid']; $sql ="INSERT INTO subscriptions (subscriber_id, newsletter_id) VALUES ('$id', '$nlid')"; $stmt =$link->query($sql) or die($link->error); $stmt->close; } elseif ($n['exists'] =='1' &&$n['subscribe'] !="true") {// Else if we had an exits but we want to unsubscribe $subid =$n['subid']; $sql ="DELETE FROM subscriptions WHERE id=$subid LIMIT 1"; $stmt =$link->query($sql) or die($link->error); $stmt->close; } } $_SESSION['success'] ="Edited subscriber."; header('Location:subscribers.php'); } $title ="edit newsletter"; $id =(int) $_GET['id']; $subscriber =query("SELECT * FROM subscribers WHERE id='$id'"); $name =$subscriber[0]['name']; $email =$subscriber[0]['email']; $newsletters =query("SELECT * FROM newsletters"); $subs =query("SELECT * FROM subscriptions WHERE subscriber_id='".$id."'"); $subscriptions =''; foreach($newsletters as $nl) { $s =false; $subid =''; foreach($subs as $sub) { if($sub['newsletter_id'] ==$nl['id']) {$s =true; $subid =$sub['id'];} } $checked =($s ==true) ? 'checked="checked"' :''; $subscriptions .='     
'; } $content =<<



Newsletters:
$subscriptions

EOF; include 'layout.php'; ?>

This page is fairly different so I will explain each part. The header is the same we have been using. I'll skip the POST block and come back to it. We then continue the same code. We next find our current subscriber. Next we find all newsletters (this includes ones that are not visible - visible mean visible to the public) and then all of the subscriber's subscriptions. We next loop through every newsletter record returned, we next reset some values. Next, we loop through every subscription the user has, and if the subscription's newsletter_id is equal to the current newsletter we are looping we set $s true, and $subid equal to the subscription id. We then set the variable $checked equal to either checked or nothing depending on whether a subscription was found for this subscriber and the current newsletter in the loop. Next we create the checkbox form area, with a lot of hidden fields. First, we have the actual checkbox with a name that will create an array for each checkbox. We then have our label, and next we output whether or not the subscription exists, the newsletter_id and then the subscription_id for when the subscription exists. After which we have our normal content.

Now, if we move on to our POST block. We first get the id posted from our hidden field at the bottom. We next create our MySQL link. Next we have our first SQL query where we update the subscriber record. Next we loop through every newsletter checkbox. The first conditional statement checks to see if the POSTed data says we do not have an existing subscription, and the user wants to subscribe to the newsletter. To handle this, we are going to perform a SQL INSERT into our subscriptions table where our subscriber_id is the same as the user_id we are editing, and newsletter_id equal to the 'nlid' value POSTed by one of our hidden fields. We then execute that SQL INSERT query. The elseif conditional statement says that if our subscription exists, but the checkbox was unchecked so we unsubscribe, we need to delete the subscription. We handle this with a SQL DELETE query. To form our query we set $subid equal to the posted value for our 'subid'. We then create our query by deleting the record where the subscription id equals our variable of $subid. Next we execute the query, set our session success message, and then redirect back to our subscribers page. Your final edit page should look like:(filled with sample data)

We have one last page to work on for the subscribers part of the backend:the delete page. Just like before, this page is very simple:

# admin/subscribers_delete.php query($sql) or die($link->error); if($link->affected_rows) { $_SESSION['success'] ="Subscriber deleted."; } else { $_SESSION['error'] ='Nothing deleted.'; } header('Location:subscribers.php');

Step 8:Messages

I will tell you upfront, this section has the most pages. We will be working with seven now, and creating one more in Step 10. First, we are going to create our messages table with this SQL:

CREATE TABLE `messages` ( `id` tinyint(10) AUTO_INCREMENT, `subject` varchar(255), `leftcol` text, `rightcol` text, `template_id` tinyint(10), PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET utf8;

Next, we'll create the files for this step. Creates seven files, each named messages.php, messages_delete.php, messages_edit.php, messages_new.php, messages_new_step2.php, messages_new_step3.php, and messages_preview.php. Let's first open up messages.php and make it look like:

# admin/messages.php send message
'; $plink ='preview
'; $dlink ='delete
'; $elink ='edit
'; $table .=''.$row['id'].''.$row['subject'].'preview
'.$slink.' '.$plink.' '.$dlink.' '.$elink.''; } $message =error_messages(); $content =<<new message »
 $message  $table 
subject template
EOF; include 'layout.php'; ?>

This is our routine table, except we now have 4 'extra' links now, one to send the message, one to preview, one to edit, and one to delete. Your page should look like:

Now we are going to start work on our new pages. The first page is where all messages start out, and then you can progress on and enter the actual message on the next page. The reason for this is because we first need to create the initial message in the DB and so we can find information about the template. The step2 page is basically the edit page (there are six line differences according to FileMerge). Open up our new file and paste the following:

# admin/messages_new.php query($sql) or die($link->error); $i =query("SELECT id FROM messages WHERE subject='".$_POST['subject']."' AND template_id=".$_POST['template']." "); $id =$i[0]['id']; $stmt->close; $_SESSION['success'] ="Added template."; header('Location:messages_new_step2.php?id=' + $id); } $title ="new message"; $templates =query("SELECT id,name,columns FROM templates"); $tselect ='"; $content =<< 


$tselect

EOF; include 'layout.php'; ?>

This page is very similar to what our other new pages look like, but this one was one change in the POST block. Right after we perform the SQL INSERT, we find the most recent insert id. Now this is not the perfect solution, but I prefer it to performing another SQL query to find a row using unindexed columns. This step should look like:

We then redirect to step2, so let's open up the file:

# admin/messages_new_step2.php '; foreach($templates as $row) { if($message['template_id'] ==$row['id']) { $selected =' selected="selected"'; if($row['columns'] =="1") { $textareas ='


'; } else { $textareas ='



'; } } else {$selected ='';} $tselect .=''; } $tselect .=''; // Check for a POST if(isset($_POST['submitted'])) { $link =new mysqli(DB_SERVER, DB_USER, DB_PASSWORD, DB_NAME) or die('There was a problem connecting to the database.'); $template =query("SELECT columns FROM templates WHERE id=".$message['template_id']); if($template[0]['columns'] =="1") { $body =mysql_real_escape_string($_POST['body']); $sql ="UPDATE messages SET subject='".$_POST['subject']."', leftcol='$body' WHERE id=$id"; } else { $leftcol =mysql_real_escape_string($_POST['leftcol']); $rightcol =htmlentities($_POST['rightcol']); $sql ="UPDATE messages SET subject='".$_POST['subject']."', leftcol='$leftcol', rightcol='$rightcol' WHERE id=$id"; } $stmt =$link->query($sql) or die($link->error); $stmt->close; header('Location:messages_new_step3.php?id='.$id); } $content =<<


$tselect

$textareas

EOF; include 'layout.php'; ?>

Hopefully you have gotten the gist of all the pages and understand the page above. We have our normal heading. we then set our id from our GET request. Next we find the message we are working with, then we find all the templates and construct a drop down. We also use this look to define whether we will have one or two textareas. Next we have our POST block, which creates the link, then checks to see if we are working with one or two columns and creates the appropriate SQL query. After that we have our form. Your form should look like:

Now we will continue onto step 3, so open up the file and paste:

# admin/messages_new_step3.php preview »

Do you want to return to messages or send the message ?

EOF; include 'layout.php'; ?>

The page is very simple and is the end of creating a message. It offers us a few links. The first is a link to preview the message. The next offers to take us back home. The third offers to take us to send the message (Step 10). The page looks like:

Now we are going to continue on to our edit page. I will not explain it as it is the same file as messages_new_step2.php, so you can refer there.

# admin/messages_edit.php '; foreach($templates as $row) { if($message['template_id'] ==$row['id']) { $selected =' selected="selected"'; } else {$selected ='';} $tselect .=''; } $tselect .=''; $mid =$message['template_id']; $template =query("SELECT id,name,columns FROM templates WHERE id=$mid"); if($template[0]['columns'] =="1") { $textareas ='


'; } else { $textareas ='



'; } // Check for a POST if(isset($_POST['submitted'])) { $link =new mysqli(DB_SERVER, DB_USER, DB_PASSWORD, DB_NAME) or die('There was a problem connecting to the database.'); if($template[0]['columns'] =="1") { $body =mysql_real_escape_string($_POST['body']); $sql ="UPDATE messages SET subject='".$_POST['subject']."', leftcol='$body' WHERE id=$id"; } else { $leftcol =mysql_real_escape_string($_POST['leftcol']); $rightcol =htmlentities($_POST['rightcol']); $sql ="UPDATE messages SET subject='".$_POST['subject']."', leftcol='$leftcol', rightcol='$rightcol' WHERE id=$id"; } $stmt =$link->query($sql) or die($link->error); $stmt->close; $_SESSION['success'] ="Edited message."; header('Location:messages.php'); } $content =<<


$tselect

$textareas

EOF; include 'layout.php'; ?>

The page will look almost identical to our step 2, but the textarea will have content. Now we will create the delete page with:

# admin/messages_delete.php query($sql) or die($link->error); if($link->affected_rows) { $_SESSION['success'] ="Message deleted."; } else { $_SESSION['error'] ='Nothing deleted.'; } header('Location:messages.php'); ?>

That page should also look familiar. The final page we are going to work on in this step is our preview page, so open it up and place:

# admin/messages_preview.php   

This file is somewhat different than you have seen, so I'll walk you through it. First have have our normal heading. Next we find the current message we are working with, and set a few variables to the results. Next we find the template we are working with and set a variable equal to the body. Next, we have a conditional statement that checks to see the number of columns the template has. If it has we use the PHP function str_replace to replace the %content% tag we have with our actual content. Otherwise, we first perform a str_replace for the left column, and then on the result of that we perform str_replace again for the right column. Now we are ready to continue onto the front-end.

Step 9:The Front-End

We have finally reached the front-end! For this step and this step only, I will assume the files we are working with are in the root of the project (so not the admin folder, the one containing it). We are going to be working with four files here, so go ahead and create index.php, preferences.php, subscribe.php and a style.css file. First open up our index.php file and paste:

# index.php   
'.$nl["description"].'
'; } ?> my newsletters

Subscribe to our newsletters!



Newsletters:

I'll explain the page first and then we will get to the picture so-far and the page styling. In the PHP section at the top we require our config.php file (now in the admin directory), then find all of our publicly visible newsletters and create a check box array. You will notice that we are not handling the POSTed data here, and I chose to do that in our subscribe.php, and we will get to that, but first let's style the page. The page should currently look like:

First I added the 960.gs reset file like I did in our other stylesheet. Then I added the three following styles to make the design look like:

# style.css #header, #container {width:65%;margin:0 auto; padding:0.7%;} #container {background:#ccc;} form input.text {width:95%; font-size:16px;} #message.success {border:solid 1px #349534; background:#C9FFCA;color:#008000;}

So now that we have a clean and simple page, we are going to continue on and work on our subscribe.php file. Go ahead and open the file and paste:

# subscribe.php query($sql) or die($link->error); $stmt->close; $sql ="SELECT id FROM subscribers WHERE name='$name' AND email='$email' LIMIT 1"; $subscriber =query($sql); $id =$subscriber[0]['id']; foreach($_POST['newsletter'] as $n) { if($n['subscribe'] =="true") { // If we want to subscribe but the record doesnt exist $nlid =$n['nlid']; $sql ="INSERT INTO subscriptions (subscriber_id, newsletter_id) VALUES ('$id', '$nlid')"; $stmt =$link->query($sql) or die($link->error); $stmt->close; } } } else {header('Location:index.php');} ?>     my newsletters     
 

Thank you for subscribing!

This page is very much like our edit subscribers page, but no DELETE SQL queries happen here. We simply check to make sure we have all POSTed data. We then set a few variables to our POSTed data, and then create and perform a SQL INSERT query to add the person to our subscribers table. After which we perform a SQL query to find that just created subscriber (insert_id was not working this time for me). We then loop through all of the POSTed newsletters and check to see if we want to subscribe to them, and perform SQL INSERTs when needed. If all goes to plan, you see a nice screen like the one below:

We have on last page here to work on, and that is the preferences.php file. This is where a user can edit their email subscription. I am going to split the page in two. First we have our PHP block:

# preferences.php query($sql) or die($link->error); $stmt->close; foreach($_POST['newsletter'] as $n) { if($n['exists'] !='1' &&$n['subscribe'] =="true") { // If we want to subscribe but the record doesnt exist $nlid =$n['nlid']; $sql ="INSERT INTO subscriptions (subscriber_id, newsletter_id) VALUES ('$id', '$nlid')"; $stmt =$link->query($sql) or die($link->error); $stmt->close; } elseif ($n['exists'] =='1' &&$n['subscribe'] !="true") {// Else if we had an exits but we want to unsubscribe $subid =$n['subid']; $sql ="DELETE FROM subscriptions WHERE id=$subid LIMIT 1"; $stmt =$link->query($sql) or die($link->error); $stmt->close; } } $_SESSION['success'] ="Preferences saved."; } if(isset($_GET['email'])) {$email =$_GET['email']; $display ='form';} else {$display ='find';} $subscriber =query("SELECT * FROM subscribers WHERE email='$email'"); if($subscriber || $display =='find') { $id =$subscriber[0]['id']; $name =$subscriber[0]['name']; $email =$subscriber[0]['email']; } else {header('Location:index.php');} $newsletters =query("SELECT * FROM newsletters WHERE visible=1"); $subs =query("SELECT * FROM subscriptions WHERE subscriber_id='".$id."'"); $subscriptions =''; foreach($newsletters as $nl) { $s =false; $subid =''; foreach($subs as $sub) { if($sub['newsletter_id'] ==$nl['id']) {$s =true; $subid =$sub['id'];} } $checked =($s ==true) ? 'checked="checked"' :''; $subscriptions .='     
'; } $message =error_messages(); ?>

In this block, a lot is going on. First, we include our config file. Next, we check for a POST, and if we have one, we update our database. This portion is copied exactly from our subscribers_edit.php file so you can look there for a bit more explanation. Next depending on if we have a get request, we set our variable (this variable is used in the HTML section of the page). We then look for a subscriber with that email, and if one exists or we are showing the find portion, we continue, otherwise we are redirected home. Next we find all of our newsletters, and all of the subscriber's subscriptions, and then create our checkbox form. The HTML portion looks like:

# preferences.php     my newsletters - my preferences     
 

my preferences



Newsletters:


In our HTML block we have two forms and some PHP to choose which one to display. The top form is the form the user sees if a record in the database has been found. The second form is for entering your email and having the system find it. The second form looks like:

And the first looks like:

And the second form after we saved our preferences:

Now that we have finished the front-end, we have one last step:sending the emails!

Step 10:Sending Messages

Our last step is to work on the page to send our message. We will be working in the admin directory, and only one file will be created. Go ahead and create our messages_send.php file and place the following in it:

# admin/messages_send.php  FROM_NAME); // BODY RENDERING $mess =query("SELECT * FROM messages WHERE id=$id"); $message =$mess[0]; $subject =$message['subject']; $tid =$message['template_id']; $data =query("SELECT body FROM templates WHERE id=$tid LIMIT 1"); $template =$data[0]['body']; if($message['rightcol'] =='') { $leftcol =$message['leftcol']; $body =str_replace('%content%', $leftcol, $template); } else { $leftcol =$message['leftcol']; $rightcol =$message['rightcol']; $b =str_replace('%leftcol%', $leftcol, $template); $body =str_replace('%rightcol%', $rightcol, $b); } send_email_to_mass($from, $emails, $body, $subject) or die('lol'); header('Location:index.php'); } $newsletters =query("SELECT * FROM newsletters"); foreach($newsletters as $nl) { $nls .='    - '.$nl['description'].'
'; } $mess =query("SELECT * FROM messages WHERE id=$id"); $message =$mess[0]; $subject =$message['subject']; $content =<<preview »

Subject:$subject

Send to:
$nls

EOF; include 'layout.php'; ?>

The first part we again require our config, then make sure the user is logged in, then our title, make sure our id is an integer, and then set our tab. Next we have our complicated post block. First we set up our base query, and running just that would return 0 records, which is good because that means no users will be send the newsletter. Next we loop through every newsletter that we want to send to, and find all of the subscriptions for that newsletter. We then create a string that will be appended to our original SQL query so that we can find every subscriber. Now, we run that query and create an array where the keys are the emails and the name is the value, and this helps us use names when the user looks at the email in their mail application, showing the TO:as their name. We next find the message we are working with, and set the subject, message, and template id to variables. We then find our template and set the body to a variable. Then we use the same code from the message preview to replace the strings inside the template the the parts of the message. Then we call our yet-to-be-created-function send_email_to_mass and then redirect home.

Leaving our POST block, we create the same checkbox list of newsletters so the admin can pick which one(s) he wants to send the message to. Then we have a simple form that looks like:

Now, open up our classes.php file and add the following function:

# admin/classes.php // EMAIL function send_email_to_mass($from, $recipients, $body, $subject) { require_once 'swift/lib/swift_required.php'; //require lib $transport =Swift_MailTransport::newInstance(); $mailer =Swift_Mailer::newInstance($transport) or die('Error creating mailer.'); $message =Swift_Message::newInstance($subject) ->setFrom($from) ->setTo($recipients) ->setBody($body, 'text/html') or die('error here.'); $result =$mailer->batchSend($message); retourner vrai ; } 

So first, we have our function declaration, and it expects four variables to be passed to it, from, recipients, body, and subject. Next we require the sqift_required.php file of our Swift Mailer Library. Next we create a new Mail Transport (this uses the PHP mail function, so it would be sending from your local machine, for the documentation on the three transport types, see the documentation). Next we create a mailer using that transport. Then we create a new message from our subject, then set our from, to, and body. Then we use the batch_send function so that each recipient only sees themselves on the email, and no one else.

There is one possibly downside of doing it the way I have, and that is if you are sending many messages, the page may take forever to load. A solution to tthis would be running a Javascript AJAX request to send each and every message, but I won't cover that here. Now that we have finished working on sending messages, we are going to spice up the home page and then we will be done!

Step 11:The Homepage

When you load the admin index, the page does not really do much. I want to have some 'stats' on our homepage, and we will finally use the count_query function. Open up the admin index file and change it to look like:

# admin/index.php current stats 

$users user registered

$emails subscribers

$subs newsletter subscriptions

$nls newsletters

$mess messages

$temps templates

EOF; include 'layout.php'; ?>

The page is very simple. We require our config, make sure we are logged in, then we perform six count queries, one for each of our tables and then output that. This is what the final page look like: