Why PHP considers MySQL INT columns as strings? - php

I am using a Laravel query builder to search for categories.
Here it is:
$array[] = $categories->where('pk_i_id', $category_id)->first();
I have to manually convert the category id to string, even though in database it is Integer type. Why do I have to do this?
Actually - I have to do this on Linux machine with Lamp stack installed. On Windows machine with Xampp it considers the column as integer as it should.

The issue sounds more like that $categories is already a Collection, not a Builder. Both the Collection and the Builder have a where() method, but their logic is not the same.
The where() method on the Builder will add a parameterized where clause to the query run against the database. In this case, the type of variable doesn't matter.
However, the where() method on the Collection will loop through the collection and return those results where the field in the first parameter is strictly equal (===) to the value passed in the second parameter. To change this, you can pass false as the third parameter, and it will use a loose comparison (==) instead of strict. Additionally, you could use whereLoose(), which is a shortcut for where() with the third parameter as false.
$array[] = $categories->where('pk_i_id', $category_id, false)->first();
// or
$array[] = $categories->whereLoose('pk_i_id', $category_id)->first();
If the incorrect field types are causing more issues that what you've described, then you may want to work on fixing the underlying issue. As has been pointed out in the linked posts, on your LAMP stack you need to replace the mysqld driver with the mysqlnd driver.

Related

MySQL select query finds a result that shouldn't be found in PDO

So, for a school assignment I have to make a website. This website must contain a functionality that gets articles out of a database.
I can, for example, show article 1 with domain.com/content/article/1/.
However, when I use a URL like this domain.com/content/article/2aadd/ it still shows article 2.
Even ../10aadd/ shows article 10.
If I try to request an article that doesn't exist with like ../11aadd (article 11 doesn't exist) it will show an error that it can't find the article, like it should.
I use URL rewriting so a URL like this domain.com/content/article/1/ is rewritten as domain.com/index.php?c=content&a=article&arg=1
I use a database class, every select query is sent to a select-query method. It accepts the following parameters:
$q - the query
$params - an array with parameters for the query
$fetch - the fetching mode
The following parameters are sent in order to show an article:
select title,content from PHP2b_OOP_EIND_Articles where id=:id and enabled=1
array("id"=>$_GET["arg"])
assoc
In every call of this method a new statement is being prepared and executed with the $params array as parameter.
I've dumped out the $params array and it does show the entire string (e.g. 10aadd).
I've tried it without the clean URL.
I've tried to look it up but I couldn't find anything.
What could be the cause of this?
I suspect your MySQL table's id column is defined as an integer data type.
You're experiencing a peculiarity of MySQL when it coerces a string data type to an integer.
select CAST('10aaadd' AS INT)
gives back the value 10, strangely enough.
Your query, after variable substitution, says WHERE id = '10aaadd'.
Because MySQL implicitly casts that string to an int, it finds the row with the id value of 10.
Weird, huh?
If you expect only integers in a $_GET or $_POST parameter, it's a good idea to check for that and throw an error if the values you receive don't match expectations. PHP's is_numeric() function can do that for you.

Laravel where 'less than' query not showing expected results

I am trying to make a database query where I search for all of the items which have a lower current level than low stock level. When running the query I am getting no results and I'm not sure why.
This is my query
public static function getLowStockItemsCache()
{
dd(\DB::table('items')->where('current_level', '<', 'low_stock_level')->get());
}
When I die and dump this I get an empty collection.
In my database I have the following records
Both of these fields at set at int(11)
If I reverse the query I get all 13 records.
Am I missing something small, as it's confusing me greatly and should be simple.
The third parameter is the value parameter which means it will be escaped when building the query to avoid SQL injection. If you want to compare two columns, you have to specifically tell the Query Builder that that part of the query should not be processed, either by using whereRaw to pass the raw SQL condition:
\DB::table('items')->whereRaw('current_level < low_stock_level')->get());
Or by using DB::raw() for the value only, so it's not escaped:
\DB::table('items')->where('current_level', '<', DB::raw('low_stock_level'))->get());
Laravel use 3 step argument on the "where" clause,
Pair::where('1st','2nd','3rd')
by default the 2nd arg is normally default equal sign, saying the 1st arg is equal to the 3rd arg,
Pair::where('name', 'john')->get();
Pair::where('stock', '<', '100')->get();
When you find this logics then you understand the "where" tricks

Laravel 4 Build Query where clause on the fly

I am porting my code from CodeIgniter to Laravel. and have some question regarding the query builder.
In codeigniter, I can just add where clause to the active record object, as I initialize each property in a class like
$this->db->where('xxxx','bbbb');
in one property initialize function, and
$this->db->where('yyyy','aaaa');
in another property function, and it will all chain up until i fire off the query. But this doesn't seem to be the case of Laravel.
Here is what I do in laravel in each property initialize function
DB::table($this->table)->where('xxxx','bbbb');
DB::table($this->table)->where('yyyy','aaa');
and when a actual method is call from outside, it runs
DB:table($this->table)->get();
but this gives me a SELECT * FROM TABLENAME without anywhere clause. So what am I doing wrong here :x or I just shouldn't treat laravel same as codeigniter and think of something totally different to handle this kind of dynamic where clause?
Also in codeigniter, you can set a section of the query to cache, so even after you fire off the query , those section retains for next query, usually the where clause. Is there a similar function in Laravel? Thank you!
You can assign your current workings to a variable, and build upon that, let me show you an example based on your example:
Instead of this
DB::table($this->table)->where('xxxx','bbbb');
DB::table($this->table)->where('yyyy','aaa');
Try this...
$query = DB::table($this->table)->where('xxxx','bbbb');
$query->where('yyyy','aaa');
$results = $query->get();
I just shouldn't treat laravel same as codeigniter and think of something totally different to handle this kind of dynamic where clause?
This is not dynamic where clause.
and please, make a habit of reading the documentation.
From the docs of Fluent query builder
$users = DB::table('users')->where('votes', '>', 100)->get();
you can set a section of the query to cache, so even after you fire off the query , those section retains for next query, usually the where clause. Is there a similar function in Laravel?
$users = DB::table('users')->remember(10)->get();
Next time, just open up the docs. they contain all this.

How can I retrieve integer values for integer columns in CakePHP?

When I do a find or fetch, the returned array of values contains string representations of all my columns regardless of the column's data type. This means instead of integer columns returning like:
array( 'field1' => 1 )
they end up as
array( 'field1' => '1' )
Is this expected behavior for CakePHP? Did I misconfigure something?
I thought about writing some code in the afterfind method of my models to call intval on the appropriate columns, but is that really the best solution? Does CakePHP have a better way of handling non-string columns?
You can figure out what kind of field a field in the table your model is from the model property Model::_schema. Based on that you could type cast the values for your fields in the Model::afterFind() callback.
You can also manually check the fields you want to be integers but using _schema would allow you to automate it. You could do this as a behavior for example and attach it to every model that needs this functionality.
So simply iterate over the results and check for the fields you want to be integers and type cast them.
I noticed this too, and apparently it's the result of PDO casting everything to string. I submitted a ticket and hopefully there might be an automatic feature to coercion feature in the future.
Although the clients could convert the data, it's not very 'clean' especially when you might be providing the api to 3rd party developers.

How do I do a boolean OR in solr?

I am completely new at this...
I am using durpal with the apachesolr module.
I have the following filter:
( tid:19895 OR tid:19937 ) AND type:poster"
This does not return any results, but if I have the following, it returns the results as expected
( tid:19937 ) AND type:poster"
EDIT: This is all in a filter. I need to have a list of tids that it could be along with having type be poster. So it has to be type:poster AND one of the following tids: 19895, 19937
although:
((tid:(19895 OR 19937)) AND type:poster) should work irrespective of defaultOperator being OR/AND
adding the clauses as separate filter is better, so add two filters as
tid:(19895 OR 19937)
type:poster
should filter out the results working as AND and also cache the results for this filter separately for improved query performance for new queries using this filter.
I think its important to note that SOLR isn't a database. Its a search engine and therefore isn't going to work like a database query you may be used to.
adding a + means the field is required
+tid:19895 would mean that TID field is required to equal exactly 19895
The * is the wildcard so adding it means your field would contain the value but not necessarily equal the value.
tid:19895* would mean TID field contains 19895
It looks like the issue is defining the field twice in the same filter???
So try removing the second "tid:"
In my testing I did this:
My SOLR query is:
+type:poster
And the Filter is:
tid:19895 OR 19937
Here is another stackoverflow question similar to yours since you obviously have a different syntax than I use.
using OR and NOT in solr query
As FYI if defalut boolen clause is "OR" then give the query like this
((tid:(19895 19937)) AND type:poster) This working fine i tested

Categories