Laravel / Eloquent - how to ORDER BY FIELD - laravel

I'm trying to sort my query results based on a series of slash-separated ids (from the URL, e.g. /10/25/1). I grab the URL segments and explode them to get an array with elements 10, 25, 1. Now, I want my SQL to be something like this:
ORDER BY FIELD(`products`.`id`, 10, 25, 1)
In Eloquent, I'm trying to do this:
->orderByRaw('FIELD(`products`.`id`, ?)', [implode(', ', $product_ids)])
But that outputs something like this:
ORDER BY FIELD(`products`.`id`, "10, 25, 1")
I could declare a variable, loop through my array, and build the string 10, 25, 1 and just use that variable in place of the ? -- however, I would not be getting the benefit of whatever Eloquent does to prevent SQL injection attacks.
Suggestions?

Each parameter needs to have its own placeholder.
You can implode placeholders and pass the array as a parameter:
$placeholders = implode(',', array_fill(0, count($product_ids), '?'));
->orderByRaw("FIELD(`products`.`id`, $placeholders)", $product_ids)

Related

Incorrect sort of DB query results in micronaut project

I am passing this to the repository function:
Pageable.from(offset, limit).order(Sort.Order(orderBy, direction, true))
It works just fine if orderBy is the name of a String property. If I try to sort by a number property it will return the results ordered as:
1,
11,
12,
...
19,
2,
20,
21
Any suggestions on how to fix for the number ordering?
Doing the sort on the method name (such as findAllOrderByNameAsc) is not an option because this is a parameter that comes from the API. We need to support ordering by any property.
remove the ignoreCase=true parameter or pass it as false
Sort.Order(orderBy, direction, true)
you should use ignoreCase only on String fields

Get last few rows in ascending order in Laravel

What is the best way (Laravel way) to get last few rows of a database table in ascending order? I want the result to be an array of objects as like:
[{"name1":"value1"}, {"name2":"value2"}]
My recent code is like:
$users = User::take(2)->latest()->get()->reverse();
return $users;
Output looks like:
{"1":{"id":582, "name":"name1"}, "0":{"id":583, "name":"name2"}}
But I want the output to be like:
[{"id":582, "name":"name1"}, {"id":583, "name":"name2"}]
When you use the reverse() method, it modifies the Collection, but doesn't re-index it, meaning the Collection is now [1, 0]. JS/JSON treats this as an Object instead of an array, hence the difference:
{"1":{"id":582, "name":"name1"}, "0":{"id":583, "name":"name2"}}
// VS
[{"id":582, "name":"name1"}, {"id":583, "name":"name2"}]
To solve this, use the values() method to re-index the array before return:
$users = User::take(2)->latest()->get()->reverse();
return $users->values();
// [{"id":582, "name":"name1"}, {"id":583, "name":"name2"}]
If you want them in the other order, don't use reverse(), and you shouldn't need values() either:
$users = User::take(2)->latest()->get();
return $users;
// [{"id":583, "name":"name2"}, {"id":582, "name":"name1"}]

Laravel database builder substrings

In my database i have field ('content') which one contains strings. My server should gets only 100 first chars from those strings (can be less but not more) how can i achieve that? I have tried 'SUBSTRING(content, 1, 100)'
using method above laravel gives error : Column not found: 1054 Unknown column 'SUBSTRING(...
Use the selectRaw method like this:
$orders = DB::table('tableName') ->selectRaw('SUBSTRING( ... ), ...)->get();
For more info check the docs here. https://laravel.com/docs/5.7/queries#raw-expressions
You can also take it out and intercept it.
$content = DB::table('tableName')->limit(1)->value('content');
echo substr($content, 0, 100);

Laravel get all the values of a column beginning with a number

I have a model called "Image" and a table called "images". The table has a column for the "id" and another for the "name". I need to fetch only the rows with the name beginning with a number.
I need to fetch are called something like
16783521_facebook.png
While the others are something like...
twiter.png
Try this:
Image::whereRaw("name REGEXP '^[0-9]'") -> get();
If it's something you're going to use in more than 1 place, consider moving it to a scope.
In your image model define something like:
public function scopeNumeric($query)
{
return $query -> whereRaw("name REGEXP '^[0-9]'");
}
Then you can just use:
Image::numeric() -> get();
I dont know much about laravel, but this plain query will help -
SELECT * FROM mytable WHERE mycolumn REGEXP '^[0-9]+$' or
SELECT * FROM myTable WHERE col1 REGEXP '[0-9]+';
Laravel doesn't have that built-in, so you'll have to make do with raw queries. In its base form:
$results = SomeModel::whereRaw("some_column REGEXP '^[0-9]'")->get();
You can modify this as usual with selects, other limitations, etc. as you require.
Filter the images after the query using one of the collection methods. Like below solved me.
$onlyNumeric = $photos->filter(function ($value, $key) {
return is_numeric(substr($value, 0, 1));
});

How to get only Odata.Count without value

Is there any way I can get only count of the data in response payload without any value array?
I am using ODataV4.0 with Webapi 2.2.
Currently it returns all the values and count when I query something like:
http://odata/People?$count=true
I just need something like "#odata.count":1, "value":[] or without "value".
Is the only way to have function for this job?
Set the $top to zero and $count to true.
For example:
http://services.odata.org/V4/Northwind/Northwind.svc/Customers?$count=true&$top=0
returns the count but no results
{
"#odata.context": "http://services.odata.org/V4/Northwind/Northwind.svc/$metadata#Customers",
"#odata.count": 91,
"value": []
}
Count is calculated after applying the $filter, but without factoring in $top and $skip.
For example: http://services.odata.org/V4/Northwind/Northwind.svc/Customers?$count=true&$top=0&$filter=Country%20eq%20%27Germany%27
informs you that there are 11 results where the Country is 'Germany', but without returning any records in the response.
You can also append $count as a path element to just get a raw count, E.G.,
https://services.odata.org/V4/Northwind/Northwind.svc/Customers/$count
This will also work with filters, etc, applied:
https://services.odata.org/V4/Northwind/Northwind.svc/Customers/$count?$filter=Country%20eq%20%27Germany%27
For a count of Customers in Germany.

Resources