Ποιες if/κώδικα πρέπει να τρέξω;

Σε αυτή την περιοχή μπορείτε να βρείτε ή να αναζητήσετε πληροφορίες σχετικές με την PHP

Συντονιστές: WebDev Moderators, Super-Moderators, PHP Moderators

Απάντηση
Άβαταρ μέλους
philos
Δημοσιεύσεις: 260
Εγγραφή: 30 Αύγ 2007 23:32

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από philos » 12 Αύγ 2013 18:29

Καλησπέρα στο forum!

Έχω ένα πρόβλημα προς επίλυση.
Λοιπόν, έχουμε ένα σύστημα αυτόματης αποστολής e-mail.
Τα e-mails προς αποστολή στους χρήστες, αποθηκεύονται στον πίνακα emails, ο οποίος έχει μεταξύ άλλων το column "after_x_weeks".
Το after_x_weeks παίρνει τιμές 1,2,3 κτλ κτλ, δλδ αριθμό εβδομάδων, που σημαίνει ότι το τάδε e-mail θα σταλεί στους χρήστες Χ εβδομάδες μετά την εγγραφή τους και ΟΧΙ επαναλαμβανόμενα.

Μπορεί για παράδειγμα ο διαχειριστής να αποθηκεύσει ένα e-mail που θα σταλεί 2 εβδομάδες μετά την εγγραφή του χρήστη και ένα άλλο 3 εβδομάδες μετά την εγγραφή του.
Οπότε ο χρήστης θα λάβει το πρώτο e-mail όταν συμπληρώσει 2 εβδομάδες από την εγγραφή του και άλλο ένα όταν συμπληρώσει 3 εβδομάδες. Δηλαδή όταν συμπληρώσει 3 εβδομάδες, θα έχει λάβει ήδη το e-mail των 2 εβδομάδων, δεν πρέπει να το ξανά λάβει, και ασφαλώς τότε θα λάβει και το e-mail των 3ων εβδομάδων.

- Ας πούμε ότι η στιγμή εγγραφής των χρηστών είναι στον πίνακα users, στο column registration_date (= είναι UNIX TIMESTAMP).
- Όταν τρέχει το cronjob αποστολής e-mail (κάθε 24 ώρες), σημειώνει στον πίνακα users, στο column latest_email, το timestamp του τελευταίου email, ΑΝ στείλει στον τάδε χρήστη e-mail.

Θέλω τη βοήθειά σας στο εξής. Ποιες if και κώδικα πρέπει να τρέξω στο cronjob για να στέλνονται σωστά τα e-mail στο σωστό χρόνο και χωρίς επανάληψη? Φυσικά μια χρονική καθυστέρηση μέχρι 24 ωρών, δεν μας ενοχλεί, μιας που κάθε 24 ώρες ελέγχει το cronjob σε ποιους είναι να στείλει.
Προσοχή στο ότι το after_x_weeks είναι αριθμός εβδομάδων, οπότε πρέπει να τις μετατρέψουμε σε unix timestamps.


Ευχαριστώ! :D

Άβαταρ μέλους
dva_dev
Script Master
Δημοσιεύσεις: 3790
Εγγραφή: 16 Σεπ 2005 01:32
Επικοινωνία:

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από dva_dev » 12 Αύγ 2013 19:08

Για να δουλέψει σωστά αυτό το πράγμα πρέπει να ξέρεις το κάθε email, στον κάθε χρήστη, πότε στάλθηκε. Αν δεν τα έχεις αυτά τα στοιχεία τότε θα πρότεινα να φτιάξεις έναν πίνακα με
userid,emailid,sentdate και να ελέγχεις εκεί μέσα αν υπάρχει να είναι τουλάχιστον Χ εβδομάδες το διάστημα (όσο λέει το after_x_weeks). Αν δεν υπάρχει στέλνεις το email και το καταχωρείς.

ΥΓ. Γιατί έχεις timestamps και όχι date ή datetime να καταλαβαίνεις κιόλας τι περιέχουν; Στον υπολογιστή δεν κάνει διαφορά, στο χρήστη (διαχειριστή βασικά) έχει μεγάλη.

Επίσης δεν υπάρχει μία if ή ένας κώδικας που μπορείς να τρέξεις. 50 άτομα από εδώ μέσα να σου γράψουν κώδικα θα πάρεις τουλάχιστον 50 διαφορετικά ifs/κώδικες.

alou
Script Master
Δημοσιεύσεις: 1374
Εγγραφή: 24 Αύγ 2007 19:52
Επικοινωνία:

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από alou » 12 Αύγ 2013 19:47

Όντως υπάρχουν 50 τρόποι να το κάνεις, το θέμα είναι τι στοιχεία έχεις και τι σε δεσμεύει από αυτά. Στον πίνακα που θα διαχειρίζεται αυτά τα email, πιθανώς βολεύει:

id--recipient(s)--title--body--min date to send(date)--status(send or not, 0 ή 1)--datetime send

Εξαρτάται και με τι τρόπο θα αποθηκευτούν αυτά τα στχοιεία, πχ όλο το κομμάτι του emal θα μπορούσε να ήταν json και να είναι όλα τα στοιχεία του email σε μία στήλη (γιατί μπορεί να έχεις και cc, attachements ή οτιδήποτε άλλο).

Μετά το query και το loop είναι απλή υπόθεση.

Άβαταρ μέλους
philos
Δημοσιεύσεις: 260
Εγγραφή: 30 Αύγ 2007 23:32

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από philos » 12 Αύγ 2013 23:53

ok παιδιά, προσθέτω και έναν πίνακα sentmails με columns:
itemid
emailid
userid
sentdate

Προσοχή στο ότι το emailid είναι του πίνακα emails (ο οποίος πίνακας έχει και τα subject, emailbody κτλ), και όχι το emailid που στάλθηκε (για το email που στάλθηκε έβαλα το itemid).

Πως μπορώ τώρα να κάνω αυτό που θέλω;

Να πω ότι αρχικά τραβάω τα στοιχεία του πίνακα emails και ύστερα τα εξάγω με μια while ($email = fetch_array(emails)).
Μέσα σε αυτή τη while τραβάω τα στοιχεία του πίνακα users και πάλι με μια while ($user = fetch_array($users)) και κάνω το εξής:
$check = $timenow - $email['after_x_weeks'] * 7 * 86400;
if ($user['registration_date'] < $check)
{
// στέλνει το email
// καταχωρεί τα στοιχεία στον πίνακα sentmails
}

To $timenow είναι timestamp του τώρα.

Δεν ξέρω πως να ελέγξω αν το τάδε email έχει ήδη σταλλεί. Υποθέτω ότι πρέπει να κάνω κάποιο JOIN του user με τον sentmails, όμως το μόνο κοινό που έχουν είναι το userid.
Δοκίμασα στο SELECT query των users να βάλω IF(sentmails .itemid,1,0) AS has_receive,
και προσθέτω:
if ($user['registration_date'] < $check AND !$user['has_receive'])
{
// στέλνει το email
// καταχωρεί τα στοιχεία στον πίνακα sentmails
}
... όμως όπως είπα το μόνο κοινό είναι το userid, οπότε στέλνει μόνο το πρώτο email που εντοπίζει, όχι τα υπόλοιπα.

Γενικά δεν μου έρχεται το πως μπορώ να χρησιμοποιήσω την τιμή sentdate.

Ευχαριστώ εκ των προτέρων για τη βοήθεια!
Το πρόβλημα είναι λίγο πιο πολύπλοκο και τα ονόματα είναι καθαρά ενδεικτικά.

Άβαταρ μέλους
philos
Δημοσιεύσεις: 260
Εγγραφή: 30 Αύγ 2007 23:32

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από philos » 13 Αύγ 2013 00:37

Δοκίμασα το εξής μέσα στην while ($email = fetch_array(emails)), το οποίο απ' ότι φαίνεται δουλεύει (δεν χρησιμοποιώ καν την τιμή sentdate).

Κώδικας: Επιλογή όλων

    		SELECT user.*
    		FROM " . TABLE_PREFIX . "user AS user 
      	WHERE user.userid NOT IN &#40;
            SELECT userid 
            FROM " . TABLE_PREFIX . "sentmails 
            WHERE emailid = " . intval&#40;$email&#91;'emailid'&#93;&#41; . "&#41;
Είναι όμως εντάξει σαν λύση από θέμα βελτιστοποίησης; Αν έχουμε 1000δες απεσταλμένα emails, αυτό το NOT IN δεν μου κάθεται καλά. :-?

alou
Script Master
Δημοσιεύσεις: 1374
Εγγραφή: 24 Αύγ 2007 19:52
Επικοινωνία:

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από alou » 13 Αύγ 2013 07:55

Για ποιό λόγο να φτιάξεις άλλο πίνακα sentmails και να μην προσθέσεις απλά ένα πεδίο με sent date ή / και status? Μετά το select είναι εύκολο.

Ο μόνος λόγος που θα σκεφτόμουν να το κάνω είναι για συντήρηση και του πίνακα emails αλλά από όσο κατάλαβα παραμένουν και εκεί τα απεσταλμένα...

Γενικά, στο loop που κάνεις για οποιοδήποτε έλεγχο, δεν κάνεις ένα query για κάθε iteration (το λέω γιατί νομίζω έτσι κάνεις). Προσθέτεις τα στοιχεία που θες να χρησιμοποιήσεις σε ένα array ή string ανάλογα και κάνεις ένα query στο τέλος.

Έτσι θα κάνεις για να γίνουν και update τα email που στέλνεις στον πίνακα emails (αν βάλεις ένα έξτρα πεδίο), πχ πολύ χοντρικά:

$updateEmailStatus = "";
$firstItem = 0;
for each ($row as $item) {
...
if ($firstitem = 0) {
$updateEmailStatus .= $row->itemid;
} else {
$updateEmailStatus .= ' ,'.$row->itemid;
}
}

και φτιάχνεις ένα string για το update query σου

update pinakas_tade SET status = 1 WHERE itemid IN ($updateEmailStatus)

Αντί για status, θα μπορούσες να βάλεις date ή datetime.

Τουλάχιστον από όσο κατάλαβα, αυτό νομίζω ότι θα λειτουργούσε λίγο καλύτερα.

Άβαταρ μέλους
philos
Δημοσιεύσεις: 260
Εγγραφή: 30 Αύγ 2007 23:32

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από philos » 13 Αύγ 2013 11:51

Ευχαριστώ για την απάντηση alou!
Εννοείς να προσθέσω ένα πεδίο sentdate και status στον πίνακα των emails?
Μα ο πίνακας των emails περιέχει τα στοιχεία των emails (emailid, subject, emailbody, after_x_weeks κτλ). Υπάρχει σελίδα στο admincp με φόρμα υποβολής νέου email (= δεν στέλνονται immedtiately τα emails, απλώς καταχωρούνται στη βάση σε αυτό τον πίνακα και ύστερα το cron κάνει τον έλεγχο).
Είναι κάτι σαν newsletter - ο πίνακας email δεν περιέχει στοιχεία απεσταλμένων emails παρά μόνο τα στοιχεία των emails. Όπότε είναι αδύνατον να προσθέσω αυτά τα πεδία.

alou
Script Master
Δημοσιεύσεις: 1374
Εγγραφή: 24 Αύγ 2007 19:52
Επικοινωνία:

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από alou » 13 Αύγ 2013 12:17

Τώρα κατάλαβα τι εννοείς, νόμιζα ότι ο email ήταν 1 row per email type per user, νομίζω όμως ότι με κάποιο τρόπο πρέπει να καταλήξεις σε ένα τέτοιο πίνακα.

Δηλαδή μια φορά τώρα και με update σε κάθε εγγραφή, να υπάρχει πίνακας με εγγραφές για ότι email πρέπει να σταλλεί με το email id, τον χρήστη, την min date που θα σταλλεί και το send status και αν θες και ημερομηνία αποστολής.

Δεν σκέφτομαι κάτι απλούστερο.

Άβαταρ μέλους
philos
Δημοσιεύσεις: 260
Εγγραφή: 30 Αύγ 2007 23:32

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από philos » 13 Αύγ 2013 14:31

Αυτό που κάνω:
philos έγραψε:Δοκίμασα το εξής μέσα στην while ($email = fetch_array(emails)), το οποίο απ' ότι φαίνεται δουλεύει (δεν χρησιμοποιώ καν την τιμή sentdate).

Κώδικας: Επιλογή όλων

    		SELECT user.*
    		FROM " . TABLE_PREFIX . "user AS user 
      	WHERE user.userid NOT IN &#40;
            SELECT userid 
            FROM " . TABLE_PREFIX . "sentmails 
            WHERE emailid = " . intval&#40;$email&#91;'emailid'&#93;&#41; . "&#41;
Είναι όμως εντάξει σαν λύση από θέμα βελτιστοποίησης; Αν έχουμε 1000δες απεσταλμένα emails, αυτό το NOT IN δεν μου κάθεται καλά. :-?
... τι λάθος έχει; :idea:

alou
Script Master
Δημοσιεύσεις: 1374
Εγγραφή: 24 Αύγ 2007 19:52
Επικοινωνία:

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από alou » 13 Αύγ 2013 16:10

Δεν είπα ότι έχει λάθος, αφού λες ότι λειτουργεί, εναλλακτικές συζητάμε που ίσως είναι πιο αποδοτικές. Τι σου ταιριάζει καλύτερα θα το κρίνεις εσύ φυσικά.

geomagas
Δημοσιεύσεις: 667
Εγγραφή: 06 Απρ 2013 13:36
Τοποθεσία: Ηράκλειο Κρήτης
Επικοινωνία:

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από geomagas » 14 Αύγ 2013 01:15

Έστω emails (id, email_addr, subject, emailbody, sched_time, sent_time, ... )
1) Το id είναι autoincrement, απλά για να υπάρχει ένα primary key (μπορεί να έχεις αποφασίσει ήδη το δικό σου)
2) Πάω με τη λύση του alou, δηλαδή με τον πίνακα ιστορικού και το πεδίο sent_time, και όχι με έναν πίνακα με τα pending, διότι προσωπικά μου έχει φανεί χρήσιμο σε ανάλογη περίπτωση.
3) Η σημαντική αλλαγή είναι ότι, δεν κρατάς after_x_weeks αλλά sched_time, το οποίο προ-υπολογίζεις κατά το insert.

Για να πάρεις τα emails που πρέπει να σταλούν, χρειάζεσαι

Κώδικας: Επιλογή όλων

select * from emails where sent_time is null and sched_time<now&#40;&#41;
Για κάθε row (foreach) απλά στέλνεις το mail και κάνεις

Κώδικας: Επιλογή όλων

update emails set sent_time=now&#40;&#41; where id=$id
Κανένας άλλος έλεγχος δεν χρειάζεται σε επίπεδο php (εκτός αν θέλεις να ελέγξεις την επιτυχία/αποτυχία αποστολής, οπότε χρειάζεσαι και το πεδίο status).

Σε περίπτωση που δεν θέλεις να κρατάς ιστορικά στοιχεία, ξεχνάς το πεδίο sent_time και στη foreach κάνεις delete αντί για update.

Άβαταρ μέλους
dva_dev
Script Master
Δημοσιεύσεις: 3790
Εγγραφή: 16 Σεπ 2005 01:32
Επικοινωνία:

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από dva_dev » 14 Αύγ 2013 13:11

Νομίζω πως αυτό που θέλει είναι να έχει τα emails (όπως τα έχεις κι εσύ) αλλά το κάθε email μπορεί να πάει σε όλους τους χρήστες.
Π.χ. το email 1 να στέλνεται 5 μέρες μετά την εγγραφή του χρήστη. Το 2 να στέλνεται 10 μέρες μετά, κ.λπ.
Οπότε χρειάζεται να ξέρει για κάθε χρήστη ποιά emails έχουν σταλεί και ποιά όχι.
Τώρα δεν ξέρω κάθε πότε προσθέτει emails, πόσο συχνά μπαίνουν νέοι χρήστες, πράγματα που γενικά είναι μάλλον λειτουργική συμπεριφορά του site, οπότε ίσως να εξυπηρετεί το να υπολογίζεις ανά τακτά διαστήματα τι emails πρέπει να φύγουν, ίσως όμως να είναι πρακτικότερο να γίνεται υπολογισμός στο runtime εκείνη την ώρα τρέχοντας κάποιο μικρό (αν γίνεται) query.

geomagas
Δημοσιεύσεις: 667
Εγγραφή: 06 Απρ 2013 13:36
Τοποθεσία: Ηράκλειο Κρήτης
Επικοινωνία:

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από geomagas » 14 Αύγ 2013 14:13

dva_dev έγραψε:Νομίζω πως αυτό που θέλει είναι να έχει τα emails (όπως τα έχεις κι εσύ) αλλά το κάθε email μπορεί να πάει σε όλους τους χρήστες.
Π.χ. το email 1 να στέλνεται 5 μέρες μετά την εγγραφή του χρήστη. Το 2 να στέλνεται 10 μέρες μετά, κ.λπ.
Οπότε χρειάζεται να ξέρει για κάθε χρήστη ποιά emails έχουν σταλεί και ποιά όχι.
Οκ, δεν βλέπω τι αλλάζει στη διαδικασία που περιέγραψα. Κάτι τέτοιο εννοώ κι εγώ, απλά υποθέτω ότι είναι λίγο απίθανο να στέλνεται πχ πανομοιότυπο subject/body σε κάθε χρήστη. Όλο και κάπου θα αλλάζει. Αλλά ακόμα και έτσι να είναι, οι αλλαγές στη ΒΔ είναι μικρές (+1 πίνακας συσχέτισης).
dva_dev έγραψε:Τώρα δεν ξέρω κάθε πότε προσθέτει emails, πόσο συχνά μπαίνουν νέοι χρήστες, πράγματα που γενικά είναι μάλλον λειτουργική συμπεριφορά του site, οπότε ίσως να εξυπηρετεί το να υπολογίζεις ανά τακτά διαστήματα τι emails πρέπει να φύγουν, ίσως όμως να είναι πρακτικότερο να γίνεται υπολογισμός στο runtime εκείνη την ώρα τρέχοντας κάποιο μικρό (αν γίνεται) query.
Όσο συχνά και να προσθέτει νέα emails, η διαδικασία ανάγεται σε insert στον αντίστοιχο πίνακα (αντίστοιχους πίνακες). Από κει και πέρα αναλαμβάνει ο cron, που ήδη τρέχει ανά 24h.
Σε κάθε περίπτωση, και αφού ήδη από την εγγραφή του χρήστη η ημερομηνία εγγραφής είναι συγκεκριμένη και στατική, ο υπολογισμός του sched_time είναι απλός, και η χρήση του απλοποιεί πολύ την query για τα μηνύματα που πρέπει να σταλούν.

Ένα δείγμα δεδομένων ίσως να ξεκαθάριζε το τοπίο.

Άβαταρ μέλους
jpk
Δημοσιεύσεις: 441
Εγγραφή: 09 Μαρ 2011 21:17

Ποιες if/κώδικα πρέπει να τρέξω;

Δημοσίευση από jpk » 14 Αύγ 2013 16:29

philos υπάρχουν δύο περιπτώσεις για εμένα . Η πρώτη είναι ότι δεν είσαι υπεύθυνος για αυτή την αρχιτεκτονική δόμηση των δεδομένων , αυτή σου δόθηκε με αυτή πρέπει να δουλέψεις οπότε να δούμε πως θα μπορούσε ένα after_x_weeks πεδίο να αποκτούσε πραγματική λογική.

Το δεύτερο είναι , αν όχι να είσαι υπεύθυνος για αυτή την σχεδίαση , αν μη τι άλλο να μπορείς να την αλλάξεις. Εκεί θα χρησίμευε να κόψεις την λογική σε μικρότερα κομμάτια , τόσο σε επίπεδο αρχιτεκτονικής δόμησης των δεδομένων όσο και εφαρμογής. Ακούστηκαν κάποιες λύσεις που θα έκαναν την δουλειά, μια ακόμα θα ήταν ο δυναμικός πίνακας μηνυμάτων με ένα απλό template system για το body (π.χ. <name_of_user>) ή για τον τίτλο του μηνύματος μαζί με το την απόσταση σε timestamp που αποστέλλεται σε σχέση με την εγγραφή του χρήστη.

Κάτι τέτοιο θα σου επέτρεπε τόσο σε επίπεδο εφαρμογής να κάνεις εύκολη την επεξεργασία αυτών των μηνυμάτων για τον διαχειριστή όσο και για το job. Δεν είναι πολύ διαφορετική απάντηση από αυτές που σου έχουν δοθεί ήδη , αλλά επειδή μπορεί να έχεις λόγο για την χρήση του πεδίου after_x_weeks και μπορεί να σου επιβληθεί προγραμματιστικά ή σε δόμηση δεδομένων να το ξαναδούμε .

(όσο αφορά τα TABLE_PREFIX που λες είναι γρήγορο και βρώμικο , κάποτε σε αυτό το forum είχα προτείνει κάτι ανάλογο σε κάποιον που ήθελε να κάνει γρήγορα την δουλειά , αλλά για να είμαστε ειλικρινείς είναι από αυτά που είναι , γρήγορο ναι , πρόχειρο ναι)

Απάντηση

Επιστροφή στο “PHP Προγραμματισμός”

Μέλη σε σύνδεση

Μέλη σε αυτήν τη Δ. Συζήτηση: Δεν υπάρχουν εγγεγραμμένα μέλη και 0 επισκέπτες