Reputation: 171
I created a blog and there is a comment system. I have a little problem to post my comments. When comments exist the articles are correctly displayed with their comments, but the problem when an article does not have a comment, it shows me an error like this
Impossible to access an attribute ("nameArticle") on a null variable.
I tried to add a if but it does not work it does not show me the article!
my controller:
/**
* @Route("/{slug}")
* @param string $slug
* @param Request $request
* @return Response
* @throws \Exception
*/
public function detail(Request $request, string $slug): Response {
$article = $this->getDoctrine()
->getRepository(Articles::class)
->findOneWithCategorySlug($slug);
$info = $this->getDoctrine()
->getRepository(InfoMore::class)
->findByInfo(2);
// $comments = $this->getDoctrine()->getRepository(Comments::class)->findAll();
$comment = new Comments();
$form = $this->createForm(CommentsType::class, $comment);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$comments = $form->getData();
$manager = $this->getDoctrine()->getManager();
$user = $this->getUser();
$comments->setUserComments($user);
$comments->setArticleComments($article);
$manager->persist($comments);
$manager->flush();
$this->addFlash('notice', 'Le commentaire a bien été ajouté ');
return $this->redirectToRoute('app_home_detail', [
'slug' => $slug
]);
}
return $this->render('front/detail_article.html.twig', [
'title' => $article,
'article' => $article,
'info' => $info,
'description' => '',
'keywords' => '',
'addComments' => $form->createView()
]);
}
my view:
{% extends 'base.html.twig' %}
{% set active = '' %}
{% set active2 = '' %}
{% set active3 = '' %}
{% set active4 = '' %}
{% set active5 = '' %}
{% set active6 = '' %}
{% if title %}
{% set title = article.nameArticle %}
{% else %}
{% set title = 'Erreur article non trouver !' %}
{% endif %}
{% block body %}
<style>
/* Style the Image Used to Trigger the Modal */
#myImg {
border-radius: 5px;
cursor: pointer;
transition: 0.3s;
}
#myImg:hover {opacity: 0.7;}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.9); /* Black w/ opacity */
}
/* Modal Content (Image) */
.modal-content {
margin: auto;
display: block;
width: 100%;
max-width: 1300px;
}
/* Caption of Modal Image (Image Text) - Same Width as the Image */
#caption {
margin: auto;
display: block;
width: 80%;
max-width: 700px;
text-align: center;
color: #ccc;
padding: 10px 0;
height: 150px;
}
/* Add Animation - Zoom in the Modal */
.modal-content, #caption {
animation-name: zoom;
animation-duration: 0.6s;
}
@keyframes zoom {
from {transform:scale(0)}
to {transform:scale(1)}
}
/* The Close Button */
.close {
position: absolute;
top: 15px;
right: 35px;
color: #f1f1f1;
font-size: 40px;
font-weight: bold;
transition: 0.3s;
}
.close:hover,
.close:focus {
color: #bbb;
text-decoration: none;
cursor: pointer;
}
/* 100% Image Width on Smaller Screens */
@media only screen and (max-width: 700px){
.modal-content {
width: 100%;
}
}
</style>
<div class="container">
<div class="row">
<div class="col-md-12 col-md-offset-2 col-sm-12 col-sm-offset-0 col-xs-12 col-xs-offset-0 text-center fh5co-table">
<div class="fh5co-intro fh5co-table-cell">
<h1 class="text-center title-article h1 animate-box">{{ article.nameArticle }}</h1>
</div>
</div>
</div>
</div>
<main role="main" class="container">
<article>
<div class="heading-section text-center">
<h2>Article publié le : {{ article.createdAt | date('d/m/Y à H:i') }} dans {{ article.category }}</h2>
</div>
{{ article.introduction | raw }}
<div class="col-md-10 col-md-offset-1">
<figure class="text-center" title="Cliquer sur l'images pour la voir en grand">
<img id="myImg" height="500" width="500" src="{{ asset('images/articles/'~article.imageName) }}" class="img-fluid" alt="{{ article.imageName }}">
</figure>
</div>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- The Close Button -->
<span class="close">×</span>
<!-- Modal Content (The Image) -->
<img class="modal-content" id="img01">
<!-- Modal Caption (Image Text) -->
<div id="caption"></div>
</div>
{{ article.articleContent |raw }}
</article>
<div class="espace60"></div>
{% for comment in article.comments %}
<p>{{ comment.commentsContent }} de la part {{ comment.userComments }}</p>
{% endfor %}
<div class="espace60"></div>
<hr>
{% if is_granted("IS_AUTHENTICATED_REMEMBERED") %}
{% for message in app.flashes('notice') %}
<p>
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</p>
{% endfor %}
{{ form_start(addComments) }}
<div class="col-md-12 animate-box">
<div class="form-group">
{{ form_widget(addComments) }}
{{ form_errors(addComments) }}
<input type="submit" class="btn btn-primary" value="Ajouter un commentaire">
</div>
</div>
{{ form_end(addComments) }}
{% endif %}
</main>
<script>
// Get the modal
var modal = document.getElementById('myModal');
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById('myImg');
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");
img.onclick = function(){
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
</script>
{% endblock %}
and my repository:
/**
* @param string $slug
* @return Articles|null
* @throws \Exception
*/
public function findOneWithCategorySlug(string $slug): ?Articles {
$query = $this->createQueryBuilder('a')
->join('a.category', 'c')
->addSelect('c')
->where('a.slug = :slug')
->setParameter(':slug', $slug)
->innerJoin('a.comments', 'com')
->getQuery()
;
try {
return $query->getOneOrNullResult();
} catch (\Exception $e) {
throw new \Exception('Problème dans ArticlesRepository::findOneWithCategory' . $e->getMessage() . var_dump($e));
}
}
Upvotes: 2
Views: 4899
Reputation: 1324
That's normal, in your query you use innerJoin.
The INNER JOIN keyword selects records that have matching values in both tables.
So your query will only select records that have matching values in both Articles and Comments tables. If there are no comments, the record with the Article found won't be selected.
If you want to get rid of
Impossible to access an attribute ("nameArticle") on a null variable.
Just fix your twig by using not null and you can add defined to enforce your verification:
{% if article is defined and article is not null %}
{% set title = article.nameArticle %}
{% else %}
{% set title = 'Erreur article non trouver !' %}
{% endif %}
If you want to display Articles even if they don't have comments use leftJoin instead of innerJoin:
/**
* @param string $slug
* @return Articles|null
* @throws \Exception
*/
public function findOneWithCategorySlug(string $slug): ?Articles {
$query = $this->createQueryBuilder('a')
->join('a.category', 'c')
->addSelect('c')
->where('a.slug = :slug')
->setParameter(':slug', $slug)
->leftJoin('a.comments', 'com')
->getQuery()
;
try {
return $query->getOneOrNullResult();
} catch (\Exception $e) {
throw new \Exception('Problème dans ArticlesRepository::findOneWithCategory' . $e->getMessage() . var_dump($e));
}
}
Upvotes: 2