Úprava PHPMailer-u aby používal Menno priestory (namespaces)
V dnešnej dobe Vám odporúčam článok o Composer. V čase písania tohto článku už síce Composer existoval, bol ale v alfa verziám a nechcel som ho Preto použité. Vtedy som potreboval integrovať PHPMailer do projektu založeného na tunajšom MVC redakčnom systéme, a tento článok je práve o tom, ako som k riesenie pristúpil.
Rozhodol som sa Napíšte vlastnú Mailer v PHP, ktory by vedel jednoducho odosielať emaily hľa s prílohami, a tiez na viacerích Emailov naraz. Po niekoľkých hodinách vymýšľania najlepšieho riesenie a testovaním som stále nevedel Ako rozhodujuca prílohy pridáva a posielať. Vzdal som sa tohto Ciel a začal som hladom, či už niekto nieco podobne nevytvoril. Narazil som na PHPMailer (https://github.com/...er/PHPMailer), ktory toto všetko vie, tak prečo ho nepoužiť.
V PHPMailer-i sa dá pohodlne Pridať viacerích prijímateľov a viacerích príloh, meniť názvy príloh, vybrať si Spôsob kódovaním príloh, sám zistí o aký typ prílohy sa jedná, má viacerích možností odosielania Emailov (mail (), Sendmail (), smtp .. .), a kopec inych vecí ktore by som vymýšľal mesiace, a možno hľa roky, a na to času nemám a vy isto tiez nie
Túto idilku však narušil jeden (pre mňa) problém, a to že v celú mojom projekte používam Menno priestory (namespaces), a PHPMailer ich nepoužíva kvoli Špatnej kompatibilite s PHP 5.0. Ja mám však Menno priestory rád, pretoze si Môžem projekt štrukturalizovať Ako sám chcem, Ako mi to vyhovuje, a Ako sa mi to logicky najviac páči. Cudzí softvér by sa však nemal upravovať z Dovod možnej aktualizáciám, kedy by sme museli všetko toto nanovo prepisovať, ale osobne si myslím že v aktuálnej podobe bude fungovať ešte Dlho. Okrem toho sa na serveroch používajte verziám php 5.3 a vyšším (5.3 sa už Vôbec nevyvíja, v 5.4 ľan opravujte chyby, nemá podla mna zmysel v nich projekt začína - http://en.wikipedia.org/wiki/PHP), ktore podporujte namespaces, a ja som lenivý používať require (include) funkciám ja chcem aby mi to všetko načítaval sám autoloader, inak to nebude a basta!
Adresárovej štruktúry nášho projektu som zvolil tak, aby sa podobala na štruktúry Jednoduchého objektového redakčného systému z tunajších tutoriálov, a bude nasledovná:
- app controllers
models
views
...
- controllers
- models
- views
- ...
- public js
css
img
...
- js
- css
- img
- ...
- vendor phpmailer
...
- phpmailer
- ...
V Naso projekte máme niekolko pravidlámi, ktore musíme spoznať a dodržiavať:
- Pomocou .htaccess podobne Ako v tunajších tutoriáloch smerujete Všetky Požiadavky (okrem povolených súborov) na Súbor index.php v koreňovej zložka nášho RS.
- Každá trieda je vo vlastnom subor (1 trieda == 1 Súbor), každý Súbor sa volá Rovňák Ako daná trieda (class Trieda == Trieda.php).
- Adresárovej štruktúry (Takmer) suhlas s menným priestorom (namespace controller \ Router == controller-Router.php), akurát podľa potreby autoloader sám doplní na zaciatok app / Alebo vendor /, podľa toho kde trieda našiel.
Použijeme PHPMailer dostupný na Github-e (https://github.com/...er/PHPMailer), ktory si stiahnem na disk a rozbalíme. Aby všetko fungovalo tak ako ma, potrebujeme subor class.phpmailer.php, class.pop3.php, class.smtp.php, a zložka extras a language. Zložka extras obsahuje 3 subor, ktore PHPMailer používa, a zložka language Moze vynechať (nebudem môcť nastaviť jazyk chybových správ a defaultne budujú anglické), ale ja som ich tam nechal, nechaj mám chyby pekne v slovenčine. V Naso RS som ich skopírovali na zložka vendor / phpmailer.
Pozornému oku pri editovanie neunikne, že v subor class.phpmailer.php máme 2 triedy, PHPMailer a phpmailerException. Keďže sme sa dohodli na pravidle 1 trieda == 1 Súbor, phpmailerException vyčleníme do samostatného subor s názvom rovnakým Ako trieda, teda phpmailerException.php. Dajte pozor aby v subor pred <? Php tágo nebola Žiadna medzera ani nič iné (sám som práve urobila takú chybička).
Premieňať musíme ai ostatné 3 subor aby súhlasil názov subor s názvom triedy, teda z class.phpmailer.php Urobíme PHPMailer.php, z class.pop3.php Urobíme POP3.php, az class.smtp.php Urobíme SMTP.php. V zložka extras musíme premieňať ľan Súbor ntlm_sasl_client.php na ntlm_sasl_client_class.php (neskorý v SMTP Urobíme zmeny), Súbor EasyPeasyICS má Rovňák názov Ako trieda, a Súbor htmlfilter.php obsahuje ľan funkciám nie Tried (celé je to nejaké divné, ani som nevidel či sa Vôbec niekde používa).
Ideme si teda Pridať namespaces: Začneme v zložka extras: triedam EasyPeasyICS a ntlm_sasl_client_class pridáme
namespace phpmailer\extras;
presne Ako máme subor zapustené v zložkách, a to bude všetko, pretoze pulovr nebo vesta triedy nepotrebuju nič iné. Z návodu o OOP v PHP vieme, že namespace sa pridáva za <? Php tag a pred definovaním triedy (class Xyz).
Vynimky phpmailerException pridáme
namespace phpmailer; //a use Exception;
keďže výnimka Exception, z ktorej táto výnimka dedí, sa nenachádza v danú mennom priestory.
Trieda POP3 pridáme
namespace phpmailer; // a tiež use Exception;
keďže tiez používa vynimky Exception.
V Trieda SMTP pridáme
namespace phpmailer; use stdClass; // a spomínanú premenovanú triedu ntlm_sasl_client_class pomocou: use phpmailer\extras\ntlm_sasl_client_class;
Treba si však dať pozor, lebo Pôvodný script na riadku 443 túto Tried (ntlm_sasl_client_class) sám require-uje, ale my už používame autoloader, a Súbor sme ai tak premieňal aby sa zhodoval s názvom triedy, tak tento príkaz require odstránime, alebo zakomentujeme! !!
Nakoniec v Trieda PHPMailer pridáme
namespace phpmailer; use phpmailer\phpmailerException; use phpmailer\SMTP; use Exception;
Treba Mat pamäti že každé include Alebo require by malo obsahovej cestu relatívna k index.php, nie k danej trieda. Výnimkou je jedno include v Tried PHPMailer, ktore je (záplavy) na riadku 1431, a slúžte na nahriatím jazykovej mutáciám pre vypisovaním chybe. Tiete subor ŠÚ v zložka language a do triedy sa includujú relatívna k tajte Tried (nie k index.php Ako máme nastavenú), takže to meniť nemusíme. Zabezpečuje to magická konštanta __FILE__ (http://php.net/...edefined.php), ktora obsahuje cestu k danej Tried v ktorej je, ak naj sa pripája cesta od danej triedy k subor ktory ideme includovať.
To by sme mali z úprav PHPMaileru všetko, v zložka app / models / Mailer.php je trieda, v ktorej je ukážka odoslania jednoduchého emailu cez mail () funkciám v php.
namespace models; use Exception; use phpmailer\PHPMailer; // pridanie PHPMaileru class Mailer { public function send($email){ try { // vytvorenie inštancie PHPMaileru, atribútom je true ktorý zapne, aby sa pri chybe vyhadzovala výnimka, defaultne je false $mailer = new PHPMailer(true); // nastavenie jazyka chybových hlášok, defaultne je "en" $mailer->setLanguage("sk"); // nastavenie znakovej sady, defaultne je iso-8859-1 $mailer->CharSet = 'UTF-8'; // defaultne sa odosiela cez php mail() funkciu. // $mailer->isSendmail(); // nastavenie na sendmail() funkciu na linuxoch // $mailer->isSMTP(); // nastavenie na SMTP // nastavenie odosielajúcej adresy $mailer->setFrom("[email protected]", "Tvoj kamarát Matúš"); // nastavenie adresy na ktorú sa bude odosielať prípadná odpoveď (také to vnucovanie :D) $mailer->addReplyTo("[email protected]", "Justin Bieber"); // nastavenie adresy na ktorú sa má email odoslať $mailer->addAddress($email); // nastavenie predmetu emailu $mailer->Subject = "Testovací super email."; // pridanie obsahu emailu zo súboru, relatívne k index.php (u mňa, v dokumentácii som videl s / na začiatku ale to nefungovalo) $mailer->msgHTML(file_get_contents("path/to/test/template.html")); // pridanie prílohy, prvé je cesta a druhú je na zmenu názvu súboru $mailer->addAttachment("path/to/test/attachment.png", "Obrázok podivnosti"); // mágia, odoslanie :) ak nie je nastavené na výnimky, tak vracia true/false $mailer->send(); } catch (Exception $e){ // akcia v prípade obecnej výnimky } } }
Okrem mail () Moze Použiť ai sendmail () (pre linuxové servery), alebo pripojením na SMTP server, a podobne. Viac ukážok sa dá pozriet na PHPMailer GitHub (https://github.com/...er/PHPMailer) + v priloženom subor sú aj povodne subor, a tam ŠÚ tiez ukážky. Možno o tom bude článok
Spôsob odosielania Emailov a nastavovaním PHPMaileru by mal ostat nezmenený.
Poznámka: Čo sa týka Autoloader, vraj by nemal vyhadzovať chyby Alebo zastavovať script. Podla mna to tak je Preto, aby sa dalo zaregistrovať viacerích rôznych AutoLoad funkcií. Napr: jedna ktora kontroluje Existencia a pripadne includuje trieda, ked nie, ide na rad druhá atd atd. Vstavané triedy Ako Exception Alebo DateTime sa vedia Načítať sami, predtym ako príde na rad náš autoloader. Funkciám AutoLoad k tomuto článku zisťuje prítomnosť potrebnych tried v zložkách app a vendor, a isto si to budete vediet prispôsobiť sami