Foros del Web » Programando para Internet » PHP »

problemas con while (newsletter)

Estas en el tema de problemas con while (newsletter) en el foro de PHP en Foros del Web. Hola, cómo están? Bueno, cuando no yo con dudas, eh? Paso a contarles: He diseñado un lindo sistema de lista de noticias, o newsletter, en ...
  #1 (permalink)  
Antiguo 28/05/2005, 12:53
Avatar de nachopro  
Fecha de Ingreso: noviembre-2003
Ubicación: Haedo, Bs. As.
Mensajes: 290
Antigüedad: 20 años, 4 meses
Puntos: 2
problemas con while (newsletter)

Hola, cómo están?

Bueno, cuando no yo con dudas, eh?

Paso a contarles: He diseñado un lindo sistema de lista de noticias, o newsletter, en PHP y funciona así:
De un formulario con datos el mensaje que quiero enviar se aloja en un registro de la tabla "mensajes".
Luego se llama a otra hoja PHP que va leyendo las direcciones de mails de la tabla "lista" y envía el mensaje que antes escribí (leyéndolo de la tabla).

pero qué pasa? con varias direcciones, 1) el servidor smtp se satura.. 2) la ejecución del PHP caduca a los 30 segundos..

intené que el while trabaje con una variable $_GET para que por cada vez que se cargue el script php se envíe sólo un mail pero tengo problemas con esto último.. les paso mi código:

Código PHP:
<? require("../base/db.php");
$result=mysql_query("select count(*) from lista",$link); //cuenta la cantidad de destinatarios
$cant_mail=mysql_result($result,0);
while(
$id<=$cant_mail) { //mientras que ID sea menor o igual a la cantidad, ejecuta
 
$con_lis=mysql_query("select lis_dir, lis_act from lista where id_lis = $id",$link); //leé el e-mail y su estado
 
while($row=mysql_fetch_array($con_lis)) {
  if(
$row['lis_act']==1){ //el campo list_act está activo ?? se le manda mail
    
$destinatario=$row['lis_dir'];
    
$con_msg=mysql_query("select * from mensajes where id_msg = 1",$link); //se lee el mail a enviar y se ejecuta la función mail()
    
while($row=mysql_fetch_array($con_msg)) {
        
$from0=$row['msg_rnom'];
        
$from1=$row['msg_rdir'];
        
$from3=$row['msg_rres'];
        
$asunto=$row['msg_asu'];
        
$mensaje=$row['msg_msg'];
        
$ldc_msg_enc="From: $from0 <$from1>\nReply-To: $from3\nMIME-Version: 1.0\nContent-Type: text/plain";
        
mail("$destinatario""$asunto","$mensaje","$ldc_msg_enc");
        echo 
"se maileó a ".$destinatario."<br>";
        }
     }
  else {
     echo 
$row['lis_dir']." está inactivo<br>"// el campo lis_act está en 0 (el usuario se desuscribió)
  
}
 }
 
$id++;
 
//Header(); << header no funciona, cómo puedo redireccionar a url/batch.php?id ????
}
?>
Justo al final, en el //Header() es donde necesito redireccionar
de modo contrario, el PHP ejecuta las acciones descriptas con tooodaa la lista de mails...

al margen de eso.. además de un sleep(2); (para no saturar el servidor SMTP) se les ocurre alguna mejora??

espero que les sea útil este básico pero útil código
  #2 (permalink)  
Antiguo 28/05/2005, 16:25
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 20 años, 6 meses
Puntos: 41
Primero:
Haces una consulta de más a la base de datos:
"select * from mensajes where id_msg = 1"
La haces en cada pasada del bucle while. Si siempre es el mismo (id_msg=1) entonces basta con que hagas la consulta una vez. Ahí ya estás ahorrando algo.

Segundo:
No hace falta que también leas los que tienen lis_act desactivada simplemente lee los que lo tienen activo y les envías el email. Ahí también estás ahorrando.

Tercero:
Puedes hacer una especie de Paginación y enviar los mails de "n" en "n".

Saludos
  #3 (permalink)  
Antiguo 28/05/2005, 17:49
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 20 años, 6 meses
Puntos: 41
No he probado esto... pero es más o menos a lo que me refiero.
Lo que he hecho primero es calcular todas las variables comunesa todas las páginas y propagarlas en variables de sesión.
Código PHP:
<?php
session_start
();
// Identificador del mensaje en la base de datos
$id_msg 1;

// Cantidad de registros por bloque
$registros_por_bloque 20// O sea, se enviarán los mails de 20 en 20 

// Determinar el boque actual
if (empty($_GET['bloque'])){
    
$actual 1;
}else{
       
$actual $_GET['bloque'];
}

// Si es el primer bloque, calculamos todos los parámetros comunes.
if($actual == 1){
    
// Información sobre el mensaje que se quiere enviar
    
$sql_msg "SELECT * FROM mensajes WHERE id_msg = $id_msg";
    
$msg_result mysql_query($sql_msg) or die("Error en <b>$sql_msg</b> ::"mysql_error());
    if(
$msg_row mysql_fetch_assoc($msg_result)){
        
$_SESSION['msg_asunto'] = $msg_row['msg_asu'];
        
$_SESSION['msg_mensaje'] = $msg_row['msg_msg'];
        
$_SESSION['msg_headers'] = "From: ".$msg_row['msg_rnom']." <".$msg_row['msg_rdir'].">\nReply-To: ".$msg_row['msg_rres']."\nMIME-Version: 1.0\nContent-Type: text/plain";
    }else{
        die(
"No se hallaron registros para id_msg = $id_msg");
    }

    
// Cantidad de destinatarios activos
    
$sql_count "SELECT COUNT(*) FROM lista WHERE lis_act = 1";
    
$count_result mysql_query($_sql_count$link); //cuenta la cantidad de destinatarios
    
$total_registros mysql_result($_pagi_count_result0);
    
    
// Cantidad de "Páginas" o "Bloques"
    
$_SESSION['total_bloques'] = ceil($total_registros $registros_por_bloque);
}
// ------------------------------------------------

$inicial = ($actual-1) * $registros_por_bloque;
$sql "SELECT lis_dir, lis_act FROM lista WHERE lis_act = 1 LIMIT $inicial,$registros_por_bloque";
$result mysql_query($sql) or die("Error en <b>$sql</b> ::"mysql_error());
while(
$row mysql_fetch_assoc($result)){
    
$destinatario $row['lis_dir'];
    
mail($destinatario$_SESSION['msg_asunto'], $_SESSION['msg_mensaje'], $_SESSION['msg_headers']))
}

// ------------------------------------------------

$bloque_siguiente $bloque_actual 1;
if(
$bloque_siguiente $_SESSION['total_bloques']){
    
// Si hay más bloques, pasamos al siguiente.
    
header("Location : ".$_SERVER['PHP_SELF']."?bloque=$bloque_siguiente");
}else{
    
// Si no hay más bloques, redireccionamos a otra parte.
    
header("Location : otra.php");
}
?>
Saludos
  #4 (permalink)  
Antiguo 29/05/2005, 15:45
Avatar de nachopro  
Fecha de Ingreso: noviembre-2003
Ubicación: Haedo, Bs. As.
Mensajes: 290
Antigüedad: 20 años, 4 meses
Puntos: 2
jpineado es muy interesante el script

logré corregirle cosas respecto a variables y unas cositas..
pero aquí me trabo:
Código PHP:
$inicial = ($actual-1) * $registros_por_bloque;
$sql "SELECT lis_dir, lis_act FROM lista WHERE lis_act = 1 LIMIT $inicial,$registros_por_bloque"
me puedes dar una mano con esto?
de donde sale el $actual y porqué se le resta 1 ??

gracias
  #5 (permalink)  
Antiguo 29/05/2005, 15:57
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 20 años, 6 meses
Puntos: 41
$actual :
Es el número del bloque que se va a enviar en esta "pasada". Se obtiene por url de la variable $_GET['bloque'].

$inicial :
Es el primer registro de este bloque. Es desde donde se empieza a leer de la BD. Necesario para la cláusula "LIMIT" del sql. Se resta 1 porque tus bloques están numerados desde el 1 hasta el $_SESSION['total_bloques']. En cambio los registros en la BD empiezan numerados desde el CERO.

Saludos
  #6 (permalink)  
Antiguo 29/05/2005, 16:12
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 20 años, 6 meses
Puntos: 41
Cita:
Iniciado por nachopro
(...)logré corregirle cosas respecto a variables y unas cositas..
Me gustaría saber las cosas que has modificado para poder dejarlo listo para quien le sirva.

Saludos
  #7 (permalink)  
Antiguo 29/05/2005, 16:24
Avatar de nachopro  
Fecha de Ingreso: noviembre-2003
Ubicación: Haedo, Bs. As.
Mensajes: 290
Antigüedad: 20 años, 4 meses
Puntos: 2
bueno, todo va tomando color... sólo un problemita
no se redirecciona.. a ver que puede andar pasando???

Código PHP:
$bloque_siguiente $bloque 1;
if(
$bloque_siguiente $_SESSION['total_bloques']){
    
// Si hay más bloques, pasamos al siguiente.
    
header("Location : batch_mandar.php?id=$id_msg&bloque=$bloque_siguiente"); //$id_msg
// viene dado por la página en la cual se elije el mensaje
a enviar y el mismo se asigna por _GET['id'];
}else{
    
// Si no hay más bloques, redireccionamos a otra parte.
    
header("Location : fin.php");

  #8 (permalink)  
Antiguo 29/05/2005, 16:31
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 20 años, 6 meses
Puntos: 41
Cita:
Iniciado por nachopro
(...)sólo un problemita
no se redirecciona.. a ver que puede andar pasando???
¿No redirecciona al bloque siguiente o no redirecciona al fin.php?
¿Entre las modificaciones no habrás puesto un "echo" u otra salida?

Sería bueno tener el código completo que estás utilizando.

Saludos
  #9 (permalink)  
Antiguo 29/05/2005, 16:49
Avatar de nachopro  
Fecha de Ingreso: noviembre-2003
Ubicación: Haedo, Bs. As.
Mensajes: 290
Antigüedad: 20 años, 4 meses
Puntos: 2
jiijijijij

no redirecciona a ningún header.. a ver.. te paso el código completo (puede uqe haya variado un poco)
incluso había unos echos, pero al anularlos sigue sin redireccionar.. el original que uso sería este:
Código PHP:
<? require("../base/db.php"); //datos para conectar a mysql
session_start(); //inicia sesion
$registros_por_bloque 1//pruebo con uno solo de momento
if (empty($_GET['bloque'])){
 
$actual 1;
}else{
 
$actual $_GET['bloque'];

if(
$actual == 1){
// contenido del mail
$id_msg=$_GET['id'];
$con_msg=mysql_query("select * from mensajes where id_msg = $id_msg",$link);
//consulta y asignación de variables
if ($row=mysql_fetch_assoc($con_msg)) {
$from0=$row['msg_rnom']; //remitente nombre
$from1=$row['msg_rdir']; //remitente mail
$from3=$row['msg_rres']; //remitente mail reply-to
// variables de sesion
$_SESSION['asunto']=$row['msg_asu']; //asunto del msg
$_SESSION['mensaje']=$row['msg_msg']; //msg
$_SESSION['ldc_msg_enc']="From: $from0 <$from1>\nReply-To: $from3\nMIME-Version: 1.0\nContent-Type: text/plain"// header
}
else { die(
"error al el mensaje"); }
// cantidad de destinatarios
$contar=mysql_query("select count(*) from lista where lis_act = 1",$link);
$cantreg=mysql_result($contar0);
// variables de sesion
$_SESSION['cantbloques']=ceil($cantreg/$registros_por_bloque);
}
// comienzo de batch para enviar
$inicial=($bloque-1)*$registros_por_bloque//valor por el cual iniciar la seleccion de registros
$sql "select lis_dir from lista where lis_act = 1 limit $inicial,$registros_por_bloque";
$result mysql_query($sql,$link) or die("Error en <b>$sql</b> ::"mysql_error());
while(
$row mysql_fetch_assoc($result)){
$destinatario $row['lis_dir'];
mail($destinatario$_SESSION['msg_asunto'], $_SESSION['msg_mensaje'], $_SESSION['msg_headers']); //envía mail
}
// --aquí comienzan los problemas, ya que parece no funcionar
$bloque_siguiente $bloque 1;
if(
$bloque_siguiente $_SESSION['cantbloques']){
    
// Si hay más bloques, pasamos al siguiente.
    
header("Location : batch_mandar.php?id=$id_msg&bloque=$bloque_siguiente");
}else{
    
// Si no hay más bloques, redireccionamos a otra parte.
    
header("Location : fin.php");
}
?>
espero que sea fácil de desifrar.. gracias
  #10 (permalink)  
Antiguo 29/05/2005, 16:55
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 20 años, 6 meses
Puntos: 41
Bueno... voy a revisar un poco el código... mientras tanto sería bueno que agregues la línea
Código PHP:
error_reporting(E_ALL); 
Al comienzo del script (antes de la conexión a la BD). Postea si te muestra algún mensaje de error, que nos ahorraría la "búsqueda a ciegas".

Saludos
  #11 (permalink)  
Antiguo 29/05/2005, 17:14
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 20 años, 6 meses
Puntos: 41
No entiendo las modificaciones que has hecho... el tema de cambiarle de nombre a algunas variables es cuestión de gustos... pero:

¿De dónde obtienes la variable $bloque?
Si no quieres llamarla $actual, entonces deberás renombrar todas las apariciones de $actual por $bloque, porque si no, sólo funcionaría bajo la directiva register globals en ON.

¿Por qué quitaste el "or die()" de la primera consulta?
Eso hace que no veamos posibles errores que puedan estar ocurriendo en ese punto. Puedes quitarlo (o mejor, modificar la salida) cuando ya lo tengas operativo y en línea. Pero por ahora, deberías dejarlo.

¿Por qué utilizar las variables $from0, $from1, $from3?
Como yo lo había puesto, se generaba directamente la cadena de headers y se almacenaba en una variable de sesión. Esas variables son innecesarias. recuerda que lo que quieres es ahorrar tiempo de ejecución.

Esos son los comentarios por ahora.
Sobre lo del redireccionamiento, ni idea. Postea los mensajes de error que te aparecen.
Recuerda que no debe haber nada de HTML ni espacios en blanco antes de "<?php" ni después de "?>" (Sobretodo verifica esto en el archivo "../base/db.php").

Saludos
  #12 (permalink)  
Antiguo 29/05/2005, 17:48
Avatar de nachopro  
Fecha de Ingreso: noviembre-2003
Ubicación: Haedo, Bs. As.
Mensajes: 290
Antigüedad: 20 años, 4 meses
Puntos: 2
Hola, disculpa, te respondo
Cita:
¿De dónde obtienes la variable $bloque?
fue un error mío de interpretación.
Cita:
¿Por qué utilizar las variables $from0, $from1, $from3?
es por una hibriedad entre tu guión y el mío.

actualmente he copiado tal cual el script original que me has facilitado con lo siguientes modificaciones:

Código PHP:
01: <?php
??: $link=mysql_connect("localhost","root","") or die (mysql_error());
??: 
mysql_select_db("np2k5",$link) or die (mysql_error());
02session_start();
03// el resto sigue idéntico
--:
30$sql_count "SELECT COUNT(*) FROM lista WHERE lis_act = 1";
31$count_result mysql_query($sql_count$link); //cuenta la cantidad de destinatarios
32$total_registros mysql_result($count_result0);
--:
50$bloque_siguiente $actual 1//origmente se llamaba bloque_actual, pero no estaba definida, porlo que interpreto que se refiere a actual ;)
Aclaración:
??: Líneas de conexión al MySQL
31, 32 y 50 Corrección de variables que incluían un _ en su inicio

con esto descarto errores entre mi guión y el tuyo, dejando el tuyo 100% original.

por desgracia sigue sin andar el header();

(perdón si te hice chivar con lo de las variables


al margen, podrías recomendarme algún entorno de desarrollo un poco más potente que el Bloc de notas que incluye Windows?? jeje

Última edición por nachopro; 29/05/2005 a las 18:09
  #13 (permalink)  
Antiguo 29/05/2005, 18:04
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 20 años, 6 meses
Puntos: 41
Es que es rarísimo que no funcione el header() y no te dé ningún mensaje de error.
¿Probaste a poner la línea que te dije?
Código PHP:
<?php
error_reporting
(E_ALL); // AGREGA ESTA LÍNEA
$link=mysql_connect("localhost","root","") or die (mysql_error());
// Todo el resto igual...
Debería darte algún mensaje de error.
Cita:
Iniciado por nachopro
al margen, podrías recomendarme algún entorno de desarrollo un poco más potente que el Bloc de notas que incluye Windows?? jeje
Puedes buscar por aquí:
http://www.forosdelweb.com/f18/mejor-editor-php-291403/

Saludos
  #14 (permalink)  
Antiguo 29/05/2005, 19:46
Avatar de nachopro  
Fecha de Ingreso: noviembre-2003
Ubicación: Haedo, Bs. As.
Mensajes: 290
Antigüedad: 20 años, 4 meses
Puntos: 2
We Are The Chamiones!!!

jpinedo.. no hay caso.. no me indica ningún error
momentooo!!!
LO LOGRAMOSSS!!!! YEAAAAAAAAAAAAAAHHHHHH

mirá lo que era.. jaja!!!
Código PHP:
$bloque_siguiente $actual 1;
if(
$bloque_siguiente <= $_SESSION['total_bloques']){ // antes tenía un > por lo que siempre se iba al else
    // Si hay más bloques, pasamos al siguiente.
    
header("Location : ".$_SERVER['PHP_SELF']."?bloque=$bloque_siguiente");
// aquí el problema "Location :" es distinto a "Location:" !!!
else{
    
// Si no hay más bloques, redireccionamos a otra parte.
    
header("Location : otra.php"); // aquí el problema "Location :" es distinto a "Location:" !!!

mil docientas gracias jpinedo

(estoy muy feliz, no??) jaja

bueno, ahora le daré una buena terminación y directo al FAQ de PHP, no te parece??

realmente EXCELENTE, te lo agradezco muchísimo
  #15 (permalink)  
Antiguo 29/05/2005, 20:22
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 20 años, 6 meses
Puntos: 41
jajajaja...
Esos son los errores más difíciles de ver...
Qué bueno que haya funcionado.... y cuando lo tengas listo, lo subes a las FAQ's.

Saludos
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 10:00.