Customize database result [Symfony 4] - mysql

I have like a search Form
I want for example search by Categorie, diplome, salaire,
Categorie, diplome works good
but my probleme is in salaire ( type float), when the form salaire null i want the Query return all Result of Categorie, diplome and ignore salaire
and when form salaire not null, i want the query return result of categorie+diplome+salaire list
this the controller
$data = $form->getData();
$repository = $this->getDoctrine()->getRepository(Candidat::class);
$candidats = $repository->findListByFilter($data->getCategorie(),$data->getDiplome(),$data->getSalaire());
This is the repository
public function findListByFilter($categorie,$diplome,$salaire):array
{
return $this->createQueryBuilder('c')
->andWhere('c.categorie = :categorie')
->andWhere('c.diplome = :diplome')
->andWhere('c.salaire <= :salaire')
->setParameter('categorie', $categorie)
->setParameter('diplome', $diplome)
->setParameter('salaire', $salaire)
->getQuery()
->getResult()
;
}

I recommend you to use IFs to accomplish this kind of request:
public function findListByFilter(string $categorie, string $diplome, ?float $salaire = null): array
{
$qb = $this->createQueryBuilder('c')
->where('c.categorie = :categorie')
->andWhere('c.diplome = :diplome')
->setParameters([
'categorie' => $categorie,
'diplome' => $diplome
]);
if($salaire) {
$qb->andWhere('c.salaire <= :salaire')->setParameter('salaire', $salaire);
}
return $qb->getQuery->getResult();
}
You are using Symfony 4 so I recommend you to start using type-hint for your variables.

Related

How to fetch data from single column stored in array using laravel?

I need to fetch the each and every column individually from the field array_payout can anyone solve it
$currentMonth_start_Date = Carbon::now()->startOfMonth()->subMonth(1);
$currentMonth_end_date = Carbon::now()->subMonth()->endOfMonth();
$clients_referral_tree = DB::table('mam_referral_payout')
->select('clients.id', 'mam_referral_payout.*')
//->addSelect(DB::raw('SUM(mam_referral_payout.Final_amount) as referral_amount'))
->leftjoin('clients', 'clients.id', '=', 'mam_referral_payout.to_id')
->where('clients.id', '=', (Auth::user()->id))
->whereBetween('mam_referral_payout.created_at', [$currentMonth_start_Date, $currentMonth_end_date])->get();
$clientTree = [];
foreach ($clients_referral_tree as $tree) {
$clientThree = $tree;
$clientTree[] = $clientThree;
}
dd($clientTree);
You can add the following to your Model:
protected $casts = [
"array_payout" => "object"
];
Add an accessor for each attribute in your json like this for example:
public function getTotalAmountAttribute(){
return optional($this->array_payout)->total_amount;
}
You can use them like this:
$clientTree1->total_amount;

Passing Laravel Collection to Vue

I am trying to return customers from model Customer where id < 10. I do have some in the database.
$customers = Customer::where('id', '<', 10)->get();
return json_encode(['customers' => $customers]);
The above code will error out "Trailing data"
and when I try to dd($customers), I get a list of the collection Customer
I have no idea why I keep getting that and why the model is returning raw collection and not an object of the list of customers???
It seems like a null date "updated_at" field is causing the error. don't know why!
Solved By:
on the Customer model I had to do:
//ask Laravel to not manage default date columns
public $timestamps = false;
also I to mutate those columns:
public function setDateRemindedAttribute($value)
{
if (strlen($value)) {
$this->attributes['date_reminded'] = Carbon::createFromFormat('d/m/Y', $value);
} else {
$this->attributes['date_reminded'] = null;
}
}
public function setUpdatedAtAttribute($value)
{
if (strlen($value)) {
$this->attributes['updated_at'] = Carbon::createFromFormat('d/m/Y', $value);
} else {
$this->attributes['updated_at'] = $_SERVER['REQUEST_TIME'];
}
}
Use response()->json() like this
$customers = Customer::where('id', '<', 10)->get();
return response()->json(['customers' => $customers]);

where condition in Codeigniter

i am trying to fetch data from the table which has some foreign keys by using codeigniter's active records. i haven't get any result. my question is where i'm going wrong here is my code in model.
public function fetch_customer()
{
$s = 'customer.stb_id';
$w_array = array('set_top_box.stb_id' => $s );
$customers = $this->db->select('customer.c_name,customer.acc_no,customer.stb_id,set_top_box.stb_no,customer.mobile_no,customer.subscription_amount,customer.c_status')
->from('customer,set_top_box')
->where($w_array)
->get();
return $customers->result();
}
Hello you can not add multiple table name in form () clause you use join() like this
public function fetch_customer()
{
$s = 'customer.stb_id';
$w_array = array('set_top_box.stb_id' => $s );
$customers = $this->db->select('customer.c_name,customer.acc_no,customer.stb_id,set_top_box.stb_no,customer.mobile_no,customer.subscription_amount,customer.c_status')
->from('customer')
->join('set_top_box','here on clause ')
->where($w_array)
->get();
return $customers->result();
}

How to return Repository Objects as Json on Symfony2

I'm trying to return the users like this, but of course it doesn't work, I need the data as JSon since im working with BackboneJs
/**
* #Route("/mytest",name="ajax_user_path")
*/
public function ajaxAction()
{
$em = $this->get('doctrine')->getManager();
$users = $this->get('doctrine')->getRepository('GabrielUserBundle:Fosuser')->findAll();
$response = array("users"=>$users);
return new Response(json_encode($response));
}
Thanks for your help guys, here is the Solution
Get the JMSSerializerBundle,
This is the code on the controller
/**
* #Route("/user")
* #Template()
*/
public function userAction()
{
$em = $this->get('doctrine')->getManager();
$users = $this->get('doctrine')->getRepository('GabrielUserBundle:Fosuser')->findAll();
$serializer = $this->get('jms_serializer');
$response = $serializer->serialize($users,'json');
return new Response($response);
}
So, findAll returns an array of entities (objects) and json_encode cannot correctly encode that array. You have to prepare your data berofe send response like that:
Example:
use Symfony\Component\HttpFoundation\JsonResponse;
/**
* #Route("/mytest",name="ajax_user_path")
*/
public function ajaxAction()
{
$users = $this->get('doctrine')->getRepository('GabrielUserBundle:Fosuser')->findAll();
$response = array();
foreach ($users as $user) {
$response[] = array(
'user_id' => $user->getId(),
// other fields
);
}
return new JsonResponse(json_encode($response));
}
Moreover, it would be great if you put preparing response to ex. UserRepository class.
With Symfony you have JsonResponse like :
return new JsonResponse($users);
And don't forget to add the header :
use Symfony\Component\HttpFoundation\JsonResponse;
I have never tried to encode a complete object, but I have used json with arrays of informations like this:
$vars = array(
'test' => 'test'
);
$response = new JsonResponse($vars);
return $response;
As you can see in JsonResponse, its function setData() is encoding the array, so you don't have to do it yourself:
public function setData($data = array())
{
// Encode <, >, ', &, and " for RFC4627-compliant JSON, which may also be embedded into HTML.
$this->data = json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
return $this->update();
}

Local sequence cannot be used in LINQ to SQL implementation

I'm getting an error, see below, when I try to generate a list of the class MappedItem. In short the code example below tries to find products by category, date range and SKU. The requirement I have is that the user should be able to enter a comma separated list of SKUs and the search is to find any product whos SKU starts with one of the SKUs entered by the user. When I run the code, I get.
Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator.
The abbreviated sequence is this:
Convert the comma separated string of SKUs into a list of strings.
string sku = TextSKU.Text;
List<string> skuList = sku.Split(new char[] { ',' }).ToList();
Define elsewhere in the code the class that will accept the search results.
public class MappedItem
{
public string ItemDescription { get; set; }
public int ItemCount { get; set; }
public MappedItem()
{
}
public MappedItem(string itemDescription, int itemCount)
{
ItemDescription = itemDescription;
ItemCount = itemCount;
}
}
Here's the query that I generate my results from
List<MappedItem> widgetItems = (from c1 in db.CCRCodes
join pac in db.widgetAssignedCodes on c1.code_id equals pac.code_id
join ph in db.widgetHistories on pac.history_id equals ph.history_id
where ph.contact_dt.Value.Date >= startDate && ph.contact_dt.Value.Date <= endDate &&
(string.IsNullOrEmpty(baanCatFam) || ph.baan_cat_family_code == baanCatFam) &&
(string.IsNullOrEmpty(baanCat) || ph.baan_cat_code == baanCat) &&
(string.IsNullOrEmpty(baanSubCat) || (ph.baan_sub_cat_code == baanSubCat)) &&
(string.IsNullOrEmpty(sku) || skuList.All(sl => ph.product_mod.StartsWith(sl)))
group c1 by c1.code_desc into ct
select new MappedItem
{
ItemDescription = ct.Key.ToUpper(),
ItemCount = ct.Count()
}).OrderByDescending(m => m.ItemCount)
.ToList();
I believe that the culprit is the line of code that I've extracted and displayed below.
skuList.All(sl => ph.product_mod.StartsWith(sl))
This identifies all skus that start with an element from the skuList which is derived from a comma delimited lists of skus entered by the user. My question is, what causes this error, and given the code examples, what do I do to get around them.
First - logically you want Any, not All.
Second, this is a poor way to build up a query filter. All of those operations are sent into the database, while the information to determine which filters should be applied is already local. The explicit joins are also bad (association properties could be used instead).
IQueryable<WidgetHistory> query = db.widgetHistories
.Where(ph => ph.contact_dt.Value.Date >= startDate
&& ph.contact_dt.Value.Date <= endDate);
if (!string.IsNullOrEmpty(baanCatFam))
{
query = query.Where(ph => ph.baan_cat_family_code == baanCatFam);
}
if (!string.IsNullOrEmpty(baanCat))
{
query = query.Where(ph => ph.baan_cat_code == baanCat);
}
if (!string.IsNullOrEmpty(baanSubCat))
{
query = query.Where(ph => ph.baan_sub_cat_code == baanSubCat);
}
//TODO sku filtering here.
List<MappedItem> widgetItems =
from ph in query
let c1 = ph.widgetAssignedCode.CCRCode
group c1 by c1.code_desc into g
select new MappedItem
{
ItemDescription = g.Key.ToUpper(),
ItemCount = g.Count()
}).OrderByDescending(m => m.ItemCount)
.ToList();
Third: the answer to your question.
what causes this error
LinqToSql's query provider cannot translate your local collection into sql. There's only a limitted set of scenarios where it can translate... .Where(ph => idList.Contains(ph.Id)) is translated into an IN clause with 1 parameter per int in idList.
To get around this limitation, you need to convert the local collection into an expression. Start by tranforming each item in the collection into a filtering expression:
List<Expression<Func<WidgetHistory, bool>>> skuFilters =
skuList.Select<string, Expression<Func<WidgetHistory, bool>>>(skuItem =>
ph => ph.ProductMod.StartsWith(skuItem)
).ToList();
Next, a helper method:
public static Expression<Func<T, bool>> OrTheseFiltersTogether<T>(
this IEnumerable<Expression<Func<T, bool>>> filters)
{
Expression<Func<T, bool>> firstFilter = filters.FirstOrDefault();
if (firstFilter == null)
{
Expression<Func<T, bool>> alwaysTrue = x => true;
return alwaysTrue;
}
var body = firstFilter.Body;
var param = firstFilter.Parameters.ToArray();
foreach (var nextFilter in filters.Skip(1))
{
var nextBody = Expression.Invoke(nextFilter, param);
body = Expression.OrElse(body, nextBody);
}
Expression<Func<T, bool>> result = Expression.Lambda<Func<T, bool>>(body, param);
return result;
}
And now putting it all together:
if (skuFilters.Any()) //this part goes into where it says "TODO"
{
Expression<Func<WidgetHistory, bool>> theSkuFilter = skuFilters.OrTheseFiltersTogether()
query = query.Where(theSkuFilter);
}