I wish I could have an isSQLCountLessThan() function or something.
$browser = new sfTestFunctional(new sfBrowser());
$browser
->get('/some/page')
->with('response')->begin()
->isStatusCode(200)
// ...
->isSQLCountLessThan(20) // imagine how cool :)
->end();
Is there a way to have such?
I once created tester for this purpose. It's based on how it's done in web debug toolbar (sfWebDebugPanelDoctrine class).
I extended sfTesterDoctrine so it behaves the same. Only assertion method is added to check query count.
You could also overwrite debug() method to show query statistics.
<?php
/*
* (c) 2010 Jakub Zalas
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* #package zTestPlugin
* #subpackage test
* #author Jakub Zalas <jakub#zalas.pl>
*/
class zTesterDoctrine extends sfTesterDoctrine
{
/**
* #param integer $limit
* #return sfTestFunctionalBase|sfTester
*/
public function assertSqlCountLessThan($limit)
{
$queryCount = $this->countDoctrineEvents();
$this->tester->cmp_ok($queryCount, '<', (int) $limit, sprintf('There are less than "%d" SQL queries performed', $limit));
return $this->getObjectToReturn();
}
/**
* #return integer
*/
protected function countDoctrineEvents()
{
return count($this->getDoctrineEvents());
}
/**
* #return array
*/
protected function getDoctrineEvents()
{
if (!$databaseManager = $this->browser->getContext()->getDatabaseManager())
{
throw new LogicConnection('The current context does not include a database manager.');
}
$events = array();
foreach ($databaseManager->getNames() as $name)
{
$database = $databaseManager->getDatabase($name);
if ($database instanceof sfDoctrineDatabase && $profiler = $database->getProfiler())
{
foreach ($profiler->getQueryExecutionEvents() as $event)
{
$events[$event->getSequence()] = $event;
}
}
}
ksort($events);
return $events;
}
}
Example usage:
$browser = new sfTestFunctional(new sfBrowser());
$browser->setTester('doctrine', 'zTesterDoctrine');
$browser
->get('/some/page')
->with('response')->begin()
->isStatusCode(200)
->end()
->with('doctrine')->begin()
->assertSqlCountLessThan(20) // imagine how cool :)
->end()
->end();
Related
We have a legacy app which is not based on symfony. Doctrine is in use and now we would like to add validation to the models. Seems that the Annotations never get autoloaded, even when "use" statements are in use.
[Semantical Error] The annotation "#Symfony\Component\Validator\Constraints\NotBlank" in property Test\Stackoverflow\User::$Username does not exist, or could not be auto-loaded.
Wrote a small demo application to showcase the problem and how we create the entity manager and validation instance.
composer.json:
{
"require": {
"symfony/validator" : "~3.1"
, "doctrine/orm" : "~2.6.1"
}
}
index.php
require_once ('vendor/autoload.php');
// Load Entities, would normally be done over composer since they reside in a package
require_once('test/User.php');
require_once('MyAnnotationTestApp.php');
// create test app
$app = new MyAnnotationsTestApp();
$app->initEntityManager('localhost', 'annotation_test', 'root', 'mysql', 3306);
if(key_exists('test', $_GET)){
// Create entity and validate it
$entity = new \Test\Stackoverflow\User();
$entity->setUsername('StackoverflowUser');
if($app->testAnnotationWithoutLoading($entity)){
print "Seems the validation was working without preloading the asserts\n<br>";
}
if($app->testAnnotationWithLoading($entity)){
print "Seems the validation was working because we loaded the required class ourself.\n<br>";
}
print "\n<br><br>The question is why the required annotation classes never get autoloaded?";
}else{
// Load the validator class otherwise the annotation throws an exception
$notBlankValidator = new \Symfony\Component\Validator\Constraints\NotBlank();
print "We have cerated the tables but also had to load the validator class ourself.\n<br>\n<br>";
// create tables and
$app->updateDatabaseSchema();
print sprintf('Now lets run the test', $_SERVER['REQUEST_URI']);
}
Doctrine user Entity
<?php
namespace Test\Stackoverflow;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity()
* #ORM\Table(name="users")
*
*/
class User{
/**
* #ORM\Id
* #ORM\Column(name="Id",type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $Id;
public function getId(){
return $this->Id;
}
/**
* #ORM\Column(type="text", length=80, nullable=false)
* #Assert\NotBlank()
*/
protected $Username;
/**
* #return string
*/
public function getUsername()
{
return $this->Username;
}
/**
* #param string $Username
*/
public function setUsername($Username)
{
$this->Username = $Username;
}
}
Demo App with doctrine/validator initialisation:
<?php
final class MyAnnotationsTestApp {
/**
* #var \Doctrine\ORM\EntityManager
*/
private $entityManager;
/**
* #param string $host
* #param string $database
* #param string $username
* #param string $password
* #param integer $port
* #param array $options
* #return \Doctrine\ORM\EntityManager
*/
public function initEntityManager($host, $database, $username, $password, $port, array $options=null){
if($this->entityManager){
return $this->entityManager;
}
$connectionString = sprintf('mysql://%3$s:%4$s#%1$s/%2$s', $host, $database, $username, $password, $port);
$isDevMode = true;
$dbParams = array(
'url' => $connectionString
, 'driver' => 'pdo_mysql'
, 'driverOptions' => array(
1002 => "SET NAMES utf8mb4"
)
);
$cacheDriver = null;
$config = \Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration(array(), $isDevMode, '.cache/', $cacheDriver, false);
if($cacheDriver){
$config->setMetadataCacheImpl($cacheDriver);
$config->setQueryCacheImpl($cacheDriver);
$config->setResultCacheImpl($cacheDriver);
}
$this->entityManager = \Doctrine\ORM\EntityManager::create($dbParams, $config);
return $this->entityManager;
}
/**
* #return \Doctrine\ORM\EntityManager
*/
public function getEntityManager(){
return $this->entityManager;
}
public function updateDatabaseSchema(){
$metaData = array();
$usedEntities = array(
'Test\Stackoverflow\User'
);
foreach($usedEntities as $entity){
$metaData[] = $this->entityManager->getClassMetadata($entity);
}
$tool = new \Doctrine\ORM\Tools\SchemaTool($this->entityManager);
$tool->updateSchema($metaData);
$this->generateProxies($metaData);
}
/**
* Generate all the proxy classes for orm in the correct directory.
* Proxy dir can be configured over application configuration
*
*
* #throws \Exception
*/
final public function generateProxies($metaData)
{
$em = $this->getEntityManager();
$destPath = $em->getConfiguration()->getProxyDir();
if (!is_dir($destPath)) {
mkdir($destPath, 0777, true);
}
$destPath = realpath($destPath);
if (!file_exists($destPath)) {
throw new \Exception("Proxy destination directory could not be created " . $em->getConfiguration()->getProxyDir());
}
if (!is_writable($destPath)) {
throw new \Exception(
sprintf("Proxies destination directory '<info>%s</info>' does not have write permissions.", $destPath)
);
}
if (count($metaData)) {
// Generating Proxies
$em->getProxyFactory()->generateProxyClasses($metaData, $destPath);
}
}
/**
* #var \Symfony\Component\Validator\Validator\ValidatorInterface
*/
protected $validator;
/**
* #return \Symfony\Component\Validator\Validator\ValidatorInterface
*/
final protected function getValidator(){
if($this->validator){
return $this->validator;
}
$this->validator = \Symfony\Component\Validator\Validation::createValidatorBuilder()
->enableAnnotationMapping()
->getValidator();
return $this->validator;
}
/**
* #param \Test\Stackoverflow\User $entity
* #return bool
*/
final public function testAnnotationWithoutLoading(\Test\Stackoverflow\User $entity){
try {
print "test to validate the entity without preloading the Assert classes\n<br>";
$this->getValidator()->validate($entity);
return true;
} catch(\Exception $e){
print "<strong>Does not work since the Asserts classes never get loaded: </strong> Exception-message: ".$e->getMessage()."\n<br>";
return false;
}
}
/**
* #param \Test\Stackoverflow\User $entity
* #return bool
*/
final public function testAnnotationWithLoading(\Test\Stackoverflow\User $entity){
// Here we force the autoloader to require the class
$notBlankValidator = new \Symfony\Component\Validator\Constraints\NotBlank();
try {
print "Loaded the validator manually, will test of it fails now\n<br>";
$this->getValidator()->validate($entity);
return true;
} catch(\Exception $e){
print "<strong>Was not working: </strong> Exception-message: ".$e->getMessage()."\n<br>";
print sprintf("<strong>Even when we autoload the class it is not working. Type of assert: %s</strong>\n<br>", get_class($notBlankValidator));
return false;
}
}
}
If you are using the Symfony Standard Edition, you must update your
autoload.php file by adding the following code [1]
How are these annotations loaded? From looking at the code you could
guess that the ORM Mapping, Assert Validation and the fully qualified
annotation can just be loaded using the defined PHP autoloaders. This
is not the case however: For error handling reasons every check for
class existence inside the AnnotationReader sets the second parameter
$autoload of class_exists($name, $autoload) to false. To work
flawlessly the AnnotationReader requires silent autoloaders which many
autoloaders are not. Silent autoloading is NOT part of the PSR-0
specification for autoloading. [2]
// at the top of the file
use Doctrine\Common\Annotations\AnnotationRegistry;
// at the end of the file
AnnotationRegistry::registerLoader(function($class) use ($loader) {
$loader->loadClass($class);
return class_exists($class, false);
});
[1] https://symfony.com/blog/symfony2-2-0-rc4-released
[2] https://www.doctrine-project.org/projects/doctrine-annotations/en/1.6/annotations.html
I created Block in Drupal 8 with a custom module.
Is it possible to implement this with PHPUnit?
If you can implement it please tell me how.
I want to realize the test with PHPUnit below.
I would be pleased if you could reply just whether it was possible or not.
moduleNameBlock.php
/**
* #file
* create block
*/
namespace Drupal\moduleName\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Url;
/**
*
* Provides a 'testBlock' block.
* #Block(
* id = "test_block",
* admin_label = #Translation("Test"),
* category = #Translation("Menu"),
* )
*/
class moduleNameBlock extends BlockBase {
/**
* {#inheritdoc}
*/
public function build()
{
$build = [];
$url = '';
$nid = '';
$nid = $this->getCurrentUserNode();
if ( !empty($nid) ) {
$url = Url::fromRoute('entity.node.canonical', ['node' => $nid]);
}
$block = [
'#theme' => 'block_theme',
'#url' => $url,
'#nid' => $nid,
'#cache' => [
'max-age' => 0
]
];
$build['test_block'] = $block;
return $build;
}
/**
* The node associated with the user
* #return nid
*/
private function getCurrentUserNode() {
$user_id = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());
$nid = $user_id->get('field_name')->getValue();
return $nid[0]['target_id'];
}
}
Yes this is possible by writing a PHPUnit Functional test.
In your module directory create the following structure /tests/src/Functional then create a file like ModuleNameBlockTest.php then you can place the block in the setUp function and create tests to test the block.
<?php
namespace Drupal\Tests\my_module_name\Functional;
use Drupal\Tests\BrowserTestBase;
/**
* Class ModuleNameBlockTest.
*
* #package Drupal\Tests\my_module_name\Functional
* #group my_group
*/
class ModuleNameBlockTest extends BrowserTestBase {
/**
* Modules to enable.
*
* #var array
*/
public static $modules = ['block', 'my_module_name'];
/**
* {#inheritdoc}
*/
protected function setUp() {
parent::setUp();
$adminUser = $this->drupalCreateUser(['administer blocks']);
$this->drupalLogin($adminUser);
$this->drupalPlaceBlock('my_block_name');
$this->drupalLogout($adminUser);
}
/**
* Test the block.
*/
public function testMyAwesomeBlock() {
// Your test logic here.
}
}
You can always look into the source code of Drupal for some examples. E.g. UserBlocksTest.php of the core user module.
I have 2 entities Submission and Documents. 1 Submission can have Multiple documents.
Submission Entity:
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Document", mappedBy="submission",cascade={"persist", "remove" })
* #ORM\JoinColumn(name="id", referencedColumnName="submission_id")
*/
protected $document;
/**
* #return mixed
*/
public function getDocument()
{
return $this->document->toArray();
}
public function setDocument(Document $document)
{
$this->document[] = $document;
return $this;
}
Document Entity:
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Submission", inversedBy="document")
* #ORM\JoinColumn(name="submission_id", referencedColumnName="id",onDelete="cascade", nullable=true)
*/
protected $submission;
public function getSubmission()
{
return $this->submission;
}
/**
* #param mixed $submission
*/
public function setSubmission($submission)
{
$this->submission = $submission;
}
After receiving files dropzonejs - I'm saving them into Document object, and then, i'm try to save this object into Submission, and persist.
$document = new Document();
$em = $this->getDoctrine()->getManager();
$media = $request->files->get('file');
foreach($media as $req){
$document->setFile($req);
$document->setPath($req->getPathName());
$document->setName($req->getClientOriginalName());
$em->persist($document);
}
$submission->setSubmissionStatus(true);
foreach($document as $item){
$submission->setDocument($item);
}
$submission->setUser($user);
$em = $this->getDoctrine()->getManager();
$em->persist($submission);
$em->flush();
Problem is that all the time, i'm receiving error that submission_title is not set, but that's not true, because i have set this field before. I haven't got idea, what is wrong.
I think you'll get some mileage out of following the tutorial over at http://symfony.com/doc/current/doctrine/associations.html, if you haven't already.
I can see that your getters / setters aren't optimal for associating more than one Document with your Submission.
As they write in the Symfony docs, where they want to associate one category with many products, they have the following code:
// src/AppBundle/Entity/Category.php
// ...
use Doctrine\Common\Collections\ArrayCollection;
class Category
{
// ...
/**
* #ORM\OneToMany(targetEntity="Product", mappedBy="category")
*/
private $products;
public function __construct()
{
$this->products = new ArrayCollection();
}
}
From the docs:
The code in the constructor is important. Rather than being
instantiated as a traditional array, the $products property must be of
a type that implements Doctrine's Collection interface. In this case,
an ArrayCollection object is used. This object looks and acts almost
exactly like an array, but has some added flexibility. If this makes
you uncomfortable, don't worry. Just imagine that it's an array and
you'll be in good shape.
So, you'll want to be sure the constructor for your Document entity has something like $this->submissions = new ArrayCollection();. I've changed the property to a plural name, because I think it's more semantically correct. But you can keep your $submission property name, if you like.
Next is to add a addSubmission, removeSubmission, and a getSubmissions method.
Then, your class might end up looking like this:
<?php
// src/AppBundle/Entity/Submission.php
namespace AppBundle\Entity
use Doctrine\Common\Collections\ArrayCollection;
class Submission
{
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Document", mappedBy="submission",cascade={"persist", "remove" })
* #ORM\JoinColumn(name="id", referencedColumnName="submission_id")
*
* #var ArrayCollection()
*/
protected $documents;
...
/**
* Instantiates the Submission Entity
*
* #return void
*/
public function __construct()
{
$this->documents = new ArrayCollection();
}
/**
* Returns all documents on the Submission
*
* #return mixed
*/
public function getDocuments()
{
return $this->documents;
}
/**
* Add document to this Submission
*
* #param Document $document The object to add to the $documents collection.
*
* #return Submission
*/
public function setDocument(Document $document)
{
$this->documents[] = $document;
return $this;
}
/**
* Remove a document from this Submission
*
* #param Document $document The object to remove from the $documents collection.
*
* #return Submission
*/
public function removeDocument(Document $document)
{
$this->documents->removeElement($document);
return $this;
}
}
I am working with form aimed at uploading the file and updating the database in Symfony2. I want to manually set value of book_id field and not to allow user to change it in the form. Thus in my controller before using doctrine to persist document I am calling:
$documents->setBookId('1');
Unluckilly I get error which indicates that the doctrine does not recognise the above hard coded value input.
An exception occurred while executing 'INSERT INTO Documents (book_id, marker, document_date, link, notes) VALUES (?, ?, ?, ?, ?)' with params [null, "fdd", "2015-04-04", null, "test"]:
To my mind this may be connected with the fact that book_id field is related to Books. Therefore probably I should use setBook function instead. Could you please advice how to do this properly?
My controler file looks like this:
/**
* This code is aimed at checking if the book is chosen and therefore whether any further works may be carried out
*/
$session = new Session();
if(!$session->get("App_Books_Chosen_Lp")) return new RedirectResponse($this->generateUrl('app_listbooks'));
// Authorization goes here
$documents = new Documents();
$form = $this->createForm(new DocumentsType(), $documents);
$form->add('save', 'submit', array('label' => 'Dodaj dokument'));
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$documents->upload();
$documents->setBookId('1');
$em->persist($documents);
$em->flush();
}
return $this->render('AppBundle:Documents:adddocuments.html.twig', array('form' => $form->createView()));
Document class:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* #ORM\Entity
* #ORM\Table(name="Documents")
* #ORM\HasLifecycleCallbacks
*/
class Documents
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Books", inversedBy="documents")
* #ORM\JoinColumn(name="book_id", referencedColumnName="id")
*/
protected $book;
/**
* #ORM\Column(type="integer")
*/
protected $book_id;
/**
* #ORM\Column(type="string", length=220)
*/
protected $marker;
/**
* #ORM\Column(type="date", length=220)
*/
protected $document_date;
/**
* #ORM\Column(type="string", length=220)
* #Assert\File(maxSize="6000000")
*/
protected $link;
/**
* #ORM\Column(type="text")
*/
protected $notes;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set book_id
*
* #param integer $bookId
* #return Documents
*/
public function setBookId($bookId)
{
$this->book_id = $bookId;
return $this;
}
/**
* Get book_id
*
* #return integer
*/
public function getBookId()
{
return $this->book_id;
}
/**
* Set marker
*
* #param string $marker
* #return Documents
*/
public function setMarker($marker)
{
$this->marker = $marker;
return $this;
}
/**
* Get marker
*
* #return string
*/
public function getMarker()
{
return $this->marker;
}
/**
* Set document_date
*
* #param \DateTime $documentDate
* #return Documents
*/
public function setDocumentDate($documentDate)
{
$this->document_date = $documentDate;
return $this;
}
/**
* Get document_date
*
* #return \DateTime
*/
public function getDocumentDate()
{
return $this->document_date;
}
/**
* Set link
*
* #param string $link
* #return Documents
*/
public function setLink($link)
{
$this->link = $link;
return $this;
}
/**
* Get link
*
* #return string
*/
public function getLink()
{
return $this->link;
}
/**
* Set notes
*
* #param string $notes
* #return Documents
*/
public function setNotes($notes)
{
$this->notes = $notes;
return $this;
}
/**
* Get notes
*
* #return string
*/
public function getNotes()
{
return $this->notes;
}
/**
* Set book
*
* #param \AppBundle\Entity\Books $book
* #return Documents
*/
public function setBook(\AppBundle\Entity\Books $book = null)
{
$this->book = $book;
return $this;
}
/**
* Get book
*
* #return \AppBundle\Entity\Books
*/
public function getBook()
{
return $this->book;
}
/*
* ### FILE UPLOAD PROCESS ###
*/
/**
* #Assert\File(maxSize="6000000")
*/
private $file;
/**
* Sets file.
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
}
/**
* Get file.
*
* #return UploadedFile
*/
public function getFile()
{
return $this->file;
}
public function getAbsolutePath()
{
return null === $this->path
? null
: $this->getUploadRootDir().'/'.$this->path;
}
public function getWebPath()
{
return null === $this->path
? null
: $this->getUploadDir().'/'.$this->path;
}
protected function getUploadRootDir()
{
// the absolute directory path where uploaded
// documents should be saved
return __DIR__.'/../../../../web/'.$this->getUploadDir();
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw up
// when displaying uploaded doc/image in the view.
return 'uploads/documents';
}
public function upload()
{
// the file property can be empty if the field is not required
if (null === $this->getFile()) {
return;
}
// use the original file name here but you should
// sanitize it at least to avoid any security issues
// move takes the target directory and then the
// target filename to move to
$this->getFile()->move(
$this->getUploadRootDir(),
$this->getFile()->getClientOriginalName()
);
// set the path property to the filename where you've saved the file
$this->path = $this->getFile()->getClientOriginalName();
// clean up the file property as you won't need it anymore
$this->file = null;
}
}
Okay, first since you're using ManyToOne relation, you don't actually need another property refering to the book - book_id. You can remove that and leave book only.
Then in your controller you have to query the database for that Book and set the that object your Document.
You can do it like this:
$bookId = 1; // Following your example, let's say tou already know the book ID.
$book = $em->getReference('AppBundle:Books', $bookId);
// Check if we actually found a record and then set it to Documents
// Looking at your entity mapping, your reference to Book can not be null,
// but doing an extra check never hurts, since this is just an example.
if( $book ) {
$documents->setBook($book);
}
-Update-
If you want to directly insert the bookID, then what is the purpose of having ManyToOne reference in your entity? Eventually you're going to have to start using doctrine's relations and objects properly. Also, the cool thing about getReference method is that you are getting a reference to an entity, without having to load the entity from the database - you get the so called Proxy objects.
The method EntityManager#getReference($entityName, $identifier) lets you obtain a reference to an entity for which the identifier is known, without loading that entity from the database. This is useful, for example, as a performance enhancement, when you want to establish an association to an entity for which you have the identifier
You can read further about this here.
I've been looking far and wide and still haven't been able to find an example of how to setup a query to look for a specific 'tag' that the user selects from a sidebar which in turn will bring up all posts with that tag.
I understand how to find all tags, but not to find a specific selected by the user.
blogrepository
public function getTags($tags)
{
$qb = $this->createQueryBuilder('b');
$qb->select('b')
->join('b.tags', 'tag')
->where('b.tags LIKE ?', '%'.$tags.'%');
return $qb->getQuery()->getResult();
}
blog entity
/**
* #var string
*
* #ORM\Column(name="tags", type="text")
*/
private $tags;
/**
* Set tags
*
* #param string $tags
* #return Blog
*/
public function setTags($tags)
{
$this->tags = $tags;
return $this;
}
/**
* Get tags
*
* #return string
*/
public function getTags()
{
return $this->tags;
}
1st solution : You should use a doctrine query.
PostRepository.php
public function findByTagName($tagName)
{
$qb = $this->createQueryBuilder('post');
$qb->select('post')
->join('post.tags', 'tag')
->where('tag.name LIKE ?', '%'.$tagName.'%');
return $qb->getQuery()->getResult();
}
2nd solution : Use Many To Many relation and get directly from doctrine
Entity/Tag.php
/**
* #ORM\ManyToMany(targetEntity="YourApp\YourBundle\Entity\Post", inversedBy="tags")
* #ORM\JoinColumn(name="posts_tags")
*/
private $posts;
Entity/Post.php
/**
* #ORM\ManyToMany(targetEntity="YourApp\YourBundle\Entity\Tag", mappedBy="posts")
*/
private $tags;
So you can do $tag->getPosts(); to get all relative posts
3rd solution : Really ugly, but the tutorial is not designed to be improved ...
Get all blog post and parsing each string to find if your tag is in.
public function getBlogWithTag($tagRequested)
{
$blogs = $this->createQueryBuilder('b')
->getQuery()
->getResult();
$blogsWithTag = array();
$tags = array();
foreach ($blogs as $blog)
{
$tags = explode(",", $blog->getTags());
foreach ($tags as &$tag)
{
$tag = trim($tag);
}
if(in_array($tagRequested, $tags)) {
array_push($blogsWithTag, $blog);
}
}
return $blogsWithTag;
}
I believe this will work for you.
public function getPostsByTags($tag)
{
$query = $this->createQueryBuilder('b')
->where('b.tags like :tag')
->setParameter('tag', '%'.$tag.'%');
return $query->getQuery()->getResult();
}