Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Algunos contenidos no se actualizan al renderizar una plantilla Symfony con Ajax

21 de febrero de 2015

Muy buenas,

Estoy teniendo muchos problemas cuando intento publicar en este caso un comentario que lleva fotos a través del método $.ajax de jQuery.

Todo me lo hace bien menos renderizarme las fotos en tiempo real a través del formulario, porque el comentario con su contenido y la fecha y todo me lo muestra perfecto. Es a la hora de las fotos, sólo me las muestra cuando actualizo la página, pero con Ajax no lo hace y eso que me las guarda perfectamente.

Estoy utilizando symfony 2.6.4 y este es mi código:

Javascript:

$.ajax({
    url: Routing.generate('comment_new_form'),
    data: $data,
    cache: false,
    dataType: 'html',
    contentType: false,
    processData: false,
    type: "POST",
    success: function(data) {
        if (data) {
            $form.remove();
            $reply.html(data);
            $('#comment_thread').find('.comment_replying').removeClass('comment_replying');
        } else {
            return false;
        }
    },
    error: function() {
        alert("Ha ocurrido un error, vuelve a intentarlo");
    },
 
});

Código PHP de la ruta Ajax:

public function newFormAction(Request $request)
{
    $user = $this->get('security.context')->getToken()->getUser();
 
    if (!$this->getRequest()->isXmlHttpRequest() OR !$user) {
        // check if request is AJAX request, if not redirect
        return new Response(json_encode(array('error' => 'Sólo respondo consultas vía AJAX.')));
    }
 
    // más datos......
    $em = $this->getDoctrine()->getManager();
    $comment = new Comment();
    $comment->setMessages($message);
    $comment->setUser($user);
    $comment->setParent($CommentRoot);
    $comment->setRoot($message_id);
    $comment->setBody($body);
 
    $em->persist($comment);
    $em->flush();
 
    $iFoto = 1;
 
    if ($fotos[0]) {
        foreach ($fotos as $foto) {
            $fotoEntity = new Fotos();
            list($width, $height, $type, $attr) = getimagesize($foto->getPathname());
 
            $nombreFotoSlug = str_replace(
                pathinfo($foto->getClientOriginalName(), PATHINFO_EXTENSION),
                "",
                $foto->getClientOriginalName()
            );
            $nombreFoto = Util::getSlug($nombreFotoSlug);
 
            $nombreArchivoFoto = $nombreFoto . "." . $foto->guessExtension();
 
            $directorio = "fotos/messages/$message_id/comments";
 
            // Guardamos todos los datos en la tabla fotos y guardamos la
            // fotos en la carpeta correspondiente.
 
            $foto->move($directorio, $nombreArchivoFoto);
            $fotoEntity->setRutaFoto($nombreArchivoFoto);
            $fotoEntity->setAlto($height);
            $fotoEntity->setAncho($width);
            $fotoEntity->setUser($user);
            $fotoEntity->setMessages($message);
            $fotoEntity->setComments($comment);
            $fotoEntity->setNumero($iFoto);
 
            $iFoto++;
            $em->persist($fotoEntity);
            $em->flush();
        }
    }
 
    $CommentNew = $em
        ->getRepository('AcmeCommentBundle:Comment')
        ->find($comment->getId());
 
    $template = $this->render(
        'AcmeCommentBundle:Comment:comment_ajax.html.twig',
        array(
            'entity' => $message,
            'comment' => $CommentNew,
        )
    );
 
    return new Response($template->getContent(), 200);
}

Plantilla Twig:

<div id="comment_{{ comment.id }}" class="comment_show comment_depth_">
    <div id="comment_body_{{ comment.id }}" class="comment_body">
        <div itemscope="" itemtype="http://schema.org/Person">
            {% set urluser=url('perfil', {'user': comment.user.getUsernameCanonical()}) %}
            <a title="{{ comment.userName | capitalize}} " itemprop="url" href="{{utils.getUrl(urluser)}}">
                {{ comment.userName  | capitalize }}
                <img sitemprop="image" src="{{ comment.user.rutaFoto | imagine_filter('my_thumb') }}" alt=" {{ comment.userName| capitalize }} " title="{{ comment.userName | capitalize}} " class="avatar">
            </a>
        </div>
 
        <p>{{ comment.body | nl2br }}</p>
 
        <div class="ago">
            <p> Publicado {{ time_diff(comment.createdAt)}}</p>
        </div>
 
        {% if comment.getFotos() %}
        <div class="galeria row clearfix" itemscope="" itemtype="http://schema.org/photos">
            <div class="col-md-12 efecto" data-liffect="zoomIn">
                {% set fotoShare = '' %}
                {% set foto = '' %}
                {% for image in comment.getFotos() %}
                    {% if loop.index ==1 %}
                        {% set fotoShare = url('home') ~ image.rutaFotoComment %}
                        {% set foto = url('foto', {'slug':entity.url}) %}
                    {% else %}
                        {% set foto = url('foto_pagination', {'slug':entity.url,'page':image.numero}) %}
                    {% endif %}
                    <div class="marco-foto" itemprop="photo" itemscope="" itemtype="http://schema.org/ImageObject">
                        {% set nombreFoto = 'Foto comentario  ' ~ loop.index ~ ' del viaje ' ~ entity.titulo|capitalize ~  ' - ' ~  comment.user.getUsername() | capitalize %}
                        {% if image.nombre %}
                            {% set nombreFoto = image.nombre ~ ', Foto comentario ' ~ loop.index ~ ' ' ~ entity.titulo|capitalize ~  ' ' ~  comment.user.getUsername() | capitalize %}
                        {% endif %}
                        <a title="{{nombreFoto}}" itemprop="url" class="fancybox" href="{{asset(image.rutaFotoComment)}}">
                            <img itemprop="contentURL" src="{{ image.rutaFotoComment | imagine_filter('my_thumb') }}" alt="{{nombreFoto}}" title="{{nombreFoto}}">
                        </a>
                    </div>
                {% endfor %}
            </div>
        </div>
 
    </div>
    {% endif %}
</div>
 
<div class="comment_reply">
    <button data-user-id="{{ comment.user.id }}" data-message-id="{{entity.id}}" data-parent-id="{{ comment.id }}"
            class="comment_reply_show_form btn btn-primary">Responder</button>
</div>
 
<div class="comment_replies"></div>

Espero que con esto sea suficiente para que me ayudar con el problema.

Gracias por todo.


Respuestas

#1

Una pregunta rápida: si pruebas a quitar el filtro imagine_filter en la plantilla que muestra el comentario, ¿se sigue produciendo el mismo error?

@javiereguiluz

21 febrero 2015, 15:47
#2

Gracias Javier,

Pero lo he quitado y lo mismo. Por alguna razón desconocida el array de fotos relacionada con los comentarios viene vació. Te pongo el código donde hago dump en mi plantilla_ajax.html.twig y luego la captura del objeto fotos.

{% if comment.getFotos() %}
 
            {{dump( comment)}}
 
            <div class="galeria row clearfix" itemscope="" itemtype="http://schema.org/photos">
                <div class="col-md-12 efecto" data-liffect="zoomIn">
                   {% set fotoShare = '' %}    
                    {% set foto = '' %}    
                        {% for image in comment.getFotos() %}

El {{ dump( comment) }} me muestra lo siguiente: el ArrayCollection vacío. La verdad esto es muy raro, por cierto dentro del for no entra {% for image in comment.getFotos() %}

@jcarlosweb

21 febrero 2015, 22:50
#3

Buenas, no estoy muy seguro de que con $.ajax puedas subir imágenes al servidor.

En el controlador veo que tienes if ($fotos[0]) {... pero no se ve de donde viene la variable $fotos, si puedes muéstranos como obtienes dicha variable.

Además puedes hacer estos dumps y nos muestras:

dump($fotos, $request->files->all(), $_FILES);

Saludos!

@manuel_j555

22 febrero 2015, 0:44
#4

Hola Manuel,

Sí se puede con HTML5 Form Data

El objeto lo recojo de la siguiente forma:

$fotos  = $request->files->get('acme_commentbundle_comment')['fotos'];

Lo sube correctamente porque cuando actualizo la página muestra las fotos perfectamente sin Ajax. Esto quiere decir que las fotos se han subido correctamente tanto a la base de datos y a su carpeta correspondiente.

El problema viene por $ajax que es super rarísimo. Te muestro los dumps que me has pedido

Si necesitas que enseñe más código me avisas.

@jcarlosweb

22 febrero 2015, 2:22
#5

Ok, gracias por la info.

En tu controlador veo que recorres las fotos y llamas al setComments($comment) en cada instancia de $fotoEntity, pero no haces la asociación inversa $comment->addFotos($fotoEntity).

Entonces aunque hagas lo siguiente luego de todos los persist:

$CommentNew = $em
        ->getRepository('AcmeCommentBundle:Comment')
        ->find($comment->getId());

Me parece que el método find() realmente no está ejecutando ninguna consulta, porque ya la entidad comment está manejada en el EntityManager, por lo que la colección de fotos en el objeto $CommentNew tiene los mismos valores que cuando hiciste el persist de $comment.

Prueba con el $comment->addFotos($fotoEntity) y nos avisas.

Saludos!

@manuel_j555

22 febrero 2015, 2:42
#6

Manuel, si ahí estaba el problema, que tonto fui.

Solo una cosa para entender el problema que he tenido.

Entonces lo que hace $comment->addFotos($fotoEntity) ¿es solo añadir las fotos al objeto actual de comment?

Muchas gracias Manuel, me has salvado ♥

@jcarlosweb

22 febrero 2015, 11:33
#7

Basicamente si, pero además te da un poco más de control de que fotos se asociarán realmente al $comment.

Hay ejemplos de código donde en el addXXX() verificas que no exista ya un elemento con cierta característica en la colección; si existe no se añade. También en mi caso, he tenido campos que dependen de cálculos que se realizan en colecciones, como sumatorios de costos (esto lo hago en el @PrePersist de la entidad), entre otros.

Saludos!

@manuel_j555

22 febrero 2015, 15:28
#8

Gracias Manuel por la explicación. Como siempre un gusto.

@jcarlosweb

23 febrero 2015, 19:36