2
\$\begingroup\$

How can I improve this code ? It was quite hard to implement AJAX comment system in Symfony 3, and result is a bit of mess:

Controller:

<?php
declare(strict_types = 1);
namespace AppBundle\Controller;

use AppBundle\Entity\Article;
use AppBundle\Entity\ArticleCategory;
use AppBundle\Entity\Comment;
use AppBundle\Entity\User;
use AppBundle\Entity\UserLikedArticles;
use AppBundle\Form\CommentFormType;
use AppBundle\Repository\ArticleRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

class ArticleController extends Controller
{
    /**
     * @Route("/articles/{category}", name="articles")
     */
    public function getArticles(string $category) : object
    {
        $em = $this->getDoctrine()->getManager();
        $categoryId = $em->getRepository('AppBundle:ArticleCategory')->getCategoryIdByCode($category);
        $articles = $em->getRepository('AppBundle:Article')->findAllByCategory((int)$categoryId);
        return $this->render('articles/articles.html.twig', [
            'articles' => $articles
        ]);
    }

    /**
     * @Route("/articles/{category}/{id}", name="article")
     */
    public function getArticle($category, $id)
    {
        $isFavourite = false;
        $isLikedArticle = false;
        $isUnlikedArticle = false;

        $articleRepo = $this->getDoctrine()->getRepository(Article::class);
        $article = $articleRepo->find($id);

        $categoryRepo = $this->getDoctrine()->getRepository(ArticleCategory::class);
        $categories = $categoryRepo->findAll();

        $categoryId = $categoryRepo->getCategoryIdByCode($category);
        $lastArticles = $articleRepo->getLimitArticlesByCategory((int)$categoryId, 3);

        $nextArticle = $articleRepo->getNextArticle((int)$categoryId, $id);
        $previousArticle = $articleRepo->getPreviousArticle((int)$categoryId, $id);

        if ($this->isGranted('ROLE_USER')) {
            $userRepo = $this->getDoctrine()->getRepository(User::class);
            $user = $this->getUser();
            $user = $userRepo->find($user->getId());
            $userFavouriteArticles = $user->getFavouriteArticles();

            $userLikedArticle = $this->getDoctrine()->getRepository('AppBundle:UserLikedArticles')
                ->findOneBy(array(
                    'userId' => $user,
                    'articleId' => $article,
                ));

            if ($userLikedArticle) {
                $userLikedArticle->getAppraisal() == 'like' ? $isLikedArticle = true : $isUnlikedArticle = true;
            }

            foreach ($userFavouriteArticles as $userFavouriteArticle) {
                if ($userFavouriteArticle->getId() == $id) {
                    $isFavourite = true;
                }
            }
        }

        if (is_null($nextArticle)) {
            $nextArticle = $articleRepo->getRandomArticle((int)$categoryId, $id);
        }

        if (is_null($previousArticle)) {
            $previousArticle = $articleRepo->getRandomArticle((int)$categoryId, $id);
        }

        $commentForm = $this->createForm(CommentFormType::class);

        return $this->render('articles/article.html.twig', [
            'article' => $article,
            'categories' => $categories,
            'lastArticles' => $lastArticles,
            'nextArticle' => $nextArticle,
            'previousArticle' => $previousArticle,
            'commentForm' => $commentForm->createView(),
            'isFavourite' => $isFavourite,
            'isLikedArticle' => $isLikedArticle,
            'isUnlikedArticle' => $isUnlikedArticle
        ]);
    }

    /**
     * @Route("/articles/{category}/{id}/addcomment/{replyToId}", defaults={"replyToId"=0}, name="addcomment")
     */
    public function addComment(Request $request, $category, $id, $replyToId)
    {
        $status = 'error';
        $message = '';

        if (!$this->isGranted('ROLE_USER')) {
            echo 'ne e lognat'; exit;
            $message = 'Трябва да се логнете, за да добавите нов коментар!';
        } else {
            $form = $this->createForm(CommentFormType::class);

            $form->handleRequest($request);
            if ($form->isSubmitted() && $form->isValid()) {

                $user = $this->getDoctrine()->getRepository("AppBundle:User")->find($this->getUser()->getId());

                $comment = $form->getData();
                $comment->setPerson($user);
                $comment->setReplyTo($replyToId);
                $comment->setPostId($id);
                $comment->setDateAdded(new \DateTime("now"));

                $em = $this->getDoctrine()->getManager();
                $article = $em->getRepository('AppBundle:Article')->find($id);
                $article->setComments($article->getComments() + 1);
                $em->persist($article);
                $em->persist($comment);
                try {
                    $em->flush();
                    $status = "success";
                    $message = "new comment was saved";
                } catch (\Exception $e) {
                    $message = $e->getMessage();
                }
            }
        }

        $response = array(
            'status' => $status,
            'message' => $message,
        );

        return new JsonResponse($response);
    }

    /**
     * @Route("/articles/{category}/{id}/addanswer/{replyToId}", defaults={"replyToId"=0}, name="addanswer")
     */
    public function addAnswer(Request $request, $category, $id, $replyToId)
    {
        $status = 'error';
        $message = '';

        if (!$this->isGranted('ROLE_USER')) {
            echo 'ne e lognat'; exit;
            $message = 'Трябва да се логнете, за да добавите нов отговор!';
        } else {
            $comment = new Comment();
            $comment->setContent($request->request->get('textarea-answer'));
            $comment->setPersonId($this->getUser()->getId());
            $comment->setReplyTo($replyToId);
            $comment->setPostId($id);
            $comment->setDateAdded(new \DateTime("now"));

            $em = $this->getDoctrine()->getManager();
            $em->persist($comment);
            try {
                $em->flush();
                $status = "success";
                $message = "new answer was saved";
            } catch (\Exception $e) {
                $message = $e->getMessage();
            }
        }

        $response = array(
            'status' => $status,
            'message' => $message,
        );

        return new JsonResponse($response);
    }

    /**
     * @Route("/articles/{category}/{id}/true/{page}", defaults={"page"=1}, name="articleAjax")
     */
    public function getArticleAjax($category, $id, $page)
    {
        $recordsPerPage = 10;
        $offset = ($page-1) * $recordsPerPage;

        $commentRepo = $this->getDoctrine()->getRepository(Comment::class);

        $countRecords = $commentRepo->countRecords($id);
        $totalPages = ceil($countRecords / $recordsPerPage);

        $articleRepo = $this->getDoctrine()->getRepository(Article::class);
        $article = $articleRepo->find($id);

        $comments = $commentRepo->getPaginationPost($recordsPerPage, $offset, $id);

        foreach ($comments as &$comment) {
            $subcomments = $commentRepo->getSubComments($comment['id']);
            $comment['subComments'] = $subcomments;
        }

        $response = [
            'comments' => $comments,
            'id' => $id,
            'totalPages' => $totalPages
        ];

        return new JsonResponse($response);
    }

    /**
     * @Route("subcomments/{commentId}/{lastAnswer}/{step}", defaults={"step"=2}, name="getSubcomments")
     */
    public function getMoreAnswers($commentId, $lastAnswer, $step)
    {
        $limit = 2;
        $commentRepo = $this->getDoctrine()->getRepository(Comment::class);
        $answers = $commentRepo->getMoreAnswers($commentId, $lastAnswer, $step, $limit);

        $step = $step+2;

        $response = [
            'answers' => $answers,
            'step' => $step
        ];

        return new JsonResponse($response);

    }

    /**
     * @Route("/articles/{category}/{id}/addtofavorites", name="addToFavourites")
     */
    public function addToFavourites($category, $id)
    {
        $em = $this->getDoctrine()->getManager();
        $article = $em->getRepository("AppBundle:Article")->find($id);
        $user = $this->getUser();
        $user = $em->getRepository("AppBundle:User")->find($user->getId());
        if (!$user->addFavouriteArticle($article)) {
            $article->setFavourites($article->getFavourites() - 1);
        } else {
            $article->setFavourites($article->getFavourites() + 1);
        }
        $em->persist($article);
        $em->persist($user);
        $em->flush();

        $test = 'true';

        return new JsonResponse($test);
    }

    /**
     * @Route("/articles/{category}/{id}/likeunlike/{type}", name="likeUnlike")
     */
    public function likeUnlikeAction($category, $id, $type)
    {
        $isLikedUnliked = false;

        $type == 'like' ? $otherType = 'unlike' : $otherType = 'like';

        $em = $this->getDoctrine()->getManager();
        $article = $em->getRepository("AppBundle:Article")->find($id);

        $user = $this->getUser();
        $user = $em->getRepository("AppBundle:User")->find($user->getId());

        $UserLikedArticle = $em->getRepository('AppBundle:UserLikedArticles')
            ->findOneBy(array(
                'userId' => $user,
                'articleId' => $article,
                'appraisal' => $type
            ));

        $userOtherTypeLikedArticle = $em->getRepository('AppBundle:UserLikedArticles')
            ->findOneBy(array(
                'userId' => $user,
                'articleId' => $article,
                'appraisal' => $otherType
            ));

        if ($type == 'like') {
            if ($UserLikedArticle) {
                $em->remove($UserLikedArticle);
                $em->flush();
                $article->setLikes($article->getLikes() - 1);
            } else {
                $userLikedArticles = new UserLikedArticles();
                $userLikedArticles->setUserId($user);
                $userLikedArticles->setArticleId($article);
                $userLikedArticles->setAppraisal($type);
                $article->setLikes($article->getLikes() + 1);

                if ($userOtherTypeLikedArticle) {
                    $em->remove($userOtherTypeLikedArticle);
                    $article->setLikes($article->getLikes() + 1);
                }

                $em->persist($userLikedArticles);
                $em->flush();
                $isLikedUnliked = true;
            }

        } else {
            if ($UserLikedArticle) {
                $em->remove($UserLikedArticle);
                $em->flush();
                $article->setLikes($article->getLikes() + 1);
            } else {
                $userLikedArticles = new UserLikedArticles();
                $userLikedArticles->setUserId($user);
                $userLikedArticles->setArticleId($article);
                $userLikedArticles->setAppraisal($type);
                $article->setLikes($article->getLikes() - 1);

                if ($userOtherTypeLikedArticle) {
                    $em->remove($userOtherTypeLikedArticle);
                    $article->setLikes($article->getLikes() - 1);
                }

                $em->persist($userLikedArticles);
                $em->flush();
                $isLikedUnliked = true;
            }
        }

        $em->persist($article);
        $em->flush();

        $likes = $article->getLikes();

        return new JsonResponse($likes);

    }
}

JS:

$( document ).ready(function() {

    loadComments(window.location.href + '/true', '', '');

    //Add / Remove Favourties
    $(".heart.fa").click(function() {

        var url = $('#add-favourite-button').data('link');

        $.ajax({
            type: "POST",
            url: url,
            success: function(data)
            {
                $('#add-favourite-button').toggleClass("fa-heart fa-heart-o");
            }
        });


    });

    //Like / Unlike
    $(".glyphicon-arrow-up, .glyphicon-arrow-down").click(function () {

        var button = $(this);
        var type = button.attr("data-type");
        var url = window.location.href + '/likeunlike/' + type;

        $.ajax({
            type: "POST",
            url: url,
            success: function(data)
            {
                if (button.attr('id') == 'button-like-article') {
                    $("#button-like-article").toggleClass("orange-arrow");
                    $('#button-unlike-article').removeClass("orange-arrow");
                } else {
                    $("#button-unlike-article").toggleClass("orange-arrow");
                    $("#button-like-article").removeClass("orange-arrow");
                }
                $('#likes-count').text(data);
            }
        });
    });


    // Send comment client logic
    $("#comment_box").submit(function(e) {
        e.preventDefault();
        var form = $(this);
        var url = form.attr('action');

        var category = url.split('/')[2];
        var article = url.split('/')[3];

        $.ajax({
            type: "POST",
            url: url,
            data: form.serialize(),
            success: function(data)
            {
                loadComments('', category, article);
            }
        });
    });

    // Send answer client logic
    $(document).on("click", "#saveButtonAnswer", function (e) {
        $(".answer_box").submit(function(e) {
            e.preventDefault();
            var form = $(this);
            var url = form.attr('action');

            $.ajax({
                type: "POST",
                url: url,
                data: form.serialize(),
                success: function(data)
                {
                    loadComments(window.location.href + '/true', '', '');
                }
            });
            });
    });

    // Show / Hide form for comment
    $(document).on("click", ".reply", function (e) {
        e.preventDefault();
        var commentId = $(this).attr('href');
        $("#post-comment"+commentId).toggle();
    });

    // Show More answers client logic
    $(document).on("click", ".show-more-answers", function (e) {
        e.preventDefault();
        url = $(this).attr('href');
        console.log(url)    ;
        id = $(this).attr('id');
        commentId = $(this).attr('data-comment-id');
        $.ajax({
            type: "GET",
            url: url,
            success: function(data)
            {
                var html = '';

                var answersArray = Object.keys(data.answers).map(function(key) {
                    return data.answers[key];
                });

                console.log(answersArray);

                for (var i = 0; i < answersArray.length; i++) {
                    html += '<div>' +
                        '<div class="media comment-area">' +
                        '<div class="media-left">' +
                        '<a href="#">' +
                        '<img class="media-object" src="../../images/testimonial-1.jpg" alt="">' +
                        '</a>' +
                        '</div>' +
                        '<div class="media-body">' +
                        '<a class="media-heading" href="#">Prodip Ghosh</a>' +
                        '<h5>Oct 18, 2016</h5>' +
                        '<p>' + answersArray[i].content + '</p>' +
                        '</div>';

                            if ((answersArray[answersArray.length - 1] === answersArray[i])) {
                                html += '<a href="/subcomments/' + commentId + '/' + answersArray[i].id + '/' + data.step + '" class="show-more-answers" id="show-more-answers' + answersArray[i].id + '" data-comment-id="' + commentId + '">Show More</a>';
                            }

                    html += '</div>';
                }

                $('#'+id).after(html);
                $('#'+id).remove();
            }
        });
    });

    $(document).on("click", "#pagination-link", function (e) {
        e.preventDefault();
        var url = $(this).attr('href');
        loadComments(url);
    });

    // Send comment client logic
    function loadComments (url = '', category = '', article = '', step = 1) {
        var html = '';
        url = (url != '' ? url : '/articles/' + category + '/' + article + '/true');

        $.ajax({
            type: "GET",
            url: url,
            success: function(data)
            {
                var image = "../../images/testimonial-4.jpg";
                data.comments.forEach(function(comment) {
                    html +=
                    '<div class="comment_area">' +
                        '<div class="media">' +
                        '<div class="media-left">' +
                            '<a href="#">' +
                                '<img class="media-object" src="' + image + '" alt="">' +
                            '</a>' +
                        '</div>' +
                    '<div class="media-body" id="comment-div">' +
                        '<a class="media-heading" href="/profile/' + comment.person.id + '">' + comment.person.firstName + '</a>' +
                        '<h5>Oct 18, 2016</h5>' +
                        '<p>' + comment.content + '</p>' +
                        '<a class="reply" href="' + comment.id + '">Отговори</a>' +
                    '</div>' +
                    '<div class="post_comment" id="post-comment' + comment.id + '" style="display: none;">' +
                        '<h3>Добави отговор</h3>' +
                        '<form method="POST" class="comment_box answer_box" id="answer-form' + comment.id  + '" action="' + data.id + '\\addanswer\\' + comment.id + '") }}">' +
                            '<textarea id="textarea-answer" name="textarea-answer" class="form-control input_box"></textarea>' +
                            '<button type="submit" id="saveButtonAnswer">Изпрати</button>' +
                        '</form>' +
                    '</div>' +
                    '</div>' +
                    '</div>';

                    var subcommentsArray = Object.keys(comment.subComments).map(function(key) {
                        return comment.subComments[key];
                    });
                    var limit = 2;

                    if (subcommentsArray.length > 0) {
                        //var lastSubcomment = subcommentsArray[subcommentsArray.length - 1];
                            for (var i = 0; i < limit; i++) {
                                if (typeof subcommentsArray[i] === 'undefined') {
                                    continue;
                                }
                                html += '<div class="comment_area reply_comment">' +
                                    '<div class="media comment-area">' +
                                        '<div class="media-left">' +
                                            '<a href="#">' +
                                            '<img class="media-object" src="../../images/testimonial-1.jpg" alt="">' +
                                            '</a>' +
                                        '</div>' +
                                        '<div class="media-body">' +
                                            '<a class="media-heading" href="#">' + subcommentsArray[i].person.firstName + '</a>' +
                                            '<h5>Oct 18, 2016</h5>' +
                                            '<p>' + subcommentsArray[i].content + '</p>' +
                                        '</div>' +
                                    '</div>';
                                    if (subcommentsArray.length > limit) {
                                        if (subcommentsArray[limit-1] === subcommentsArray[i]) {
                                            html += '<a href="/subcomments/' + comment.id + '/' + subcommentsArray[i].id + '" class="show-more-answers" id="show-more-answers' + subcommentsArray[i].id + '" data-comment-id="' + comment.id + '">Show More</a>'
                                        }
                                    }
                                html += '</div>';

                            }
                    }
                });

                html += '<ul>';
                for (var i = 1; i <= data.totalPages; i ++) {
                    html += '<li><a href="' + data.id + '/true/' + i + '" id="pagination-link">' + i +'</a></li>';
                }
                html += '</ul>';

                $('.testt').html(html);
            }
        });
    }
});

View:

{% extends 'base.html.twig' %}

{% block body %}
    {% include 'home/header.html.twig' %}

    <!-- Banner area -->
    <section class="banner_area" data-stellar-background-ratio="0.5">
        <h2>Our Blog</h2>
        <ol class="breadcrumb">
            <li><a href="index.html">Home</a></li>
            <li><a href="#" class="active">Blog</a></li>
        </ol>
    </section>
    <!-- End Banner area -->

    <!-- blog area -->
    <section class="blog_all">
        <div class="container">
            <div class="row m0 blog_row">
                <div class="col-sm-8 main_blog">
                    <img src="images/blog/blog_hed-1.jpg" alt="">
                    <div class="col-xs-1 p0">
                        <div>
                            <button id="button-like-article" class="glyphicon glyphicon-arrow-up {{ isLikedArticle ? 'orange-arrow' : '' }}" data-type="like"></button>
                            <p id="likes-count">{{ article.likes }}</p>
                            <button id="button-unlike-article" class="glyphicon glyphicon-arrow-down {{ isUnlikedArticle ? 'orange-arrow' : '' }}" data-type="unlike"></button>
                        </div>
                        <div class="blog_date">
                            <a href="#">{{ article.dateAdded|date("d") }}</a>
                            <a href="#">{{ article.dateAdded|date("M")|cyrillicMonth }}</a>
                        </div>
                        {% if is_granted('ROLE_USER') %}
                            <div>
                                <i class="{{ isFavourite ? 'heart fa fa-heart' : 'heart fa fa-heart-o' }}" id="add-favourite-button" data-link="{{ path('addToFavourites', {'category':article.category.code, 'id':article.id}) }}"></i>
                            </div>
                        {% endif %}
                    </div>
                    <div class="col-xs-11 blog_content">
                        <a class="blog_heading" href="#">{{ article.title }}</a>
                        <a class="blog_admin" href="#"><i class="fa fa-user" aria-hidden="true"></i>{{ article.author }}</a>
                        <ul class="like_share">
                            <li><a href="#"><i class="fa fa-comment" aria-hidden="true"></i>{{ article.comments }}</a></li>
                            <li><a href="#"><i class="fa fa-heart" aria-hidden="true"></i>{{ article.favourites }}</a></li>
                            <li><a href="#"><i class="fa fa-share-alt" aria-hidden="true"></i></a></li>
                        </ul>
                        <p>{{ article.content }}</p>
                        <!--div class="tag">
                            <h4>TAG</h4>
                            <a href="#">PAINTING</a>
                            <a href="#">CONSTRUCTION</a>
                            <a href="#">PAINTING</a>
                        </div-->
                    </div>
                    <div class="client_text" id="client-text">
                        <img class="img-circle" src="images/testimonial-4.jpg" alt="">
                        <a class="client_name" href="#">Emran Khan</a>
                        <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</p>
                        {% if previousArticle is not null and nextArticle is not null %}
                            <a class="control button_all" href="{{ path('article', {'category':previousArticle.category.code, 'id':previousArticle.id}) }}"><i class="fa fa-long-arrow-left" aria-hidden="true"></i> {{ previousArticle.title }}</a>
                            <a class="control button_all" href="{{ path('article', {'category':nextArticle.category.code, 'id':nextArticle.id}) }}">{{ nextArticle.title }} <i class="fa fa-long-arrow-right" aria-hidden="true"></i></a>
                        {% endif %}
                    </div>
                    <div class="testt">

                    </div>
                    <div class="post_comment">
                        <h3>Добави коментар</h3>
                        {{ form_start(commentForm, {'action': path('addcomment', {'category':article.category.code, 'id':article.id})}) }}
                            <div class="col-md-12">
                                <h4>{{ form_label(commentForm.content) }}</h4>
                                {{ form_widget(commentForm.content) }}
                                {{ form_widget(commentForm.submit) }}
                            </div>
                        {{ form_end(commentForm) }}
                    </div>
                </div>
                <div class="col-sm-4 widget_area">
                    <div class="resent">
                        <h3>Последни теми:</h3>
                        {% for article in lastArticles %}
                        <div class="media">
                            <div class="media-left">
                                <a href="{{ path('article', {'category':article.category.code, 'id':article.id}) }}">
                                    <img class="media-object" src="images/blog/rs-1.jpg" alt="">
                                </a>
                            </div>
                            <div class="media-body">
                                <a href="">{{ article.title }}</a>
                                <h6>{{ article.dateAdded|date("M")|cyrillicMonth }} {{ article.dateAdded|date("d") }}, {{ article.dateAdded|date("Y") }}</h6>
                            </div>
                        </div>
                        {% endfor %}
                    </div>
                    <div class="resent">
                        <h3>Категории</h3>
                        <ul class="architecture">
                            {% for category in categories %}
                                <li><a href="{{ path('articles', {'category':category.code}) }}"><i class="fa fa-arrow-right" aria-hidden="true"></i>{{ category.name }}</a></li>
                            {% endfor %}
                        </ul>
                    </div>
                    <!--div class="resent">
                        <h3>ARCHIVES</h3>
                        <ul class="architecture">
                            <li><a href="#"><i class="fa fa-arrow-right" aria-hidden="true"></i>February 2016</a></li>
                            <li><a href="#"><i class="fa fa-arrow-right" aria-hidden="true"></i>April 2016</a></li>
                            <li><a href="#"><i class="fa fa-arrow-right" aria-hidden="true"></i>June 2016</a></li>
                        </ul>
                    </div-->
                    <div class="search">
                        <input type="search" name="search" class="form-control" placeholder="Search">
                    </div>
                    <!--div class="resent">
                        <h3>Tag</h3>
                        <ul class="tag">
                            <li><a href="#">PAINTING</a></li>
                            <li><a href="#">CONSTRUCTION</a></li>
                            <li><a href="#">Architecture</a></li>
                            <li><a href="#">Building</a></li>
                            <li><a href="#">Design</a></li>
                            <li><a href="#">Design</a></li>
                        </ul>
                    </div-->
                </div>
            </div>
        </div>
    </section>
    <!-- End blog area -->

    {% include 'home/footer.html.twig' %}
{% endblock %}

Any advice is welcome!

\$\endgroup\$
2
\$\begingroup\$

PHP

Overall, the methods and functions look a bit long. Look at ArticleController::getArticle() - its more than 50 lines! Pretend you are a teammate who has to modify this code without being very familiar with it.

One way to improve things would be to split out blocks of code into separate methods - especially repeated code like the blocks that instantiate and save Comment objects. This adheres to the Don't Repeat Yourself principle (i.e. D.R.Y). You might also aim to keep the indentation level to one and avoid using the else keyword, as recommended by Rafael Dohms in this presentation about cleaning up code.


As was mentioned above, addAnswer and addComment both manipulate a Comment object in very similar ways - many of the common lines could be abstracted to a separate function. In the image below, blue lines represent identical lines that could be abstracted and the purple line is similar - could be abstracted to use a parameter.

enter image description here

Also note that the return formats are similar so that could also potentially be abstracted to a separate method.


In the method addComment() I see the following:

public function addComment(Request $request, $category, $id, $replyToId)
    {
        $status = 'error';
        $message = '';

        if (!$this->isGranted('ROLE_USER')) {
            echo 'ne e lognat'; exit;
            $message = 'Трябва да се логнете, за да добавите нов коментар!';
        } else {

When the condition in the if block evaluates to true then the string literal will be sent to the echo and the program will exit, thus making the next line (which sets $message) unreachable, and thus superfluous.


I see a couple places like

$status = 'error';

And then later on:

$status = "success";

One could argue that those values should be stored in constants


There are multiple places where a variable is created and assigned immediately before a return statement - e.g. :

addToFavourites():

 $test = 'true';
return new JsonResponse($test);

likeUnlikeAction():

$likes = $article->getLikes();
return new JsonResponse($likes);

There is little point to assigning the value to a variable immediately before it gets used in a return statement. Just use the value in the return statement.


JS

I see a lot of DOM lookups throughout the various javascript event handlers. Bear in mind that those are not cheap1 so it is better to store DOM lookups in a variable (or constant if is used - see last section below for more information).


Is there really only one element with the class testt? Would there ever be a case where multiple elements with that class would be appropriate? If not, perhaps an id attribute should be used instead (including referencing that element in the JavaScript code).


I can't tell which version of jQuery is used but as of version 3.02 the following syntax is deprecated:

$( document ).ready(function() {

and can be shortened to

$(function() {

Some places in the JavaScript could be simplified using partially applied functions- e.g.:

success: function(data)
            {
                loadComments(window.location.href + '/true', '', '');
            }

could be simplified to something like:

success: loadComments.bind(null, window.location.href + '/true', '', '')

It appears that there are default parameters used on one JavaScript function definition:

function loadComments (url = '', category = '', article = '', step = 1) {

This is a feature of , which means that if you are going to use that standard, then you could start using other features like const and let instead of var for scoping variables, arrow functions, etc.

1https://channel9.msdn.com/Events/MIX/MIX09/T53F
2https://api.jquery.com/ready/

\$\endgroup\$
  • \$\begingroup\$ Thanks for your reply! I'd be glad to see more info about Symfony part. \$\endgroup\$ – MorganFreeFarm Feb 18 at 8:04
  • \$\begingroup\$ Okay I added some more aspects about the Symfony part. \$\endgroup\$ – Sᴀᴍ Onᴇᴌᴀ Feb 21 at 20:05
  • \$\begingroup\$ Thank you! Now I can accept your answer :) \$\endgroup\$ – MorganFreeFarm Feb 22 at 7:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.