Querying for Data!
Keep on Learning!
If you liked what you've learned so far, dive in!
Subscribe to get
access to this tutorial plus video, code and script downloads.
22 Comments
Hey Richard!
Hmm, that's actually a pretty good question! The simplest answer is this: in an earlier tutorial, we installed this bundle specifically to get markdown functionality including this filter. So if you were actually building this project from the beginning, you would be aware that you installed that bundle. And if you had installed that bundle, its docs would tell you all the features it gives you.
But let me give you one other answer :). At any time, you can see a list of ALL the functions & filters in your application by running:
php bin/console debug:twig
This would tell you that you have a markdown
filter. It wouldn't tell you where it came from, but it is nice to get a list of what's available.
I hope that helps! Cheers!


I have a quick question related to:
$article = $repository->findOneBy(['slug' => $slug]);
'slug', is an hard-coded string now, is there a better way to store such strings?
Should this be a constant stored against repository? Example:
$article = $repository->findOneBy([ArticleRepository::COLUMN_SLUG => $slug]);
or maybe entity?
$article = $repository->findOneBy([Article::FIELD_SLUG => $slug])
Does it make sense? What are the best practise here?
Hey Krzysztof K.!
Hmm. This is an interesting question. First, I'll tell you that the best practice is *not* to set these as constants. And, it's not because it's a bad idea. I think it's more because it's seen as unnecessary. In some ways, the string "slug" *is* already a "constant". Well, it's not a constant - it's a *property* name on your class. So what I mean is, this is already represented in concrete code.
But, the "upside" to using a constant would be that, if you wanted to change the property name, that would be very easy. Without a constant, if you wanted to change the property name, you could use "Refactor" on PhpStorm to change *almost* all of the code... but, you're right, that these "queries" would not change. Even still, I *think* it's overkill.
Here is one tip that I have. In practice, I don't use the findOneBy() functions *too* often. Instead, even for simple queries like this, I tend to always make custom repository methods. For example, in ArticleRepository, I might create a findOneBySlug($slug) that does this query. By doing this, instead of having the string "slug" in many places in my codebase, I will only have it in this one class. *This* is the way that I'd centralize this.
Let me know what you think! Cheers!


Whats the best option for escaping data of a search bar (user input), while querying for data, like in this tutorial?
<b>Situtation:</b>
My Query:
$qb->where('MATCH_AGAINST(a.slug, a.description, a.content) AGAINST (:term boolean)>0')
->setParameter('term', '*'.$searchTerm.'*');
If`
$searchTerm`
is i.ex.`
< test`
I get this error`
SQLSTATE[42000]: Syntax error or access violation: 1064 syntax error, unexpected '<', expecting FTS_TERM or FTS_NUMB or '*'`
<b>Question:</b>
How do I prevent this?
How can I tell doctrine to "escape" the :term properly for match_against?


<b>Solution:</b>
I found out, that doctrine really has nothing to offer for this use case.
I have to filter all "operator" characters on $searchTerm myself.
I do this with:
$searchTerm = '*' . preg_replace('/[+\-><\(\)~*\"@]+/', ' ', $searchTerm) . '*';```
Source:
https://stackoverflow.com/a/26537463/4024751
<b>Question:</b>
Is there a way of implementing this "filter" always to my custom DoctrineExtensions\Query\MySQL class?
Source: https://github.com/beberlei/DoctrineExtensions/blob/master/src/Query/Mysql/MatchAgainst.php
I tried it, but in this class I just get the prepared statement at the end:
This:
public function getSql(\Doctrine\ORM\Query\SqlWalker $walker)
...
return sprintf('MATCH (%s) AGAINST (%s)', implode(', ', $fields), $against);```
Just returns AGAINST (%s) as "AGAINST (?)".
Is there any way to apply the new filter the given parameters (%s // :term) automatically inside the custom class?
Or do I really have to do it manually on every call in my repository when using MATCH_AGAINST, because the class itself doesnt have access to the content of :term from setParameters()?
Hey Mike,
Woh, complex question :) Fairly speaking, I think I've never use that MATCH AGAINST thing before, it's difficult to say if it's possible to do with a custom filter... I'd say it should be possible I think. But Doctrine adds an overhead on plain SQL queries to make it work as DQL, so it might be tricky. But I have a workaround I could suggest you: you can create a new method that will do only those 2 things: escaping and adding MATCH AGAINST to the query builder, something like:
public static function addEscapedMatchAgainst(QueryBuilder $qb, $searchTerm)
{
return $qb->where('MATCH_AGAINST(a.slug, a.description, a.content) AGAINST (:term boolean)>0')
->setParameter('term', '*'.$searchTerm.'*');
}
And you can use it wherever you want in your other methods like this:
public function findAllByTerm($searchTerm)
{
$qb = $this->createQueryBuilder('table');
self::addEscapedMatchAgainst($qb, $searchTerm)
}
And as it's a static method - you can even use it in other entity repositories.
I hope this helps!
Cheers!


Hi!
I get the current user
$user = $this->em->getRepository(User::class)->findOneBy(array('id' => $id));
Next, I add access to it with the function
$this->user_model->addExpire($user);
...
public function addExpire(User $user) {
...
}
but a warning occurs in the PHPStorm for the function addExpire
Expected \App\Entity\User, got Object.
How can I remove this warning?
Hey Dmitriy!
Excellent question! Before I give you a long answer & explanation, let's try something simple first ;). What happens if, instead of injecting the entity manager and saying $this->em->getRepository(User::class)
, you injected the UserRepository
service (I assume you have one?) instead and then said $this->userRepository->findOneBy()
?
The first part of this problem is that PHPStorm doesn't know exactly what object $this->em->getRepository(User::class)
returns. It knows that it returns an "entity repository" - but it's not smart enough to know that it is specifically UserRepository
.
Anyways, let me know if that helps. If it doesn't (and it might not depending on your app), I have more to say ;). Also, as a bonus, if you're ever finding something by id, you can just use ->find($id)
instead of findOneBy()
.
Cheers!


Thank you, Ryan!
Maybe I can tell the PHPStorm that the "entity repository" should return a User object.
Maybe something like this:
/**
* @return User[]
*/
But my UserRepository does not contain functions:
find and findOneBy
Hey Dmitriy,
I suppose you can add @method \App\Entity\User|null findOneBy()" annotation to your UserRepositoy class. This annotation should help PhpStorm to know that findOneBy() returns exactly *User* object. If it does not help, as an alternative option you can override that findOneBy() method in UserRepository, add the proper annotation to it to help PhpStorm. Inside this method you would only need to call the parent method like "return parent::findOneBy()" and pass all the same args to it.
If you need an example - let me know! I just think that it's easy to understand and I hope this is clear for you.
Cheers!


Hi Victor. Thanks a lot.
@method \App\Entity\User|null findOneBy()
This is what I was looking for.


Hello during making project the_spacebar I do havr a error :Impossible to access an attribute ("title") on a null variable. Please help me to solve it{% extends 'base.html.twig' %}{% block title %}Read: {{ article.title }}{% endblock %}{% block body %} <div class="container"> <div class="row"> <div class="col-sm-12"> <div class="show-article-container p-3 mt-4">

Hey Mykyta S.
The error is saying that your "article" variable is null
. So, double check what are you passing to your template by adding a dump($article);
right before rendering such template
Cheers!


Hi! I've been following the course and everything is added correctly but I've this error :
<blockquote>"No article for slug "why-asteroids-taste-like-bacon".</blockquote>
Symfony show me the error is in this line :if (!$article) {<br />throw $this->createNotFoundException(sprintf('No article for slug "%s"', $slug));<br />}
Anyone to help me please ^^ ?
Hey Galnash,
Please, double check that you have an Article in the DB with the slug "why-asteroids-taste-like-bacon". Btw, did you load fixtures? If no, you need to run "bin/console doctrine:fixture:load" command to populate the DB with data.
Cheers!


Awesome! I've check my database and I did not have a simple "why-asteroids-taste-like-bacon", only with a random number like this "why-asteroids-taste-like-bacon896".
Thank you for your answer!


I've been following the course carefully, and making sure everything is added correctly, but during this lesson, when I add the query:
$repository = $em->getRepository(Article::class);
I am receiving an error:
Class 'App\Controller\Article' does not exist
Is there anything that I might have missed? I thought I was careful enough, but sometimes things go sideways.

Hey @RayDube
For some reason the import of your Article entity is pointing to the "controllers" folder (App\ "Controller" \Article)
You have to double check 2 things:
- First: the namespace and location of your Article entity
- Second: The import (use statement at the top of your file) of Article entity in your controller's file
Cheers!


That's it, I hadn't noticed that the use statement didn't populate automatically. Should have seem that, must have been tired.
Thanks a million!
simple q I hope: how did you "know" that the knpmarkdownbundle gave you a twig filter? debug_container doesn't show anything related. I guess I am asking how, when developing, you can find this from the command line (I dont use phpstorm, rather emacs) using console? Or is it a case of googling up the official docs for our markdown and hoping they provide twig facilities?