Symfony2 (doctrine2) native sql insert - symfony

How to insert data in symfony2 doctrine2 on native sql?
My query
insert into propriedades (id,name,descripcion,num_lote,cod_imovel,imovel,convenio,proprietar,cpf,area_ha,perimetro,location,centro) VALUES (nextval('propriedades_id_seq'),'?','?','?','?','?','?','?','?','?','?',ST_GeomFromKML('<Polygon><outerBoundaryIs><LinearRing><coordinates>".$terra['coordinates']."</coordinates></LinearRing></outerBoundaryIs></Polygon>'),ST_Centroid(ST_GeomFromKML('<Polygon><outerBoundaryIs><LinearRing><coordinates>".$terra['coordinates']."</coordinates></LinearRing></outerBoundaryIs></Polygon>')))

You have to use $conn->insert('table', $dataArray);. See documentation

In 2020 you can do something like (example query, adapt it to your params):
$query = "
INSERT INTO `user_challenges_claimed`
SET
`season_id` = :seasonId,
`user_id` = :userId,
`interval_type` = :intervalType,
`is_claimed` = true
ON DUPLICATE KEY UPDATE
`is_claimed` = true
;
";
// set query params
$queryParams = [
'seasonId' => $seasonId,
'userId' => $userId,
'intervalType' => $intervalType,
];
// execure query and get result
$result = $this->manager->getConnection()
->executeQuery(
$query,
$queryParams
);
// clear manager entities
$this->manager->clear();
// optional - assert row has been inserted/modified
if ($result->rowCount() < 1) {
throw new ChallengeAlreadyClaimedException(
"[{$seasonId}:{$userId} - {$intervalType}]"
);
}
$this->manager is an object implementing EntityManagerInterface (ie EntityManager).

Usually you do not use what you call native sql in a symfony 2 project but the high level Doctrine ORM layer.
However there is a doctrine dbal layer which enables e.g. mysql queries instead of DQL. Here is the reference
http://symfony.com/doc/2.0/cookbook/doctrine/dbal.html

Related

Symfony / Doctrine findBy

Hove to create custom Repository function who query by json field. I have params column in my database who look like this:
"params": {
"product": "stopper",
"itemIdentifier": ""
}
I want to query record by product value. In this case stopper term.
You can achieve this with a classic example :
In your repository :
For one result
public function findOneProduct($value): ?Params
{
return $this->createQueryBuilder('p')
->andWhere('p.product = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
For multiple result
public function findParamsByProduct($value): ?Params
{
return $this->createQueryBuilder('p')
->andWhere('p.product = :val')
->setParameter('val', $value)
->orderBy(/*some field */)
->setMaxResults(/*if needed*/)
->getQuery()
->getResults()
;
}
In your controller:
$stoppers = $entityManager->getRepository(Params::class)->findParamsByProduct('stopper');
If I understood your question correctly, you have a table with a column named params. And inside this mysql column, you store JSON text.
And then you want to query that table and filter by looking into the JSON in your column.
This can be a bit tedious and was also highly discouraged in the past (prior to the JSON Type in Mysql 5.7.8).
Best practices would be to have a NoSQL DB such as MongoDB which is actual JSON stored in a collection(table).
Anyways, there is a solution for you.
Taking into account #AppyGG explained how to make a custom repository function.
First of all, we have to make a query using pure SQL.
It can be done two ways:
1.Return arrays containing your data.
$conn = $this->getEntityManager()->getConnection();
$sql = '
SELECT * FROM product p
WHERE p.price > :price
ORDER BY p.price ASC
';
$stmt = $conn->prepare($sql);
$stmt->execute(['price' => $price]);
// returns an array of arrays (i.e. a raw data set)
return $stmt->fetchAll();
2.Return hydrated Entities
use Doctrine\ORM\Query\ResultSetMappingBuilder;
$rsm = new ResultSetMappingBuilder($entityManager);
$rsm->addRootEntityFromClassMetadata('MyProject\Product', 'p');
$sql = '
SELECT * FROM product p
WHERE p.price > :price
ORDER BY p.price ASC
';
$nql = $this->_em->createNativeQuery( $sql, $rsm );
$nql->setParameter('price', $price);
//Return loaded entities
return $nql->getResult();
Now, knowing how to make make a MySQL query with doctrine, we want to select results filtered in JSON data.
I'm am referencing this beautiful stackoverflow which explains it all:
How to search JSON data in MySQL?
The easiest solution proposed in there requires at least MySQL 5.7.8
Your MySQL query would be as follow:
//With $entity->getParams() == '{"params": {"product":"stopper", "itemIdentifier":""}}'
$conn = $this->getEntityManager()->getConnection();
$sql = '
SELECT * FROM Entity e
WHERE JSON_EXTRACT(e.params, "$.params.product") = :product
';
//Or Like this if the column is of Type JSON in MySQL(Not doctrine, yes check MySQL).
$sql = '
SELECT * FROM Entity e
WHERE e.params->"$.params.product" = :product
';
$stmt = $conn->prepare($sql);
$statement->bindValue("product","stopper");
$stmt->execute();
return $statement->fetchAll();
Hope this helps!
P.S: Note that my example uses a column named 'params' with a Json containing also a named attribute 'params', this can be confusing. The intended purpose is to show how to do multiple level filtering.

Symfony2 Doctrine2 native queries basics

I am developing a basic web-app in my job. I have to work with some sql server views. I made the decision of trying native queries, and once tested it's functionality, try to write some classes to code all the queries and kinda forget their implementation.
So my issue is, I've got an Entity in Acme/MyBundle/Entity/View1.php.
This entity has got all the attributes matching the table and also it's getters and setters.
I guess this entity is well mapped to the DB (Doctrine cant work with views easily).
My aim is to let a Controller be able to fetch some data from those views(SQL SERVER) and return it to the view (twig) so it can display the info.
$returned_atts = array(
"att1" => $result[0]->getAttribute1(), //getter from the entity
"att2" => $result[1]->getAttribute2(), //getter from the entity
);
return $returned_atts;`$sql = "SELECT [Attribute1],[Attribute2],[Attribute3] FROM [TEST].[dbo].[TEST_VIEW1]"; //THIS IS THE SQL SERVER QUERY
$rsm = new ResultSetMapping($em); //result set mappin object
$rsm->addEntityResult('Acme\MyBundle\Entity\View1', 'view1'); //entity which is based on
$rsm->addFieldResult('view1', 'Attribute1', 'attribute1'); //only choose these 3 attributes among the whole available
$rsm->addFieldResult('view1', 'Attribute2', 'attribute2');
$rsm->addFieldResult('view1', 'Attribute3', 'attribute3');
//rsm built
$query = $em->createNativeQuery($sql, $rsm); //execute the query
$result = $query->getResult(); //get the array
It should be possible to return the array straight from the getResult() method isn't it?
And what's killing me, how can I access the attribute1, attriute2 and attriute2?
$returned_atts = array(
"att1" => $result[0]->getAttribute1(), //getter from the entity
"att2" => $result[1]->getAttribute2(), //getter from the entity
);
return $returned_atts;`
If you want result as array, you don't need to use ResultSetMapping.
$sql = " SELECT * FROM some_table";
$stmt = $this->getDoctrine()->getEntityManager()->getConnection()->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll();
That is a basic example for controller action. You can dump the result, use var_dump(), to see how to access your particular field values.
More examples here Doctrine raw sql

Doctrine query: delete with limit

I am trying to delete only x objects with a delete query from Doctrine. And since there is no LIMIT in doctrine, we should use $query->setMaxResults($limit) instead. I am using Symfony2.
However it does not work with the following query (with or without $query->setMaxResults($limit), it delete everything instead of deleting the $limit first entities).
$limit = 10;
$query = $entityManager->createQuery(
'DELETE FROM MyProject\Bundle\MyBundle\Entity\MyEntity myEntity
WHERE myEntity.cost = 50'
)
$query->setMaxResults($limit);
$query->execute();
One solution that works is to use native SQL with Doctrine like this (instead of DQL).
$limit = 10;
$sql = 'DELETE FROM my_entity
WHERE cost = 50
LIMIT ' . $limit;
$stmt = $entityManager->getConnection()->prepare($sql);
$stmt->execute();
setMaxResults works only in some cases. Doctrine seems to ignore it if it's not managed.
check the Doctrine doc : https://www.doctrine-project.org/projects/doctrine1/en/latest/manual/dql-doctrine-query-language.html#driver-portability
If it does not work, try in native SQL, like the other solution posted.
Use a sub query so you can use setMaxResults
$qb = $this->em->getRepository(MyClass::class)->createQueryBuilder('x');
$subQb = $this->em->getRepository(MyClass::class)->createQueryBuilder('x_sub');
// We can not use "setMaxResults" on delete query so we need a sub query
$subQb
->select('x_sub.id')
// ... your where clauses
->setMaxResults(500)
;
$qb
->delete()
->andWhere($qb->expr()->in('x.id', ':ids'))
->setParameter('ids', $subQb->getQuery()->getResult())
;

Symfony2 Doctrine Join Entity

I have a entity with the next join:
class blogComment
{
....
/**
* #ORM\OneToMany(targetEntity="BlogComment", mappedBy="replyTo")
*/
protected $replies;
....
}
Now I get successfully all the replies. But I only want to get: where active = true
How to do that?
Oke if you guys recommend to get the comments by query in the controller how to build a nested array to get result like this:
For solving the part where you only want active replies there are a couple of options:
1) Use some custom DQL in a repository:
$dql = 'SELECT bc FROM BlogComment bc WHERE bc.replyTo = :id AND bc.active = :active';
$q = $em->createQuery($dql)
->setParameters(array('id' => $id, 'active' => true));
2) Using ArrayCollection::filter() in the getter:
public function getReplies()
{
return $this->replies
->filter(function ($reply) {
return $reply->isActive();
})
->toArray();
}
3) Using ArrayCollection::matching() (Collection Criteria API) in the getter:
use Doctrine\Common\Collections\Criteria;
// ...
public function getReplies()
{
$criteria = new Criteria::create()
->where(Criteria::expr()->eq('active', true));
return $this->replies
->matching($criteria)
->toArray();
}
4) Use Filters. These can add where clauses to queries regardless of where that query is generated. Please see the docs.
If you want to be able to fetch an entire set of replies, nested and all, in a single query, you need to implement some kind of "tree" of "nested set" functionality. I'd advise you to look at the Tree behavior of l3pp4rd/DoctrineExtensions.
http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html
Wherever you are obtaining your blog comments to display them (probably on a controller), you need to customise your query so that only the active replies are extracted. Something like:
$query = $em->createQuery('SELECT b FROM blogComment b JOIN b.replies r WHERE r.active = :active');
$query->setParameter('active', true);
$blogComments = $query->getResult();
EDIT:
For your new requirement of nested replies, you would need to specify a relationship between a comment entity and its parent comment.

Database Searching Using Doctrine and Symfony2

So I'm currently trying to perform a simple search using Symfony2 and Doctrine. Something similar to this: http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/searching.html
I've currently got the following YAML file setup to generate my entities. It generates my class Style entity correctly as a class.
...\Style:
type: entity
table: styles
id:
id:
type: integer
generator:
strategy: IDENTITY
actAs:
Searchable:
fields: [title]
batchUpdates: true
fields:
title:
type: string
length: 150
unique: true
In my controller, I'm trying to run a search on that table based on a string.
public function searchAction($pattern)
{
$repository = $this->getDoctrine()->getRepository('..:Style');
$search = $repository->search($pattern);
return $this->outputize($search);
}
However, when I try executing the code, I get the following exception.
Undefined method 'search'. The method name must start with either findBy or findOneBy!
Am I generating my entities correctly or is there something I'm clearly missing?
On a side note, when I look at my Entity/Style.php after generating, there is no clear method ->search(), is the function supposed to be generated by Symfony here?
search() is not a function supported in Symfony2. You're looking at the Symfony 1.x documentation, and Symfony2 is really different from Symfony 1.x so for reference, you should always use the doc.
There are several ways to fetch entities in Symfony2. Here are a few examples:
Find
$user = $this->getDoctrine()
->getRepository('UserBundle:User')
->find($user_id)
;
DQL:
$query = $em->createQuery(
'SELECT b FROM YourBundle:Bid b WHERE b.property_id = :property_id ORDER BY b.amount DESC'
)->setParameter('property_id', $property_id);
try {
$bids = $query->getResult();
} catch (\Doctrine\Orm\NoResultException $e) {
//Handle No Result Exception here
}
Refer to the Doctrine guide for Symfony2 here: http://symfony.com/doc/current/book/doctrine.html
Hello you can do it in symfony 3
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'SELECT p
FROM AppBundle:Hotel p
WHERE p.address like :location
ORDER BY p.address ASC'
)->setParameter('location','%'.$request->get('location').'%' );
$hotel = $query->getResult();

Resources