Bonjour,

Voila je rencontre un petit problème avec mon code.

Ce que je fais

Actuellement je génère des fichiers Excel que j'envoi ensuite par email de façon automatisée, dans le même script.
Le tout prend quelques minutes. Aussi, pour éviter de se trouver dans un risque de timeout (cequi qui arrive couramment vu le délai nécessaire), je passe en php-cli qui résoud le problème. L'inconvénient c'est que je ne peux lancer l'opération que de ma machine alors qu'en mode web, ça laisse plus de flexibilité.

Ce que je veux

Je voudrais donc découper la tâche en lot de X fichiers. Quelle serait la meilleure façon de faire ?
Via de l'Ajax ?
Y'a-t-il des tutos quelque part dans ce genre ?

Merci.

4 réponses


Bonjour.
Lorsque tu dis :

de façon automatisée

Veux-tu dire que le script s'effectue sans aucune intéraction nécessaire d'un utilisateur ?
Car si c'est le cas, l'ajax ne t'aidera pas étant donné que l'ajax et donc le javascript est un langage côté client et non côté serveur.
Quand tu parle de lots de fichiers, si c'est un fichier par mail, il te suffit par exemple de récupérer les addresses emails et leur fichier en les groupant puis à chaque groupe de mettre le script en sommeil pendant un certain temps, exemple :

$records = $db->query('SELECT email, file FROM users'); // Récupération de tous les enregistrements nécéssaires
$groups = array_chunk($records, 10); // On groupe les enregistrements par 10
foreach ($groups as $group) // On boucle sur les groupes pour n'en récupérer qu'un
{
    foreach ($group as $record) // On boucle sur le groupe pour ne récupérer qu'un enregistrement
    {
        // Ton code qui envoi un mail avec le fichier
    }
    // Ici un groupe de 10 enregistrements s'est effectué, on met le script en sommeil pendant 10 secondes
    sleep(10);
    // À la fin des dix secondes le script continue en passant au groupe des 10 suivants
}

Bonjour, j'ai fais un script cet été qui pourrai ressembler à ta demande.
Mon script fonctionne avec les tâches CRON & fonctionne simplement en générant un fichier qui gère le nombre de mails envoyés actuellement.
Je te partage ça :

<?php
/**
 * Created by PhpStorm for fenyx.
 *
 * \______   \_______  ____ |  | __ ____   ____ \_   _____/|__|  |   ____   ______
 * |    |  _/\_  __ \/  _ \|  |/ // __ \ /    \ |    __)  |  |  | _/ __ \ /  ___/
 * |    |   \ |  | \(  <_> )    <\  ___/|   |  \|     \   |  |  |_\  ___/ \___ \
 * |______  / |__|   \____/|__|_ \\___  >___|  /\___  /   |__|____/\___  >____  >
 * \/                    \/    \/     \/     \/                 \/     \/
 * __      _______________________  _________._________________________ _________
 * /  \    /  \_   _____/\______   \/   _____/|   \__    ___/\_   _____//   _____/
 * \   \/\/   /|    __)_  |    |  _/\_____  \ |   | |    |    |    __)_ \_____  \
 * \        / |        \ |    |   \/        \|   | |    |    |        \/        \
 * \__/\  / /_______  / |______  /_______  /|___| |____|   /_______  /_______  /
 * \/          \/         \/        \/                        \/        \/
 * Email : commandes.broken@gmail.com
 * Author: BrokenFiles_
 * Date: 19/07/2018
 * Time: 10:48
 */

// cette config sert juste aux tests, bien évidemment tu vires toute la partie récup de PDO
// et config

// la classe mailer simule juste un mailer donc osef

Class Mailer
{

    public function send($passwd, $j, $data) // le mailer imite une classe qui envoie des mails
    {
        echo("Mail envoyé à {$j} ({$data['id']})!<br>");
    }

}

Class Cron
{

    private $finalEmail; //cet email envoie un mail lors ce que la tâche est terminée

    /**
     * Cron constructor.
     */
    public function __construct()
    {
        $this->mailer = new Mailer();
        $this->sql = new PDO("mysql:host={$this->config['host']};dbname={$this->config['db']}", $this->config['user'], $this->config['password']);
        //jusqu ici

        $this->finalEmail = 'ton email final'; //TODO : ça tu remplie
    }

    /**
     * envoie des mails
     * @param int $x
     * @param int $limit
     */
    public function sendMails(int $x, int $limit = 100)
    {
        $data = $this->recupData();
        $x += $data['current'];
        if($x < $data['total']){
            $y = $x + $limit;
            $this->write($y);
            $mails = $this->getMails($x, $limit);
            foreach ($mails as $mail) {
                $this->mailer->send('slt', $mail, [
                    'data' => 'SALUT!',
                    'bbc' => array('yo@gmail.com'),
                    'title' => 'salut salut'
                ]);
            }
        }else{
            $this->mailer->send("c'est envoyé à tt le monde!", $this->finalEmail, [
                'id' => 0,
                'data' => 'data',
                'bbc' => array('yo@gmail.com'),
                'title' => 'salut salut'
            ]);
        }
    }

    /**
     * récupération des adresses mails dans ta bdd
     * @param int $x
     * @param int $limit
     * @return array
     */
    public function getMails(int $x, int $limit): array
    {
        $mails = array();
        $request = $this->SQL()->query("SELECT * FROM mails LIMIT {$x}, {$limit}");
        $request->setFetchMode(PDO::FETCH_ASSOC);
        foreach ($request->fetchAll() as $mail) {
            $mails[] = $mail['mail'];
        }
        return $mails;
    }

    /**
     * décupération des données utiles pour le bon fonctionnement
     * @return array
     */
    public function recupData(): array
    {
        $file = fopen('mail.txt', 'r+');
        $data = [
            'total' => 0,
            'current' => 0
        ];
        $res = intval(fgets($file));
        $data['current'] = $res;
        $data['total'] = $this->getTotalMails();
        fclose($file);
        return $data;
    }

    /**
     * récupération du nombre total de mails inscrits
     * @return int
     */
    public function getTotalMails(): int
    {
        $query = $this->SQL()->query("SELECT * FROM mails");
        $res = $query->fetchAll();
        return count($res);
    }

    /**
     * écrire dans le fichier mail.txt
     * @param int $val
     */
    public function write(int $val)
    {
        $file = fopen('mail.txt', 'r+');
        fseek($file, 0);
        fputs($file, $val);
        fclose($file);
    }

}

Ce script nécessite de créer un fichier dans le même dossier se nommant "mail.txt" et dedans, il faut mettre 1 par défaut.
Il ne faut pas oublier de lancer ce script avec des tâches CRON toutes les 5-10 minutes.
J'espère avoir pu t'aider.
Bonne journée.

__@BrokenFiles__ : Est-ce que ça ne te dérange pas de partager un script aussi mal écrit ?
Tu utilises ou cherches à definir des propriétés qui n'existent pas dans la classe concernée, en plus de ça, il y en a une
(sql)_, qui en plus de passer de sql à SQL, deviens tout d'un coup une méthode.
En plus de ça, quel est l'intérêt de sélectionner tous les champs de la table si ce n'est pour n'en utiliser qu'un, sans compter qu'au lieu d'utiliser la fonction count juste après avoir récupéré les résultats dans la base de données, tu pourrais plutôt utiliser la méthode columnCount, tu pourrais donc facilement modifier ta fonction par :

public function getTotalMails(): int
{
    $query = $this->SQL()->query("SELECT mail FROM mails");
    return $query->columnCount();
}

De toute manière, l'auteur du sujet ne semble pas s'intéresser aux réponses qui lui sont apportées étant donné que depuis 7 jours, soit depuis qu'il à créé son sujet et que je lui ait répondu, il n'a pas répondu à mes questions.

@Lartak
Bonsoir, j'ai juste partagé un script qui pouvait l'aider car je l'avais sous la main.
Je suis bien au courant que ce script n'était pas optimisé je partageais juste car je pensais pouvoir faire plaisir.
Les propriétés ($this->SQL()) et les autres non définies dans la classe concernée sont justes là pour être remplacées !
Je précise que j'ai oublié d'enlever des lignes (comme le $this->sql) qui était là pour mes tests j'imagine.
Mais je ne comptais pas faire un script utilisable sur-le-champ mais juste pour qu'il puisse comprendre comment cela pourrait fonctionner au niveau logique.

Bonne soirée tout de même