Wrong GridView total rows count - yii2

I'm getting a weird result.
In my CustomerQuery i have some filters applied before the all() function.
(like
$this->andWhere(['profiles.type'=>'f']);
)
The filter gets applied before every find()->all(), but in the pagination count before the gridview it states
Showing 1-6 of 12 elements
If i check the query with Yii's debugger, i can see the count query used by yii to determine the number of elements is missing the profiles.type = "f" while the actual query doesn't.
Is this a bug? Is there another function i need to use instead of andWhere to apply the same filter to the count query?

Ok, it seems this in expected result (i'd expect and definitely prefer the count function to execute the exact same query, though).
To apply the same filter/where to both the real query and the count query you have to override the ActiveQuery's count method.
Here's an example
class ProfileQuery extends \yii\db\ActiveQuery{
...
public function standardFilters(){
$this->andWhere(['not',['table_name.status'=>2]]);
}
public function all($db = null){
$this->standardFilters();
return parent::all($db);
}
public function count($q = '*', $db = null) {
$this->standardFilters();
return parent::count($q, $db);
}
...

Related

SQL HAVING LIKE returning all results if a single match is found

I'm using knex (+ objection) to generate a HAVING LIKE query. I am adding the below to my query:
/*
This is the shape of queryString and valuesObject
queryString: ' :property0: like :value0',
valuesObject: {
value0: '%7963e2e2-3b5c-499d-bf42-f9b14ea804f8%',
property0: 'logTypeId'
}
*/
// This is where I add them to the query builder
query.having(raw(queryString, valuesObject));
If the ID isn't matched by any rows then nothing is returned as expected, however if id matches one then all rows are being returned.
The start of the query builder looks like this:
const query = Account.query()
.select('prospect:audit.logTypeId as logTypeId')
.where('trident_account.id', accountId)
.first()
.withGraphFetched('[prospect.[audit.[logType, actionBy]]]')
.joinRelated('prospect.[audit]')
.limit(limit)
.offset(offset);
What could be causing this? I have an identical setup on other queries that give the desired result (filter by ID)

Symfony Doctrine: Search in simple_array

I got values stored in my database column field as value1,value2,value3,value4, so a simple_array column.
So i'm using Doctrine to make a search using this:
$searchQuery = $this->getDoctrine()
->getRepository('AppBundle:Ads')
->createQueryBuilder('p')
->andWhere("p.vals <= :value2")
->setParameter('value2', $request->query->get('value2'));
->orderBy("p.creationtime", 'DESC');
So expecting value2 is in the 2nd position of a simple array like value1,value2,value3, how can i ask QueryBuilder to select the second value in the string?
I think this query try to get all the values in p.vals, results are not right, shound select just one.
How can I select eg. the 2nd value in p.vals?
I believe you cannot access nth item of an array column using pure Mysql since the data is serialized, in order to do it I'd create a simple function
public function getItemFromArray(array $array, $index)
{
return isset($array[$index]) ? $array[$index] : null;
}
And if you want to find item with condition use
array_filter()

Laravel Query Builder Issue

I'm trying to make it so that the items pulled from the database are only from the current month, however when I do this using various methods it throws an error (which I can't debug due to a the issue mentioned here). In the code below if I just simply paginate the full results it works fine, but when I start to use query builder methods it gives an error, does anybody have any idea why this error is occurring?
public function index()
{
// $trades=Trade::paginate(10);
$currentMonth = date('m');
$trades = DB::table('trades')->whereMonth('date', $currentMonth)->paginate(10);
// dd($trades);
$pastwinners=Winner::paginate(10);
return view('raffle', compact('pastwinners'), compact('trades'));
}
As you can see above the $pastwinners variable and the first $trades variable provide the proper values, but when I'm trying to select only the ones from this month (using the 'date' field) it seems to break.
Try this one. And if you want to paginate your results, do not forget to add pagination links to your view. Also do not forget the import Carbon in your controller class.
https://laravel.com/docs/5.6/pagination
public function index()
{
$trades = Trade::whereMonth('date' , Carbon::today()->month)->paginate();
$pastwinners = Winner::all();
return view('raffle', compact('pastwinners', 'trades');
}

How to pass one of the mysql query results in the model from controller?

In my controller I have called a model that makes a mysql query to fetch information from table. It is working okay but now under the same function I want to call another model and make a query based on one of the results from the previous mysql query. (The field name which I want to get the result of is "batch") . I have tried to get the value (batch) right in my controller, pass it into the model and then tried to make the second query but it seems like the second model is not getting the value from the controller and hence its not working. Would you please kindly help me with this?
Thanks in Advance :)
Here is my Controller
function Get($id){
$this->load->model('mod_studentprofile');
$data['query']= $this->mod_studentprofile->student_get($id);
// To get the batch name
$batch= $query ['batch']; // This I get from the above query result.
$this->load->model('batchname');
$data['query1']= $this->batchname->batchname($batch);
$data['tab'] = "Student Profile";
$data['main_content']='studentprofile';
$this->load->view('includes/template',$data);
}
Here is my model number 1
function student_get($id)
{
$query=$this->db->get_where('student',array('studentid'=>$id));
return $query->row_array();
}
Here is my model number 2
function batchname($batch)
{
$query1=$this->db->get_where('batch',array('batchid'=>$batch));
return $query1->row_array();
}
Well, you're not actually assigning anything to $batch, how about this:
$batch= $data['query'];
This now passes the variable along. As a side note, you can pass it as a paramater and be done with it in a single line, dependency injection style:
$data['query1']= $this->batchname->batchname($this->mod_studentprofile->student_get($id));
Are you getting a value back from the first query?
I would log the value you are getting back from the first query in your controller.
log_message('debug', 'Batch value is '.$batch);
And also put in some debug to see what the query that is being ran.
function batchname($batch)
{
$query1=$this->db->get_where('batch',array('batchid'=>$batch));
$str = $this->db->last_query();
log_message('debug', 'Batchname Query: '.$str);
return $query1->row_array();
}

Linq: Simple Boolean function returns linq Exception

I have a Linq query that looks something like this:
var query = from x in table where SomeFunctionReturnsBool() select;
private bool SomeFunctionReturnsBool()
{
return true;
}
This returns and exception that says "SomeFunctionReturnsBool has no supported translation to SQL". I get that this is because it wants to treat "SomeFunctionReturnsBool" as an expression to evaluate as SQL, but it can't.
Although this Linq query isn't complicated, the real ones are. How can I accomplish what I'm trying to do here, which is to break out pieces of the query to hopefully make it more readable?
Jeff
UPDATE
Good answers. I am trying now to work with expressions instead, but this code gets me "cannot resolve method Where(lambda expression)":
var query = from x in table where SomeFunctionReturnsBool() select x;
private Expression<Func<EligibilityTempTable, bool>> SomeFunctionReturnsBool
{
return (x) => true;
}
Another way is to use Expression<Func<YourType, bool>> predicate...
var query = from x in table where SomeFunctionReturnsBool() select;
Edit: I don't usually do it the way I've shown above... I was just getting that from the code above. Here is the way I usually implement it. Because then you can tack on additional Enumerable methods or comment them out during debugging.
var results = table.Where(SomeFunctionReturnsBool())
.OrderBy(yt => yt.YourProperty)
//.Skip(pageCount * pageSize) //Just showing how you can easily comment out parts...
//.Take(pageSize)
.ToList(); //Finally executes the query...
private Expression<Func<YourType, boo>> SomeFunctionReturnsBool()
{
return (YourType yt) => yt.YourProperty.StartsWith("a")
&& yt.YourOtherProperty == true;
}
I prefer to use the PredicateBuilder which allows you to build an expression to be used in your Where...
You can do this in LINQ-to-SQL by creating a UDF mapped to the data-context; this involves writing TSQL, and use ctx.SomeFunctionblah(...).
The alternative is to work with expression trees - for example, it could be:
Expression<Func<Customer, bool>> SomeFunc() {
return c => true; // or whatever
}
and use .Where(SomeFunc()) - is that close enough? You can't use the query syntax in this case, but it gets the job done...
Added dodgy Where method to show how you might use it in query syntax. I don't suggest this is fantastic, but you might find it handy.
using System;
using System.Linq;
using System.Linq.Expressions;
static class Program
{
static void Main()
{
using (var ctx = new NorthwindDataContext())
{
ctx.Log = Console.Out;
// fluent API
var qry = ctx.Customers.Where(SomeFunc("a"));
Console.WriteLine(qry.Count());
// custom Where - purely for illustration
qry = from c in ctx.Customers
where SomeFunc("a")
select c;
Console.WriteLine(qry.Count());
}
}
static IQueryable<T> Where<T>(this IQueryable<T> query,
Func<T, Expression<Func<T, bool>>> predicate)
{
if(predicate==null) throw new ArgumentNullException("predicate");
return query.Where(predicate(default(T)));
}
static Expression<Func<Customer, bool>> SomeFunc(string arg)
{
return c => c.CompanyName.Contains(arg);
}
}
Basically, "out of the box", you can't have LINQ-to-SQL execute queries that have custom functions in them. In fact only some native methods that can be translated to SQL can be used.
The easiest way around this can unfortunately affect performance depending on how much data you're bringing back from the DB.
Basically, you can only use custom functions in WHERE statments if the data has already been loaded into memory, i.e, SQL have already executed.
The quickest fix for your example would look like this:
var query = from x in table.ToList() where SomeFunctionReturnsBool() select;
Notice the ToList(). It executes the SQL and puts the data into memory. You can now do whatever you want in the WHERE statement/method.
I would just break them out like so:
Expression<Func<Table, bool>> someTreeThatReturnsBool = x => true;
var query = from x in table where someTreeThatReturnsBool select x;
You could create functions that pass around expression trees.
Don't use query syntax for this.
var query = table.Where( x => SomeFunction(x) );