I am trying to use a case control structure in a Laravel.I can not for the life of me get the required 'blueberry' result even though there are muffins with the 'App\Models\blueberrymuffin' type in the database.
$muffintype=DB::table('muffins')
->select(
DB::raw"(CASE muffin_type WHEN 'App\Models\blueberrymuffin' THEN 'Blueberry' END)" ))->get();
I don't think it is my syntax since when I test this out it works.
$muffintype=DB::table('muffins')
->select(
DB::raw"(CASE milk_type WHEN 'coconut' THEN 'Vegan' END)" ))->get();
I am thinking it has something to do with the ""in the muffin type. The muffin_type is a varchar(255). Does anyone have a clue because I am very perplexed. Thank you in advance
If a string contains forward slashes, those should be escaped:
DB::raw("(CASE muffin_type WHEN 'App\\Models\\blueberrymuffin' THEN 'Blueberry' END)")
Pls also have a look at this thread.
Related
I am migrating an old TYPO3-extension to the current build and am trying to change my database access to using doctrine. For the most part that worked great, but now I came upon a few select queries, that make use of SQL-functions e.g. "Year(FROM_UNIXTIME())".
I tried using the sql function as is in the following form:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('mytable');
$queryBuilder
->select('i.*','c.title AS cat_title','c.uid AS cat_uid')
->from('mytable','i')
->join('c'
...
)
->join('d'
...
)
->where(
$queryBuilder->expr()->eq('Year(FROM_UNIXTIME(i.datetime))', $queryBuilder->createNamedParameter($year, \PDO::PARAM_STR))
)
The problem is only with the where part, if i get a read-out on the SQL statement the where clause is simply omitted, as if the line of code never happened.
I then proceeded to make debug statements around the where statement and encapsulate it in a try catch block with a log attached to it:
It executes fine, without error, but does nothing.
After google, I now believe, that i would need to implement that function again using the DQL user functions, but the documentation on the typo3 site offers no mention of this and so i am a little unsure as to how to proceed.
Can someone point me in the right direction?
Any help would be much appreciated
Regards
Theo
I defaulted to using php to parse the years to full dates and convert them to unix timestamps. The option of using the ORM was there, but simply too much to handle.
I implemented it as follows:
// to convert towards db:
$queryBuilder->createNamedParameter(mktime(0,0,0,1,1, (int)$year), \PDO::PARAM_INT)
// and back:
$queryBuilder->select('i.datetime AS yearb')
// ... the rest of the query seems of litle interest
;
$current = date("Y",$queryBuilder->execute()->fetch()['yearb']);
You can use plain SQL:
$queryBuilder
->select('i.*','c.title AS cat_title','c.uid AS cat_uid')
->from('mytable','i')
->join('c'
...
)
->join('d'
...
)
->where(
'Year(FROM_UNIXTIME(i.datetime)) = '.$queryBuilder->createNamedParameter($year, \PDO::PARAM_STR)
)
I have problem in searching, I am using Laravel 5.5 version, the situation like this: I have groups which study during some period of time. On filtering page, Admin enters study starting date and ending date, the result must show all groups which studied or studying between given time period. A comparing in simple way is not working, I would like to use strtotime function, but when I use:
->where(strtotime('edu_ending_date'),'=<',strtotime($edu_ending_date));
the eloquent is saying there is not such a column name ...
if(!empty($input['daterange']))
{
$q->where(function($query)use($edu_starting_date,$edu_ending_date){
$query->where('edu_starting_date', '>=', "$edu_starting_date")
->where('edu_ending_date','=<',"$edu_ending_date");
});
}
if you need to use dates in your where clauses I might want to have a look at this article and this section of laravel docs where they mention additional where clauses which include also whereDate, whereDay, etc. Might come in handy. In your case I would suggest you to do two whereDate conditions to act as between:
$query->whereDate('edu_starting_date', '>=', $edu_starting_date)
->whereDate('edu_ending_date', '=<', $edu_ending_date)
Note that $edu_starting_date and $edu_ending_date are recommended to be a Carbon object or output of PHP's date function. If you want to use strings according to the Laravel docs it should be possible. Hopefully this helps you :)
You can use
$q->whereBetween('edu_starting_date', [$edu_starting_date,$edu_ending_date])
try this:
if(!empty($input['daterange']))
{
$q->where(function($query)use($edu_starting_date,$edu_ending_date){
$query->where('edu_starting_date', '>=', $edu_starting_date)
->where('edu_ending_date','=<',$edu_ending_date);
});
}
The date is saved as a string in my database, is that ok, that is why I would like to use
something like this:
->where(strtotime('edu_ending_date'),'=<',strtotime($edu_ending_date));
You can use DB::raw
->where(DB::raw("strtotime('edu_ending_date')"),'=<',strtotime($edu_ending_date));
Thank you guys, I found my stupid mistake, I stored date as a string.
(integer) cast must be done in Homestead for Controller parameter
I am having a hard time searching for the cause of a discrepancy between my local dev environment (Homestead) and the hosted one.
I define a route like this:
Route::get('group/{id}/data', 'GroupDataController#index');
And the code in the Controller looks like this:
public function index($id)
{
return Grouping::all()->where('group_id', $id);
}
Which works fine in production (hosted env), BUT when I execute it locally it throws and empty array [] unless I modify my Controller function to look like this:
public function index($id)
{
return Grouping::all()->where('group_id', (integer)$id);
}
I have no idea of what is going on in here, and I am tired of making changes all over my Controller to make it work on both environments.
I have searched in several place, but maybe I am using incorrect tokens for my search as I have found nothing.
Any help will be really appreciated.
The problem here is that you're not using the correct set of functions.
When you call Grouping::all(), this is actually returning an Eloquent Collection object with every record in your groupings table. You are then calling the where() method on this Collection. This causes two problems: one, it is horribly inefficient; two, the where() method on the Collection works differently than the where() method on the query builder.
The where() method on the Collection takes three parameters: the name of the field, the value in that field on which to filter, and finally a boolean value to tell it whether or not to do a strict comparison (===) or a loose comparison (==). The third parameter defaults to strict. This strict comparison is why you're having the issue you are having, but I cannot explain why one environment sees $id as an integer and the other doesn't.
The where() method on a query builder object will actually add a where clause to the SQL statement being executed, which is a much more efficient way of filtering the data. It also has more flexibility as it is not limited to just equals comparisons (the second parameter is the comparison operator for the where clause, but will default to "=" if it is left out).
You have two options to fix your issue. You can either pass in false as the third parameter to your where() method in the current code (bad), or you can update the code to actually filter using the query instead of filtering on the entire Collection (good).
I would suggest updating your code to this:
public function index($id) {
return Grouping::where('group_id', '=', $id)->get();
}
In the above code, Grouping::where('group_id', '=', $id) will generate a query builder object that has the given where clause, and then get() will execute the query and return the Collection of results.
I marked #patricus (thanks you, so much!) as the correct answer, for he really pointed me in the right direction to understand that there are some keywords that work differently under different contexts (like get()), but I will also point out, how my 2 confusing points were solved in my case:
The difference in my code between production and Homestead development environments was solved by pointing my Homestead to the production database. I am not sure what was the difference (maybe collation or table format), but it gave me a quick out.
I was trying to filter a list of elements in the database but I was constructing it with the wrong logic for Laravel.
To clear what I refer to in the second point, I was using this code:
Grouping::all(['id', 'name_id', 'product_id', 'ship_id'])->where('name_id', '=', $id);
I thought this could work, because it would be selecting all items, with the selected columns, and then filter those with a where clause. But I was wrong, since, as I found out later, the correct way of writing this is:
Grouping::where('name_id', $id)->select('id', 'name_id', 'product_id', 'ship_id')->get();
This is because I forgot completely that I was assembling the query, not writing the actions I expected the program to do.
This second syntax has more logic, since I specify the filter, then put the columns over what was filtered, and finally execute the query with the get() clause.
Of course, it can also be written the other side around for clearer fluent reading:
Grouping::select('id', 'name_id', 'product_id', 'ship_id')->where('name_id', $id)->get();
I am learning about Laravel 4 and I'm trying its pagination. I created a simple query to test the pagination, yet it always end up hanging. If I use get(), it works fine, but when I replace get() with paginate(), it hangs. Here is my code:
DB::table("samp_tbl")
->select("id","activity")
->whereNull("deleted_at")
->orderBy("id","desc")
->paginate(5);
Could someone tell me what's wrong with my code?
In case anyone else comes across this issue it's because you are using orderBy. In the Note: area on this page http://laravel.com/docs/4.2/pagination#usage it explains that laravel has issues with groupBy. However I also would assume this would go for orderBy as well. Writing a custom query would be recommended in your case.
create a model for your database and it will work fine
Conider this simple query:
$this->db->join('bids','bids.bid_for = request_quote.quoteid','left');
Is there any way possible to alter it, so instead of joining the result, it would instead join the COUNT of all bids it find?
I could rewrite this in plain SQL, but it is a part of bigger query, which I dont want to rewrite in SQL
Tough one. I've looked at the CI's source code, and I don't see a "hack" for that.
Perhaps you could use this CI's method:
$this->db->count_all_results();
Ok after messing around for couple hours I got it to work, so ill share it just in case anyone need it again:
public function getAllJobsByUserId($userid){
$this->db->select('quoteid')->select('quoteby')->select('country_from')
->select('country_to')->select('city_from')->select('city_to')
->select('countries.country_name, countries_to.country_name AS country_name_to')
->select('COUNT(\'bids.bid_id\') as bid_count');
$this->db->from('request_quote');
$this->db->where('quoteby',$userid);
$this->db->join('countries','countries.country_id = request_quote.country_from');
$this->db->join('countries as countries_to','countries_to.country_id = request_quote.country_to');
$this->db->join('bids as bid_count','bid_count.bid_for = request_quote.quoteid','outter');
$query=$this->db->get();
return $query->result();
}
This seem to work. But still in future ill probably write more complex queries in straight up SQL :)