fosRestBundle : Send Array into Http Request Header - symfony

Aim : Send an Http request as an array (i'm looking to the uri syntax if it's possible to send an array by the header of the Http)
Server Side
ProfilHandler.php My Profil Handler
/**
* Get a list of News.
*
* #param int $limit the limit of the result
* #param int $offset starting from the offset
* #param array $sector get profils by sectors
*
* #return array
*/
public function all($limit = 5, $offset = 0,$sector)
{
return $this->repository->findBy(array(), null, $limit, $offset, $sector);
}
ProfilController.php My Profil Controller
/**
* List all profiles.
*
* #ApiDoc(
* resource = true,
* statusCodes = {
* 200 = "Returned when successful"
* }
* )
*
* #Annotations\QueryParam(name="offset", requirements="\d+", nullable=true, description="Offset from which to start listing profiles.")
* #Annotations\QueryParam(name="limit", requirements="\d+", default="10", description="How many pages to return.")
* #Annotations\QueryParam(name="sector", requirements="\d+", default="IT", description="How many pages to return.")
*
* #Annotations\View(
* templateVar="profiles"
* )
*
* #param Request $request the request object
* #param ParamFetcherInterface $paramFetcher param fetcher service
*
* #return array
*/
// ....
public function getProfilsAction(Request $request, ParamFetcherInterface $paramFetcher)
{
$offset = $paramFetcher->get('offset');
$offset = null == $offset ? 0 : $offset;
$limit = $paramFetcher->get('limit');
$secteur = $paramFetcher->get('sector');
return $this->container->get('genius_profile.profil.handler')->all($limit, $offset,$sector);
}

Yes, it is possible. For example:
Construct url like this:
url -> http://your-app.dev/app_dev.php/some/route/?options[city]=1231&options[county]=3432
then in controller for some/route action you can get
$arr = $request->get('options', array());
And then $arr should conatin:
Array
(
[city] => 1231
[county] => 3432
)
[Edit]:
Maybe try this:
Remove requirements for sector (or set it to match comma separeted list requirements="[\w,]+":
* #Annotations\QueryParam(name="sector", default="IT", description="How many pages to return.")
Then construct url with sector as an comma separated list, for example
?offset=5&limit=10&sector=IT,HEALTH
And inside controller retrive it like this:
$secteur = explode(',', $paramFetcher->get('sector'));
[Edit2]:
public function all($limit = 5, $offset = 0,$secteur) {
if (sizeof($secteur)>=1){
return $this->repository->findBy(array('secteur' => $secteur), array('secteur' => 'ASC'));
}
return $this->repository->findBy(array(), null, $limit);
}

Related

Query Build doctrine Symfony

I have 2 entity (Rule and analysisRule)( association one to many)
I try to make a query that counts the number of idAnalyseRule that have an idAnalyse pass as a parameter in the function
example:
I pass idRule = 15 as a parameter, the query will count all IdAnalysisRules that have an idAnalysis = 15
I do not know how it works but I try it like that
$qb = $this->createQueryBuilder('p');
$expr = $qb->expr();
$qb->andWhere(
$expr->eq('p.analyse', ':analyse')
)
->setParameter('analyse', $analyse);
return $qb->getQuery()->getSingleResult();
this is the manager
/**
* #param $analyse
* #return mixed
*/
public function errorsAnalyseRule(Analyse $analyse){
return $this->repository->totalErrors($analyse);
}
this is controller
/**
*
* Get a totalError by idAnalyse.
* #param Analyse $analyse
* #param AnalyseRuleManager $analyseRuleManager
* #return ApiResponse
*
* #SWG\Parameter(name="id", in="path", type="integer", description="Supplier Id"))
* #SWG\Response(response=200, description="Returns the nbErrors")
*
* #Rest\Get("analyses/{id}", requirements={"id"="\d+"})
*/
public function getTotalErrorsAction(Analyse $analyse, AnalyseRuleManager $analyseRuleManager)
{
return new ApiResponse(['nbErrors' => $analyseRuleManager->errorsAnalyseRule($analyse)]);
}
I am in a state of blockage for 3 days
This works with an inner join. In the repository of analysisRule you have to add the function that makes the query and returns the count:
public function countAnalysisRule(Rule $rule)
{
return $this-createQueryBuilder('a')
->select('count(a)')
->innerJoin('a.Rule', 'rule')
->where('rule.id = :rule')
->setParameter('rule', $rule->getId())
->getQuery()
->getSingleScalarResult();
}
Don't forget ofcourse to add a use of the Rule class.
According to https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/query-builder.html
You should use:
$qb = $entityManager->createQueryBuilder();
$qb->select($qb->expr()->count('p.id'))
->from('App:AnalyseRule','p')
->where('p.analyse', ':analyse')
->setParameter('analyse', $analyse);
$count = $qb->getQuery()->getSingleScalarResult();
where $analyse = 15 in your case !
If you are under 2.6 for doctrine prefer:
$qb = $entityManager->createQueryBuilder();
$qb->select('count(p.id)')
->from('App:AnalyseRule','p')
->where('p.analyse', ':analyse')
->setParameter('analyse', $analyse);
$count = $qb->getQuery()->getSingleScalarResult();

Symfony-Doctrine : join a table with a view after persisting entity

In my database, I have a table T and a view V.
The view has some columns of my table and other data (from other tables).
In Symfony, I declared my view as a read-only Entity.
/**
* #ORM\Table(name="V")
* #ORM\Entity(readOnly=true, repositoryClass="AppBundle\Entity\Repository\VRepository")
*/
class V
{
In my T entity, I did a Join :
/**
* #ORM\OneToOne(targetEntity="V")
* #ORM\JoinColumn(name="T_id", referencedColumnName="V_id")
*/
private $view;
And I added just the getter :
/**
* Get view
*
* #return \AppBundle\Entity\V
*/
public function getView()
{
return $this->view;
}
Everything is working well when I want to read and show data.
But I have a problem after persisting a new T entity.
Symfony seems to lost posted data of my form when I create a new T entity (editAction() works perfectly).
An exception occurred while executing 'INSERT INTO T (T_id, T_name, updated_at) VALUES (?, ?, ?)' with params [null, null, "2017-09-01 15:30:41"]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Field 'T_id' cannot be empty (null)
When I remove ORM annotations of the $view property, it creates correctly my new record T in the database.
I think the problem is due to the fact that the V entity (the record in my SQL view) will exist just after the creation of T. And when I persist/flush data in Symfony, V doesn't exist yet. They are "created" at the same time.
I tried to add Doctrine #HasLifecycleCallbacks on my T entity and the #PostPersist event on the getView() method but it doesn't change anything...
Any idea to differ the Join after the creation of the entity ?
I know it's not conventional to use views as entities with Symfony but I haven't other choice.
I've just checked, it works fine with Bidirectional One-To-One relation
In my case tables are defined like:
create table T (`id` int(11) NOT NULL AUTO_INCREMENT, name varchar(100), primary key (id));
create view V as select id as entity, name, '123' as number from T;
Annotations in T:
/**
* #ORM\Table(name="T")
* #ORM\Entity()
*/
class T
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
private $name;
/**
* #var V
*
* #ORM\OneToOne(targetEntity="V", mappedBy="entity")
*/
private $view;
Annotations in V:
/**
* #ORM\Table(name="V")
* #ORM\Entity(readOnly=true)
*/
class V
{
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="number", type="string", length=255, nullable=true)
*/
private $number;
/**
* #var T
*
* #ORM\Id
* #ORM\OneToOne(targetEntity="T", inversedBy="view")
* #ORM\JoinColumn(name="entity", referencedColumnName="id")
*/
private $entity;
And a test snippet to prove that it saves, updates and reads fine:
public function testCRUD()
{
/** #var EntityManager $manager */
$manager = $this->client->getContainer()->get('doctrine.orm.default_entity_manager');
$t = new T();
$t->setName('Me');
$manager->persist($t);
$manager->flush();
$t->setName('He');
$manager->flush();
$manager->clear();
/** #var T $t */
$t = $manager->find(T::class, $t->getId());
$this->assertEquals('He', $t->getView()->getName());
}
Based on the #Maksym Moskvychev answer : Prefer a bidirectional One-to-One relation.
T Entity :
/**
* #ORM\OneToOne(targetEntity="V", mappedBy="entity")
*/
private $view;
V Entity :
/**
* #ORM\OneToOne(targetEntity="T", inversedBy="view")
* #ORM\JoinColumn(name="V_id", referencedColumnName="T_id")
*/
private $entity;
Fix the loss of data after posting the addAction() form (new T instance).
In the form where I list all T records :
$builder->add('entity', EntityType::class, array(
'class' => 'AppBundle:T',
'choice_label' => 'id',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('t')
->orderBy('t.name', 'ASC')
->setMaxResults(25); // limit the number of results to prevent crash
}
))
Fix the too consuming resources problem (show 25 entities instead of 870+).
Ajax request :
$(".select2").select2({
ajax: {
type : "GET",
url : "{{ path('search_select') }}",
dataType : 'json',
delay : 250,
cache : true,
data : function (params) {
return {
q : params.term, // search term
page : params.page || 1
};
}
}
});
Response for Select2 :
$kwd = $request->query->get('q'); // GET parameters
$page = $request->query->get('page');
$limit = 25;
$offset = ($page - 1) * $limit;
$em = $this->getDoctrine()->getManager();
$repository = $em->getRepository('AppBundle:V');
$qb = $repository->createQueryBuilder('v');
$where = $qb->expr()->orX(
$qb->expr()->like('v.name', ':kwd'),
$qb->expr()->like('v.code', ':kwd')
);
$qb->where($where);
// get the DQL for counting total number of results
$dql = $qb->getDQL();
$results = $qb->orderBy('m.code', 'ASC')
->setFirstResult($offset)
->setMaxResults($limit)
->setParameter('kwd', '%'.$kwd.'%')
->getQuery()->getResult();
// count total number of results
$qc = $em->createQuery($dql)->setParameter('kwd', '%'.$kwd.'%');
$count = count($qc->getResult());
// determine if they are more results or not
$endCount = $offset + $limit;
$morePages = $count > $endCount;
$items = array();
foreach ($results as $r) {
$items[] = array(
'id' => $r->getCode(),
'text' => $r->getName()
);
}
$response = (object) array(
"results" => $items,
"pagination" => array(
"more" => $morePages
)
);
if (!empty($results))
return new Response(json_encode($response));

POST route annotation symfony2

I am trying to develop a rest api, I have a problem with routes annotations, for gets it works well, my code for get is as follows
/**
* #QueryParam(name="offset", requirements="\d+", nullable=true, description="Offset from which to start listing pages.")
* #QueryParam(name="limit", requirements="\d+", nullable=true, default="20", description="How many pages to return.")
*
* #View()
*
* #param Request $request the request object
* #param ParamFetcherInterface $paramFetcher param fetcher service
* GET Route annotation.
* #Get("/users/")
* #return array
*/
public function getUsersAction(Request $request, ParamFetcherInterface $paramFetcher)
{
$offset = $paramFetcher->get('offset');
$offset = null == $offset ? 0 : $offset;
$limit = $paramFetcher->get('limit');
return $this->container->get('user.handler')->all($limit, $offset);
}
for post I do not know how to do it, my code is as follows, i want to add attribues of user in the url, how to do that plz
/**
* #View(template = "UserBundle:User:register.html.twig", statusCode = Codes::HTTP_BAD_REQUEST, templateVar = "form")
*
* #param Request $request the request object
* POST Route annotation.
* #Post("/users/")
* #return FormTypeInterface|View
*/
public function postUserAction(Request $request)
{
try {
$newUser = $this->get('user.handler')->post($request);
$routeOptions = array(
'id' => $newUser->getId(),
'_format' => $request->get('_format')
);
return $this->routeRedirectView('get_user', $routeOptions, Codes::HTTP_CREATED);
} catch (InvalidFormException $exception) {
return $exception->getForm();
}
}
You can get those parameters from the request:
/**
* #View(template = "UserBundle:User:register.html.twig", statusCode = Codes::HTTP_BAD_REQUEST, templateVar = "form")
*
* #param Request $request the request object
* POST Route annotation.
* #Route("/user/{name}/{email}")
* #Method("POST")
* #return FormTypeInterface|View
*/
public function postUserAction(Request $request, $name, $email)
{
try {
$newUser = $this->get('user.handler')->post($request);
$routeOptions = array(
'id' => $newUser->getId(),
'_format' => $request->get('_format')
);
return $this->routeRedirectView('get_user', $routeOptions, Codes::HTTP_CREATED);
} catch (InvalidFormException $exception) {
return $exception->getForm();
}
}

symfony: Error: Call to a member function getDateTime() on a non-object

How can I solve
Error: Call to a member function getDateTime() on a non-object
Here are is my code:
$repository = $this->getDoctrine()
->getRepository('AppBundle\Entity\Menu');
$today = date_create_from_format('Y-m-d H:i', date('Y-m-d H:i'));
$menu = $repository->findAll();
if($menu->getDateTime() == \DateTime('now')){
$primiOne = $menu->getPrimiOne();
$primiTwo = $menu->getPrimiTwo();
$primiThree = $menu->getPrimiThree();
$secondOne = $menu->getSecondOne();
$secondTwo = $menu->getSecondTwo();
$secondThree = $menu->getSecondThree();
$sideOne = $menu->getSideOne();
$sideTwo = $menu->getSideTwo();
$sideThree = $menu->getSideThree();
and the entity is:
/**
* #var \DateTime
*
* #ORM\Column(name="date_time", type="string")
*/
private $dateTime;
/**
* Set dateTime
*
* #param string $dateTime
*
* #return Menu
*/
public function setDateTime($dateTime)
{
$this->dateTime = $dateTime;
return $this;
}
/**
* Get dateTime
*
* #return string
*/
public function getDateTime()
{
return $this->dateTime;
}
You are calling this:
$menu = $repository->findAll();
which will never be instance of your entity because findAll() method returns all objects from given table from db, so this is going to be an array of your entities - this is your mistake - you should query for one object, not all objects.
So, either do:
$menuItems = $repository->findAll();
$menu = $menuItems[0];
if ($menu->getDateTime() (...) )
or
$menu = $repository->findOneBy($criteriaArray);
if ($menu->getDateTime() (...) )

Symfony2 - FindBy To Arrays Parameters

I can't Call findBy with to arrays by the following code :
return $this->repository->findBy(array('secteur'=>$secteur),array('slug'=>$slug));
Exception :
message: "Warning: trim() expects parameter 1 to be string, array given in C:\wamp\www\Symfonyv2\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\BasicEntityPersister.php line 1168",
Following the current Doctrine class, the first array is the list of criteria and the second the order of the request (desc, asc) :
/**
* Finds entities by a set of criteria.
*
* #param array $criteria
* #param array|null $orderBy
* #param int|null $limit
* #param int|null $offset
*
* #return array The objects.
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
{
$persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
return $persister->loadAll($criteria, $orderBy, $limit, $offset);
}
So your method seems to be wrong. And maybe you should do something like this (I don't know what you have in secteur and slug).
return $this->repository->findBy(array('secteur'=>$secteur,'slug'=>$slug));

Resources