I need of you for helping to resolve my problem.
I use Symfony 4 for display some charts with the bundle google charts
Thanks you a lot
This is my function controller
/**
* #Route("/admin/test", name="statsTest")
*/
public function statsTest(){
$results = $this->getDoctrine()->getRepository(IssueNubitalk::class)
->CountIssueByPartenaire('Canal');
dump($results);
// $results = [];
foreach ($results as $key => $val) {
// dump($results);
$results[] = [
'campaign' => $val->getCampaign(),
'total' => $val->getTotal(),
];
}
dump($results);
$data = json_decode(json_encode($results), true);
$pieChart = new PieChart();
$pieChart->getData()->setArrayToDataTable($data);
$pieChart->getOptions()->setHeight(250);
$pieChart->getOptions()->setWidth(400);
$pieChart->getOptions()->getTitleTextStyle()->setBold(true);
$pieChart->getOptions()->getTitleTextStyle()->setColor('#009900');
$pieChart->getOptions()->getTitleTextStyle()->setItalic(true);
$pieChart->getOptions()->getTitleTextStyle()->setFontName('Arial');
$pieChart->getOptions()->getTitleTextStyle()->setFontSize(20);
return $this->render('backend/test.html.twig', [
'piechart' => $pieChart,
]);
}
this is my repository
public function CountIssueByPartenaire($partenaire){
return $this->createQueryBuilder('i')
->select('i.campaign')
->addSelect('COUNT(DISTINCT i.sessionId) as total')
->where('i.campaign LIKE :campaign')
->setParameter('campaign', $partenaire.'_%')
->groupBy('i.campaign')
->getQuery()
->getResult();
}
this is the output
Call to a member function getCampaign() on array
Related
My category url contains both id and slug like https://myapp.com/category/56-category-name (id field = 56 and slug field = category-name in the DB), when updating category name the slug field in DB is updated but the id still the same.
I would like to display my category whatever the slug provided that the id is correct and of course display the correct url. In this case SEO still correct i think.
Here my show method :
/**
* #Route("/category/{id}-{slug}", name="category_show", requirements={"id"="\d+"})
*/
public function show(CategoryRepository $categoryRepository, $slug, $id): Response
{
$category = $categoryRepository->find($id);
if($category->getSlug() !== $slug) {
return $this->redirectToRoute('category_show', [
'id' => $id,
'slug' => $category->getSlug()
]);
}
return $this->render('category/show.html.twig', [
'category' => $category
]);
}
It works if the given id exists in DB, othewise i got an error Call to a member function getSlug() on null. I can throw a NotFoundException, but i think this method use many times queries.
So please help me doing these properly with more flexibility and performance.
In case I would like to display the category in the post url as well like https://myapp.com/56-category-name/23-post-title how to go about it ??
Thanks in advance
Use findOneBy() and check if the result is null
/**
* #Route("/category/{id}-{slug}", name="category_show", requirements={"id"="\d+"})
* #Route("/{id}-{slug}/{idArticle}-{postSlug}", name="article_show", requirements={"idArticle"="\d+"})
*/
public function show(CategoryRepository $categoryRepository, $slug, $id, $idArticle = false, $postSlug = false ): Response
{
$category = $categoryRepository->findOneBy(['id'=>$id]);
if(is_null($category)){
throw new NotFoundHttpException(); //404, nothing found
}else{
//Category found.
if($idArticle){ // https://myapp.com/56-category-name/23-post-title
//Article route, put your logic here
}else{ //https://myapp.com/category/56-category-name
// Category route, logic here
if($category->getSlug() !== $slug) {
return $this->redirectToRoute('category_show', [
'id' => $id,
'slug' => $category->getSlug()
]);
}
return $this->render('category/show.html.twig', [
'category' => $category
]);
}
}
}
here is what i found good for my app :
in my CategoryController.php i create, the show method :
/**
* #Route("/{id}-{slug}", name="category_show", requirements={"id"="\d+"})
*/
public function show(CategoryRepository $categoryRepository, $slug = null, $id): Response
{
$category = $categoryRepository->find($id);
if (!$category) {
throw new NotFoundHttpException();
}
if($category->getSlug() !== $slug) {
return $this->redirectToRoute('category_show', [
'id' => $id,
'slug' => $category->getSlug()
]);
}
return $this->render('category/show.html.twig', [
'category' => $category
]);
}
in my index template to display the category_show link :
show
in my ArticleController.php i create, the show method :
/**
* #Route("/{category}/{id}-{slug}", name="article_show", requirements={"id"="\d+"})
*/
public function show(ArticleRepository $articleRepository, $slug = null, $id, $category = null): Response
{
$article = $articleRepository->find($id);
if (!$article) {
throw new NotFoundHttpException();
}
$cat = $article->getCategory()->getId() . '-' . $article->getCategory()->getSlug();
if($article->getSlug() !== $slug || $cat !== $category) {
return $this->redirectToRoute('article_show', [
'id' => $id,
'slug' => $article->getSlug(),
'category' => $cat
]);
}
return $this->render('article/show.html.twig', [
'article' => $article,
]);
}
in my index template to display the article_show link :
show
For me that solves my problem. But still, if we can improve the process, I'm a buyer.
Thanks
I'm building a simple task planner. This is a fragment from the file TaskController.php. How can I combine these 3 queries (tasks, notcompleted, completed) to make it work? Should I use DQL?
/**
* Lists all task entities.
*
* #Route("/", name="task_index")
* #Method("GET")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$tasks = $em->getRepository('TaskBundle:Task')->findByUser($this->getUser()); // all tasks of a specific user
$notcompleted = $em->getRepository('TaskBundle:Task')->findByCompleted(false); //tasks that are not completed
$completed = $em->getRepository('TaskBundle:Task')->findByCompleted(true); // all completed tasks
return $this->render('task/index.html.twig', array(
'notcompleted' => $notcompleted,
'completed' => $completed,
'tasks' => $tasks,
));
}
You can use Doctrine's \Doctrine\Common\Collections\Collection::partition() to split the tasks:
$em = $this->getDoctrine()->getManager();
$tasks = $em->getRepository('TaskBundle:Task')->findByUser($this->getUser());
$collection = new ArrayCollection($tasks);
list($completed, $notcompleted) = $collection->partition(function ($key, Task $task) {
return $task->isCompleted();
});
return $this->render('task/index.html.twig', array(
'notcompleted' => $notcompleted,
'completed' => $completed,
'tasks' => $tasks,
));
The simplest solution could be to filter tasks in the controller:
$em = $this->getDoctrine()->getManager();
$tasks = $em->getRepository('TaskBundle:Task')->findByUser($this->getUser());
$notcompleted = $completed = [];
foreach ($tasks as $task) {
if ($task->isCompleted()) {
$completed[] = $tasK;
} else {
$notcompleted[] = $task;
}
}
return $this->render('task/index.html.twig', array(
'notcompleted' => $notcompleted,
'completed' => $completed,
'tasks' => $tasks,
));
In this solution you are doing only one DB query, instead of three queries.
Hi all i have problem and don't know what to do.
public function getOrderCityByPrefix($data)
{
$queryBuilder = $this->createQueryBuilder('w')
->where('w.orderCity IN (:data)')
->setParameter('data', $data)
->getQuery();
return $queryBuilder->getResult();
}
Controller:
$cities = json_decode($request->get('cities'), true); // if return i get The controller must return a response (Array(0 => 'VLN', 1 => 'KNS') given)
if i get this responce Array(0 => 'VLN', 1 => 'KNS') and put to function i get well result which i need. But if i put variable $cities to function i have empty result.
$cities = json_decode($request->get('cities'), true);
if(!empty($cities)){
$orders = $this->getDoctrine()->getEntityManager()
->getRepository('AppBundle:OrderWork')
->getOrderCityByPrefix([0 => 'VLN', 1 => 'KNS']); // it's good
$orders = $this->getDoctrine()->getEntityManager()
->getRepository('AppBundle:OrderWork')
->getOrderCityByPrefix($cities); // bad
}
How I can get multiple data from entity data row
public function findByUser1Id($userId)
{
$connections = $this->_em
->getRepository('AppBundle:ConnectionsList')
->findBy(array('user1Id' => $userId));
foreach($connections as $con)
{
$user = $this->_em
->getRepository('AppBundle\Entity\User')
->findOneBy(array('id' => $con->getUser2Id()));
var_dump($user->getFirstname());
var_dump($user->getLastname());
var_dump($user->getEmail());
var_dump($user->getId());
die;
}
}
I need some way to get data in one row in example:
$user->get(array('firstname', 'lastname', 'email' ...))
I found solution, but can't get all data in one row
code is here:
public function findByUser1Id($userId)
{
$connections = $this->_em
->getRepository('AppBundle:ConnectionsList')
->findBy(array('user1Id' => $userId));
foreach($connections as $con)
{
$user = $this->_em
->getRepository('AppBundle\Entity\User')
->findOneBy(array('id' => $con->getUser2Id()));
array_push($user, array(
'id' => $data->getId(),
'email'=>$data->getEmail(),
'firstname'=>$data->getFirstname(),
'lastname'=>$data->getLastname()
));
}
return $data
}
I have three entities: Country, State and City with the following relationships:
When creating a City, I want two selectors, one for the Country and one for the State where the city belongs. These two selectors need to be chained so changing the Country will "filter" the States shown in the other selector.
I found a tutorial showing how to do this using Form Events but their example it's not quite my case. My entity City it's not directly related to the Country entity (they are indirectly related through State) so, when setting the country field in the City form (inside the class CityType), I'm forced to declare that field as 'property_path'=>false as you can see in the code below:
class CityType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('country', 'entity', array(
'class'=>'TestBundle:Country',
'property'=>'name',
'property_path'=>false //Country is not directly related to City
));
$builder->add('name');
$factory = $builder->getFormFactory();
$refreshStates = function ($form, $country) use ($factory)
{
$form->add($factory->createNamed('entity', 'state', null, array(
'class' => 'Test\TestBundle\Entity\State',
'property' => 'name',
'query_builder' => function (EntityRepository $repository) use ($country)
{
$qb = $repository->createQueryBuilder('state')
->innerJoin('state.country', 'country');
if($country instanceof Country) {
$qb->where('state.country = :country')
->setParameter('country', $country);
} elseif(is_numeric($country)) {
$qb->where('country.id = :country')
->setParameter('country', $country);
} else {
$qb->where('country.name = :country')
->setParameter('country', "Venezuela");;
}
return $qb;
}
)));
};
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (DataEvent $event) use ($refreshStates)
{
$form = $event->getForm();
$data = $event->getData();
if($data == null)
return;
if($data instanceof City){
if($data->getId()) { //An existing City
$refreshStates($form, $data->getState()->getCountry());
}else{ //A new City
$refreshStates($form, null);
}
}
});
$builder->addEventListener(FormEvents::PRE_BIND, function (DataEvent $event) use ($refreshStates)
{
$form = $event->getForm();
$data = $event->getData();
if(array_key_exists('country', $data)) {
$refreshStates($form, $data['country']);
}
});
}
public function getName()
{
return 'city';
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Test\TestBundle\Entity\City');
}
}
The problem is that when I try to edit an existing City, the related Country is not selected by default in the form. If I remove the line 'property_path'=>false I get (not surprisingly) the error message:
Neither property "country" nor method "getCountry()" nor method "isCountry()" exists in class "Test\TestBundle\Entity\City"
Any ideas?
OK, I finally figured out how to do it properly:
namespace Test\TestBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Event\DataEvent;
use Test\TestBundle\Entity\Country;
use Test\TestBundle\Entity\State;
use Test\TestBundle\Entity\City;
class CityType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('name');
$factory = $builder->getFormFactory();
$refreshStates = function ($form, $country) use ($factory) {
$form->add($factory->createNamed('entity','state', null, array(
'class' => 'Test\TestBundle\Entity\State',
'property' => 'name',
'empty_value' => '-- Select a state --',
'query_builder' => function (EntityRepository $repository) use ($country) {
$qb = $repository->createQueryBuilder('state')
->innerJoin('state.country', 'country');
if ($country instanceof Country) {
$qb->where('state.country = :country')
->setParameter('country', $country);
} elseif (is_numeric($country)) {
$qb->where('country.id = :country')
->setParameter('country', $country);
} else {
$qb->where('country.name = :country')
->setParameter('country', null);
}
return $qb;
})
));
};
$setCountry = function ($form, $country) use ($factory) {
$form->add($factory->createNamed('entity', 'country', null, array(
'class' => 'TestBundle:Country',
'property' => 'name',
'property_path' => false,
'empty_value' => '-- Select a country --',
'data' => $country,
)));
};
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (DataEvent $event) use ($refreshStates, $setCountry) {
$form = $event->getForm();
$data = $event->getData();
if ($data == null) {
return;
}
if ($data instanceof City) {
$country = ($data->getId()) ? $data->getState()->getCountry() : null ;
$refreshStates($form, $country);
$setCountry($form, $country);
}
});
$builder->addEventListener(FormEvents::PRE_BIND, function (DataEvent $event) use ($refreshStates) {
$form = $event->getForm();
$data = $event->getData();
if(array_key_exists('country', $data)) {
$refreshStates($form, $data['country']);
}
});
}
public function getName()
{
return 'city';
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Test\TestBundle\Entity\City');
}
}
The jQuery AJAX selector
$(document).ready(function () {
$('#city_country').change(function(){
$('#city_state option:gt(0)').remove();
if($(this).val()){
$.ajax({
type: "GET",
data: "country_id=" + $(this).val(),
url: Routing.generate('state_list'),
success: function(data){
$('#city_state').append(data);
}
});
}
});
});
I hope this will be helpful to somebody else facing the same situation.
Since your link to this approach is down i decided to complement your excelent answer so anyone can use it:
In order to execute the following javascript command:
url: Routing.generate('state_list'),
You need to install FOSJsRoutingBundle that can be found in here.
ATENTION: in the read me section of the bundle there are instalation instructions but there is something missing. If you use the deps with this:
[FOSJsRoutingBundle]
git=git://github.com/FriendsOfSymfony/FOSJsRoutingBundle.git
target=/bundles/FOS/JsRoutingBundle
You must run the php bin/vendors update before the next steps.
I'm still trying to find out what route is needed in the routing.yml for this solution to work. As soon as i discover i will edit this answer.
You will need a dedicated FieldType for the chained selectbox. And also an xhr controller that can return child options based on passed parameter. Ofcourse property_path should be set to false.