Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [klasa] mailing
Forum PHP.pl > Inne > Oceny
piotrooo89
dziękuje za wszelkie porady, uwagi. zabieram się do poprawek.

proszę również o dalsze komentarze.

Odłożyłem na chwile stronicowanie, potrzeba chwili wymogła na mnie zrobienie newslettera. Nie chce zakładać kolejnego tematu więc pokaże go tu. Jest to najprostsze wysyłanie maila, tymczasowo bez nagłówków. Powiedzcie mi czy idę w dobrą stronę.

newsletter-class.php
  1. <?php
  2. class Newsletter
  3. {
  4.    public function GetMailsFromFile($file, $separator)
  5.    {
  6.        $string = file_get_contents($file);
  7.        $mails_file = explode($separator, $string);
  8.        return $mails_file;
  9.    }
  10.    public function GetMailsFromDb($sql)
  11.    {
  12.        $sql_query = mysql_query($sql);
  13.        while ($rows = mysql_fetch_row($sql_query))
  14.        {
  15.            $mails_db[] = $rows[0];
  16.        }
  17.        return $mails_db;
  18.    }
  19.    public function Send($where, $subject, $message)
  20.    {
  21.        foreach($where as $mails)
  22.        {
  23.            mail($mails, $subject, $message);
  24.        }
  25.    }
  26. }
  27. ?>


index.php
  1. <?php
  2. require_once ('newsletter-class.php');
  3. require_once ('mysql.php');
  4.  
  5. $topic = 'Test';
  6. $msg = 'Wiadomość testowa';
  7.  
  8. $sql = 'SELECT mail FROM emails';
  9.  
  10. $news = new Newsletter();
  11. $file = $news -> GetMailsFromFile('mail.txt', ';');
  12. $db = $news -> GetMailsFromDb($sql);
  13. // z pliku
  14. $news -> Send($file, $topic, $msg);
  15. //lub lub bazy
  16. $news -> Send($db, $topic, $msg);
  17. ?>
phpion
Ogólnie idziesz w dobrą stronę ale poczytaj o tym, co to jest polimorfizm i jak można go wykorzystać. Konkretnie chodzi mi o metody:
- GetMailsFromFile
- GetMailsFromDb
Generalnie nie powinno się tak robić (tworzyć osobnych metod do pobierania danych z różnych źródeł). Zdecydowanie lepiej utworzyć obiekt typu Loader, który by pobierał dane w speclajny sposób, coś na wzór:
  1. <?php
  2. abstract class Loader {
  3.    abstract public function load();
  4. }
  5.  
  6. class Loader_File extends Loader {
  7.    public function load() {
  8.        // wczytaj adresy z pliku
  9.    }
  10. }
  11.  
  12. class Loader_Database extends Loader {
  13.    public function load() {
  14.        // wczytaj adresy z bazy danych
  15.    }
  16. }
  17. ?>

Klasa Newsletter mogłaby wyglądać mniej-więcej tak:
  1. <?php
  2. class Newsletter {
  3.    private $loader;
  4.    
  5.    public function setLoader(Loader $loader) {
  6.        $this->loader = $loader;
  7.    }
  8.    
  9.    public function getMails() {
  10.        return $this->loader->load();
  11.    }
  12. }
  13. ?>

oraz wykorzystanie:
  1. <?php
  2. $obj = new Newsletter();
  3. $obj->setLoader(new Loader_File());
  4. print_r($obj->getMails());
  5. ?>
Cypherq
Hmn... obsługa wyjątków, szczególnie przy pracy na pliku? Zawsze wydawało mi się, że nazewnictwo plików powinno wyglądać tak: class.Nazwaklasy.php, ale może to tylko moja konwencja winksmiley.jpg
piotrooo89
~phpion dzięki za przykład, uczę się dopiero i nie bardzo mi to wychodzi. zrobiłem coś takiego:

  1. <?php
  2. abstract class Loader
  3. {
  4.    abstract public function load();
  5. }
  6. class Loader_File extends Loader
  7. {
  8.    public function load()
  9.    {
  10.        $string = file_get_contents($file);
  11.        $mails_file = explode($separator, $string);
  12.        print_r($mails_file);
  13.    }
  14. }
  15. class Loader_Database extends Loader
  16. {
  17.    public function load()
  18.    {
  19.        $sql_query = mysql_query($sql);
  20.        while ($rows = mysql_fetch_row($sql_query))
  21.        {
  22.            $mails_db[] = $rows[0];
  23.        }
  24.        print_r($mails_db);
  25.    }
  26. }
  27. class Newsletter
  28. {
  29.    private $loader;
  30.  
  31.    public function setLoader(Loader $loader)
  32.    {
  33.        $this->loader = $loader;
  34.    }
  35.  
  36.    public function getMails()
  37.    {
  38.        return $this->loader->load();
  39.    }
  40. }
  41. ?>


ale jest źle. dlaczego? ponieważ nie wiem gdzie mam podać nazwę pliku/query do bazy.

~Cypherq
wiem o nazwach narazie testuje wszytko, później będę wyjątki łapał. narazie chce to uruchomić.

#EDIT

jak podam na sztywno nazwy pliku/query działa.

#EDIT2
zrobiłem tak, powiedzcie co o tym sądzicie:

newsletter-class.php
  1. <?php
  2. abstract class Loader
  3. {
  4.    abstract public function load();
  5. }
  6. class Loader_File extends Loader
  7. {
  8.    public function __construct($file, $separator)
  9.    {
  10.        $this->file = $file;
  11.        $this->sep = $separator;
  12.    }
  13.    public function load()
  14.    {
  15.        $string = file_get_contents($this->file);
  16.        $mails_file = explode($this->sep, $string);
  17.        return $mails_file;
  18.    }
  19. }
  20. class Loader_Database extends Loader
  21. {
  22.    public function __construct($sql)
  23.    {
  24.        $this->sql = $sql;
  25.    }
  26.    public function load()
  27.    {
  28.        $sql_query = mysql_query($this->sql);
  29.        while ($rows = mysql_fetch_row($sql_query))
  30.        {
  31.            $mails_db[] = $rows[0];
  32.        }
  33.        return $mails_db;
  34.    }
  35. }
  36. class Newsletter
  37. {
  38.    private $loader;
  39.  
  40.    public function setLoader(Loader $loader)
  41.    {
  42.        $this->loader = $loader;
  43.    }
  44.  
  45.    public function getMails()
  46.    {
  47.        return $this->loader->load();
  48.    }
  49.    public function Send($where, $subject, $message)
  50.   {
  51.       foreach($where as $mails)
  52.       {
  53.           mail($mails, $subject, $message);
  54.       }
  55.   }
  56. }
  57. ?>


index.php
  1. <?php
  2. require_once ('newsletter-class.php');
  3. require_once ('mysql.php');
  4.  
  5. $topic = 'Test';
  6. $msg = 'Wiadomość testowa';
  7.  
  8. $sql = 'SELECT mail FROM emails';
  9. $f = 'mail.txt';
  10.  
  11. $news = new Newsletter();
  12. $file = new Loader_File($f, ';');
  13. $db = new Loader_Database($sql);
  14.  
  15. $news -> setLoader($file);
  16.  
  17. print_r($news -> getMails());
  18.  
  19. $news -> Send($news->getMails(), $topic, $msg);
  20. ?>
erix
Wydzieliłem z http://forum.php.pl/index.php?showtopic=118120
piotrooo89
Cytat(erix @ 11.04.2009, 00:58:19 ) *


Dziękować.
netvalue
hmm..
1. jak będę posiadał 60k maili w bazie czy pliku smile.gif ... To myślisz że wszystko gładko wyśle za jednym zamachem smile.gif ?
2. Może warto byłoby zaopatrzyć maila w nagłówki i autoryzację smtp. przy obecnym stanie większość serwerów oznaczy to flagą SPAM snitch.gif
skowron-line
@piotrooo89 a dlaczego wymyślasz koło od nowa jest klasa phpMailer ma wszystko czego tobie potrzeba.
phpion
Cytat(skowron-line @ 11.04.2009, 12:32:16 ) *
@piotrooo89 a dlaczego wymyślasz koło od nowa jest klasa phpMailer ma wszystko czego tobie potrzeba.

Może dlatego, że się chłopak uczy?
piotrooo89
Cytat(netvalue @ 11.04.2009, 11:16:33 ) *
1. jak będę posiadał 60k maili w bazie czy pliku smile.gif ... To myślisz że wszystko gładko wyśle za jednym zamachem smile.gif ?


tak tak już o tym pomyślałem. dodam odpowiednie funkcje.

Cytat(netvalue @ 11.04.2009, 11:16:33 ) *
2. Może warto byłoby zaopatrzyć maila w nagłówki i autoryzację smtp. przy obecnym stanie większość serwerów oznaczy to flagą SPAM snitch.gif


nagłóweczki już są choć narazie chce zrobić ogólny zarys klasy i zapytać innych o zdanie.

Cytat(skowron-line @ 11.04.2009, 12:32:16 ) *
@piotrooo89 a dlaczego wymyślasz koło od nowa jest klasa phpMailer ma wszystko czego tobie potrzeba.


tak jak napisał ~phpion:

Cytat(phpion @ 11.04.2009, 12:42:36 ) *
Może dlatego, że się chłopak uczy?


i chyba bardziej cieszy coś własnego smile.gif

a wracając do tematu jak oceniacie? co zmienić, dodać?

aktualnie wygląda to tak:

newsletter.Class.php
  1. <?php
  2. abstract class Loader
  3. {
  4.    abstract public function load();
  5.    public $errors =
  6.        array(
  7.        'no_file' => 'Plik nie istnieje',
  8.        'wrong_separator' => 'Nie podano separatora',
  9.        'wrong_sql' => 'Brak zapytania SQL',
  10.        'wrong_sql_col' => 'Podaj kolumne z adresami e-mail',
  11.        'wrong_sql_tab' => 'Podaj tabele SQL'
  12.        );
  13. }
  14. class Loader_File extends Loader
  15. {
  16.    public function __construct($file, $separator)
  17.    {
  18.        if (empty($separator))
  19.            throw new Exception($this->errors['wrong_separator']);
  20.  
  21.        $this->file = $file;
  22.        $this->sep = $separator;
  23.    }
  24.    public function load()    
  25.    {
  26.        if (!file_exists($this->file))
  27.            throw new Exception($this->errors['no_file']);
  28.            
  29.            $string = file_get_contents($this->file);
  30.            $mails_file = explode($this->sep, $string);
  31.            return $mails_file;
  32.    }
  33. }
  34. class Loader_Database extends Loader
  35. {
  36.    public function __construct($col, $tab)
  37.    {
  38.        if (empty($col) && empty($tab))
  39.            throw new Exception($this->errors['wrong_sql']);
  40.        elseif (empty($col))
  41.            throw new Exception($this->errors['wrong_sql_col']);
  42.        elseif (empty($tab))
  43.            throw new Exception($this->errors['wrong_sql_tab']);
  44.            
  45.        $this->col = $col;
  46.        $this->tab = $tab;
  47.    }
  48.    public function load()
  49.    {
  50.        $sql_query = mysql_query("SELECT `".$this->col."` FROM `".$this->tab."`");
  51.        while ($rows = mysql_fetch_row($sql_query))
  52.        {
  53.            $mails_db[] = $rows[0];
  54.        }
  55.        return $mails_db;
  56.    }
  57. }
  58. class Newsletter
  59. {
  60.    private $loader;
  61.  
  62.    public function setLoader(Loader $loader)
  63.    {
  64.        $this->loader = $loader;
  65.    }
  66.    public function getMails()
  67.    {
  68.        return $this->loader->load();
  69.    }
  70.    public function Send($where, $subject, $message, $head)
  71.    {
  72.        foreach($where as $mails)
  73.        {
  74.            mail($mails, $subject, $message, $head);
  75.        }
  76.    }
  77. }
  78. ?>


index.php
  1. <?php
  2. require_once ('newsletter.Class.php');
  3. require_once ('mysql.php');
  4.  
  5. $topic = 'Test';
  6. $msg = 'Wiadomość testowa';
  7. $headers .= "From: Olaszewski <piotroo89@gmail.com>r\n";
  8. $headers .= "Reply-To: Olaszewski <piotroo89@gmail.com>r\n";
  9. $headers .= "Return-Path: Olaszewski <piotroo89@gmail.com>r\n";
  10. $headers .= 'X-Mailer: PHP/' . phpversion() ."r\n";
  11. $headers .= 'MIME-Version: 1.0'. "\n";
  12. $headers .= 'Content-type: text/html; charset=utf-8' . "r\n";
  13. $headers .= "Content-transfer-encoding: utf-8r\n";
  14.  
  15. $column_sql = 'mail';
  16. $table_sql = 'emails';
  17.  
  18. $f = 'mail.txt';
  19.  
  20. try
  21. {
  22.    $news = new Newsletter();
  23.    $file = new Loader_File($f, ';');
  24.    $db = new Loader_Database($column_sql, $table_sql);
  25.    $news -> setLoader($db);
  26.  
  27.    print_r($news->getMails());
  28.  
  29.    $news -> Send($news->getMails(), $topic, $msg, $headers);
  30. }
  31. catch(Exception $e)
  32. {
  33.    $error = ($e->getMessage());
  34.    echo $error;
  35. }
  36. ?>
phpion
Moje 2 uwagi:

1. Loader::$errors - wg mnie komunikaty błędów powinny znajdować się w wyspecjalizowanych klasach, ponieważ teraz każda klasa pochodna będzie miała wszystkie komunikaty (po co np. w Loader_File komunikat wrong_sql?). Ponadto rozważyłbym zapis komunikatów w postaci stałych wewnątrz klasy (const).

2. Nie podoba mi się sposób dodawania nagłówków. Zrobiłbym to raczej w ten sposób:
  1. <?php
  2. class Newsletter {
  3.    private $headers = array();
  4.  
  5.    //...
  6.  
  7.    public function addHeader($name, $value) {
  8.        $this->headers[$name] = $value;
  9.    }
  10. }
  11. ?>

i potem przy wysyłaniu maila wystarczyłoby przekształcić tą tablicę na stringa (tak, jak to robisz w przykładzie). Dzięki temu rozwiązaniu możesz już w konstruktorze machnąć kilka domyślnych nagłówków (np. ustawić kodowanie oraz typ wysyłanego maila).
piotrooo89
dzięki za kolejne rady. obecnie klasa wygląda tak:

newsletter.Class.php
  1. <?php
  2. abstract class Loader
  3. {
  4.    abstract public function load();
  5. }
  6. class Loader_File extends Loader
  7. {
  8.    const WRONG_FILE = 'Plik nie istnieje';
  9.    const WRONG_SEPARATOR = 'Nie podano separatora';
  10.    
  11.    public function __construct($file, $separator)
  12.    {
  13.        if (empty($separator))
  14.            throw new Exception(Loader_File::WRONG_SEPARATOR);
  15.  
  16.        $this->file = $file;
  17.        $this->sep = $separator;
  18.    }
  19.    public function load()    
  20.    {
  21.        if (!file_exists($this->file))
  22.            throw new Exception(Loader_File::WRONG_FILE);
  23.            
  24.            $string = file_get_contents($this->file);
  25.            $mails_file = explode($this->sep, $string);
  26.            return $mails_file;
  27.    }
  28. }
  29. class Loader_Database extends Loader
  30. {
  31.    const WRONG_SQL = 'Brak zapytania SQL';
  32.    const WRONG_SQL_COL = 'Podaj kolumne z adresami e-mail';
  33.    const WRONF_SQL_TAB = 'Podaj tabele SQL';
  34.    
  35.    public function __construct($col, $tab)
  36.    {
  37.        if (empty($col) && empty($tab))
  38.            throw new Exception(Loader_Database::WRONG_SQL);
  39.        elseif (empty($col))
  40.            throw new Exception(Loader_Database::WRONG_SQL_COL);
  41.        elseif (empty($tab))
  42.            throw new Exception(Loader_Database::WRONF_SQL_TAB);
  43.            
  44.        $this->col = $col;
  45.        $this->tab = $tab;
  46.    }
  47.    public function load()
  48.    {
  49.        $sql_query = mysql_query("SELECT `".$this->col."` FROM `".$this->tab."`");
  50.        while ($rows = mysql_fetch_row($sql_query))
  51.        {
  52.            $mails_db[] = $rows[0];
  53.        }
  54.        return $mails_db;
  55.    }
  56. }
  57. class Newsletter
  58. {
  59.    private $loader;
  60.    private $headers = array();
  61.  
  62.    public function setLoader(Loader $loader)
  63.    {
  64.        $this->loader = $loader;
  65.    }
  66.    public function getMails()
  67.    {
  68.        return $this->loader->load();
  69.    }
  70.    public function addHeaders($value)
  71.    {
  72.        $this->headers[] = $value;
  73.    }
  74.    public function getHeaders()
  75.    {
  76.        foreach($this->headers as $heads)
  77.        {
  78.            $show_heads .= $heads;
  79.        }
  80.        return $show_heads;
  81.    }
  82.    public function Send($where, $subject, $message, $head)
  83.    {
  84.        foreach($where as $mails)
  85.        {
  86.            mail($mails, $subject, $message, $head);
  87.        }
  88.    }
  89. }
  90. ?>


index.php
  1. <?php
  2. require_once ('newsletter.Class.php');
  3. require_once ('mysql.php');
  4.  
  5. $topic = 'Test';
  6. $msg = 'Wiadomość testowa';
  7. /*************
  8. $headers .= "From: Olaszewski <piotroo89@gmail.com>r\n";
  9. $headers .= "Reply-To: Olaszewski <piotroo89@gmail.com>r\n";
  10. $headers .= "Return-Path: Olaszewski <piotroo89@gmail.com>r\n";
  11. $headers .= 'X-Mailer: PHP/' . phpversion() ."r\n";
  12. $headers .= 'MIME-Version: 1.0'. "\n";
  13. $headers .= 'Content-type: text/html; charset=utf-8' . "r\n";
  14. $headers .= "Content-transfer-encoding: utf-8r\n";
  15. *************/
  16.  
  17. $column_sql = 'mail';
  18. $table_sql = 'emails';
  19.  
  20. $f = 'mail.txt';
  21.  
  22. try
  23. {
  24.    $news = new Newsletter();
  25.    $file = new Loader_File($f, ';');
  26.    $db = new Loader_Database($column_sql, $table_sql);
  27.    
  28.    $news->setLoader($file);
  29.    
  30.    $news->addHeaders("From: Olaszewski <piotroo89@gmail.com>r\n");
  31.    $news->addHeaders("Reply-To: Olaszewski <piotroo89@gmail.com>r\n");
  32.    $news->addHeaders("Content-type: text/html; charset=utf-8r\n");
  33.  
  34.    $news -> Send($news->getMails(), $topic, $msg, $news->getHeaders());
  35. }
  36. catch(Exception $e)
  37. {
  38.    $error = ($e->getMessage());
  39.    echo $error;
  40. }
  41. ?>


czekam na dalsze rady (optymalizacja, poprawienie działania etc.).
bim2
Może
  1. <?php
  2. $news->addHeaders('Content-type', 'text/html; charset=utf-8');
  3. ?>

a \r\n dodawać automatycznie ? smile.gif
skowron-line
Według mnie mógłbyś dać więcej metod typu
Kod
setMessage( $msg )
{
$this->msg = stripslashes( $msg );
}
addAddress( $address )
{
//walidacja adresu
}

Albo jeszcze sprawdzać czy wiadomość nie jest pusta.

  1. <?php
  2. public function addHeaders($value)
  3.   {
  4.       $this->headers[] = $value;
  5.   }
  6. public function Send($where, $subject, $message)
  7.   {
  8.       foreach($where as $mails)
  9.       {
  10.           mail($mails, $subject, $message, $his->headers);
  11.       }
  12.   }
  13. ?>

Po co wstawiasz do metody kolejny parametr jak możesz je wyciągać wewnątrz klasy.
Tak samo jak message i where i subject i miałbyś
  1. <?php
  2. $news->send();
  3. ?>
Cypherq
Te komunikaty o błędach, zawsze myślałem, że wygodniej trzymać w osobnym pliku. Wtedy zmieniając język komunikatów nie grzebiemy w klasie, a chyba o to chodzi?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.