Symfony2 - How can I simplify this querybuilder? - symfony

I have a working queryBuilder that gets posts by category and excludes the one being shown and sets a max limit.
Question: How can I simplify this queryBuilder?
In the query, I am pretty sure I don't need to join the 2 tables (category/post connected with a OneToMany/ManyToOne relationship) and am setting $category in the controller, is there a better way of refactoring this?
queryBuilder
public function getRelatedPosts($exceptPost, $limit, $category)
{
return $this
->createQueryBuilder('post')
->leftJoin('post.category','category')
->where('post != :exceptPost')
->setParameter('exceptPost', $exceptPost)
->andWhere('category = :category')
->setParameter('category', $category)
->orderBy('post.createdAt', 'DESC')
->setMaxResults($limit)
->getQuery()
->execute();
}
controller
public function showAction($slug)
{
$post = $this->getDoctrine()->getRepository('AcmeDemoBundle:Post')
->findOneBy(array(
'slug' => $slug
));
if (null === $post) {
throw $this->createNotFoundException('Post was not found');
}
$category = $post->getCategory();
$posts = $this->getDoctrine()->getRepository('AcmeDemoBundle:Post')
->getRelatedPosts($post, 4, $category);
return array(
'post' => $post,
'posts' => $posts
);
}
updated queryBuilder
public function getRelatedPosts($exceptPost, $limit, $category)
{
return $this
->createQueryBuilder('post')
->where('post != :exceptPost')
->andWhere('post.category = :category')
->setParameter('exceptPost', $exceptPost)
->setParameter('category', $category)
->orderBy('post.createdAt', 'DESC')
->setMaxResults($limit)
->getQuery()
->execute();
}

I am not sure if this is what you are looking for but you may want something like this:
Controller
public function showAction($slug)
{
$post = $this->getDoctrine()->getRepository('AcmeDemoBundle:Post')
->findOneBy(array(
'slug' => $slug
));
if (null === $post) {
throw $this->createNotFoundException('Post was not found');
}
$posts = $this->getDoctrine()->getRepository('AcmeDemoBundle:Post')
->getRelatedPosts($post, 4);
return array(
'post' => $post,
'posts' => $posts
);
}
Repository
public function getRelatedPosts($exceptPost, $limit)
{
return $this
->createQueryBuilder('post')
->where('post.id != :exceptPost')
->andWhere('post.category = :category')
->setParameter('exceptPost', $exceptPost->getId())
->setParameter('category', $exceptPost->getCategory()->getId())
->orderBy('post.createdAt', 'DESC')
->setMaxResults($limit)
->getQuery()
->getResult();
}
You can also build this in a join query of post table with itself or SELECT ... IN (...); if you are interested

Related

How can I filter posts when the meta_value is a serialize object?

I'm doing a dropdown in my post custom type just to filter the content when is completed or not.
my meta_value is a serialize object like "a:3:{s:5:"email";s:21:"mrsxcvsfesr#gmail.com";s:9:"store";s:6:"testes";s:5:"token";s:34:"$P$B7efpLZUWWyB4QkhG0YaYyIwXRAj.3.";}"
and my job is to check if the token is null or not
CustomPostTypeController.php
add_action('restrict_manage_posts',[ $this, 'dropdown_status_filter']);
add_filter( 'parse_query', [ $this, 'filter_request_query'])
public function dropdown_status_filter($post_type){
if('ctp_dasboard' !== $post_type) {
return; //filter your post
}
$selected = '';
$request_attr = 'status_filter';
if ( isset($_REQUEST[$request_attr]) ) {
$selected = $_REQUEST[$request_attr];
}
echo '<select id="status_filter-loc" name="status_filter">';
echo ($selected === '1') ? "'<option value='1' selected>Done</option>'" : "'<option value='1'>Done</option>'";
echo ($selected === '2') ? "'<option value='2' selected>Pending</option>'" : "'<option value='2'>Pending</option>'";
echo '</select>';
}
public function filter_request_query($query){
//modify the query only if it admin and main query.
if( !(is_admin() AND $query->is_main_query()) ){
return $query;
}
//we want to modify the query for the targeted custom post and filter option
if( !('ctp_dasboard' === $query->query['post_type'] AND isset($_REQUEST['status_filter']) ) ){
return $query;
}
//for the default value of our filter no modification is required
if(0 == $_REQUEST['status_filter']){
return $query;
}
//modify the query_vars.
// $value = "";
// var_dump($_REQUEST['status_filter'] === '1');
if ( $_REQUEST['status_filter'] === '1'){
// global $wpdb;
// $meta_key = 'form_ctp';
// $meta_value = '"token";N;';
// $mid = $wpdb->get_results( $wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value LIKE %s ", $meta_key, $meta_value) );
// dd($mid);
// // The Query
$args = [
'post_type' => 'ctp_dasboard',
['meta_query' => [
'key' => 'form_ctp',
'value' => 'token";N;', // this is when token is null
'compare' => 'IN'
]]
];
// dd($args);
$query = new \WP_Query( $args );
// dd($the_query);
}
if ( $_REQUEST['status_filter'] === '2'){
}
return $query;
}
There is a special function maybe_unserialize which can return you unserialized data array/ string and etc. Check documentation. Your variable should look like this:
$str = "a:3{s:5:"email";s:21:"mrsxcvsfesr#gmail.com";s:9:"store";s:6:"testes";s:5:"token";s:34:"$P$B7efpLZUWWyB4QkhG0YaYyIwXRAj.3.";}";
$data = maybe_unserialize($str); // will return an array

How to fix the output?

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

Prevent EntityManager for one entity but not the other

so I have a controller that essentially submits an edit of a category for approval by sending an email to the admin. This was fine before I decided to add in an actions table to store action history (e.g. category: edit).
The problem that's arose is that, by using entityManager to add data to the actions table, it's automatically updating the category entity due to the Event Watcher.
I tried a google and couldn't find anything on setting entityManager to one entity only.
This is my current controller:
<?php
namespace App\Controller\Category\Edit;
use App\Entity\Action;
use App\Entity\Category;
use App\Entity\User;
use App\Form\Category\EditCategoryType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class EditController extends Controller
{
public function edit($id, Request $request, \Swift_Mailer $mailer)
{
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
$category = $this->getDoctrine()->getRepository(Category::class)->find($id);
$categoryGuru = $category->getGuru();
$guruName = $categoryGuru->getUsername();
$category->setGuru($categoryGuru);
$form = $this->createForm(EditCategoryType::class, $category);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$formData = $form->getData();
$name = $formData->getName();
$description = $formData->getDescription();
$newGuruId = $form['guru']->getData();
$newGuru = $this->getDoctrine()->getRepository(User::class)->find($newGuruId);
$actionId = $this->setAction();
$approveUrl = $category->getId();
$approveUrl .= '/'. $actionId;
$approveUrl .= '/'. $name;
$approveUrl .= '/'. $description;
$approveUrl .= '/'. $newGuru->getId();
$message = (new \Swift_Message('Category Edit Request - '. $category->getName()))
->setFrom('some#email.com')
->setTo('another#email.co.uk')
->setBody(
$this->renderView(
'emails/category/edit-request.html.twig',
array(
'category' => $category->getName(),
'category_new_name' => $name,
'description' => $category->getDescription(),
'category_new_description' => $description,
'guru' => $guruName,
'category_new_guru' => $newGuru->getUsername(),
'category_new_guru_id' => $newGuru->getId(),
'category_id' => $category->getId(),
'category_author' => $this->getUser()->getUsername(),
'approve_url' => $approveUrl,
'action_id' => $actionId
)
),
'text/html'
);
$mailer->send($message);
$this->addFlash('success', 'Category Edit Submitted for Review.');
return $this->redirectToRoute('category_list');
}
return $this->render(
'category/edit.html.twig',
array('form' => $form->createView(), 'category' => $category, 'guru' => $categoryGuru)
);
}
# this was originally a part of the above controller
# tried separating to see if it would work - didn't
public function setAction()
{
$action = new Action();
$entityManager = $this->getDoctrine()->getManager();
# set action data
$action->setDate(new \DateTime());
$action->setUserId($this->getUser()->getId());
$action->setDescription($this->getUser()->getUsername(). ' has edited a category');
$action->setStatus('pending');
$action->setType('Category: edit');
$entityManager->persist($action);
$entityManager->flush();
return $action->getId();
}
}
The answer I came to was, don't. Use the Repository class:
CategoryRepository.php
public function addAction($userId, $description, $status, $type)
{
$entityManager = $this->getEntityManager();
$connection = $entityManager->getConnection();
$date = date('Y-m-d H:i:s', strtotime('now'));
$connection->insert(
'action',
array(
'type' => $type,
'user_id' => $userId,
'date' => $date,
'description' => $description,
'status' => $status
)
);
return $entityManager->getConnection()->lastInsertId();
}
then call it in the controller - no longer classing entityManager issues.

Use delete_user_meta

I want to delete my usermeta in table database but give nothing. it give me an error because its not array expected string parameter
function remove_meta(){
$role = 'client'; //Select user role
$users = get_users('role='.$role);
global $wpdb;
$stats = $wpdb->get_results("
SELECT ".$wpdb->prefix." group_clients.client_id
FROM ".$wpdb->prefix." group_clients
WHERE ".$wpdb->prefix." group_clients.group_id IN (1, 2, 5, 6)
", $users); // Fetch data by selective group ID
$stats = array();
if (is_array($stats) || is_object($stats)){
//foreach ((array) $stats as $stat){
foreach ($stats as $stat) {
delete_user_meta($stat->ID, 'terms_and_conditions');
}
echo 'Fini!';
}
}
Try below code you are doing confusing code. Do not do sql query unless it is really required.
$args = array(
'role' => 'customer', //client or whatever you required
);
//geting all user
$users = get_users( $args );
foreach ($users as $result)
{
//each user id
$userId = $result->ID;
if($userId != '')
{
//getting all user meta of particular user
$all_meta_for_user = get_user_meta( $userId );
if(is_array($all_meta_for_user))
{
foreach ($all_meta_for_user as $key => $value) {
$terms =get_user_meta($userid,'terms_and_conditions',true);
if($terms !=''){
delete_user_meta($userId, 'terms_and_conditions');
}
}
}
}
}
with hook
add_action('init','deletedata');
function deletedata()
{
if(!is_admin())
return;
if(!current_user_can('manage_options'))
return false;
$args = array(
'role' => 'customer', //client or whatever you required
);
//geting all user
$users = get_users( $args );
foreach ($users as $result)
{
//each user id
$userId = $result->ID;
if($userId != '')
{
//getting all user meta of particular user
$all_meta_for_user = get_user_meta( $userId );
if(is_array($all_meta_for_user))
{
foreach ($all_meta_for_user as $key => $value) {
# code...
$terms =get_user_meta($userid,'terms_and_conditions',true);
if($terms !=''){
delete_user_meta($userId, 'terms_and_conditions');
}
}
}
}
}
}

How can I rerender a template with an array after search?

I've made search functionality in symfony, which works.
public function forSaleAction(Request $request)
{
$data = array();
$form = $this->createFormBuilder($data)
->add('searchText')
->getForm();
$form->handleRequest($request);
$ads = $this->getDoctrine()
->getRepository('ParkResortBundle:Ad')
->findAll();
if ($form->isSubmitted()) {
$data = $form->getData();
$SearchKeyword = $data['searchText'];
$qb = $this->getDoctrine()->getEntityManager()->getRepository('ParkResortBundle:Ad')->createQueryBuilder( 'p' );
$qb->add( 'where',
$qb->expr()->orX(
$qb->expr()->like( 'p.adTitle', "'%{$SearchKeyword}%'" ),
$qb->expr()->like( 'p.address', "'%{$SearchKeyword}%'" )
)
)
->addOrderBy('p.price', 'ASC');
$ads = $qb->getQuery()->getResult();
}
if ($request->isXmlHttpRequest()) {
return $this->render('ParkResortBundle:Pages:_ad.html.twig',
array('ads' => $ads));
}
$paginator = $this->get('knp_paginator');
$paginated = $paginator->paginate(
$ads, /* query NOT result */
$request->query->getInt('page', 1)/*page number*/,
2/*limit per page*/
);
return $this->render('ParkResortBundle:Pages:forSale.html.twig',
array('ads' => $paginated,
'form'=>$form->createView()));
}
I want when the search area is empty(after user presses backspace or delete all) the list should appear all in for_sale twig template.
How can I do that?
You need to use entity manager with findAll()
$ads = $this->getDoctrine()->getEntityManager()
->getRepository('ParkResortBundle:Ad')
->findAll();

Resources