Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

rajrajeevkarn's avatar

DB::raw() method does not work in laravel 10

If we execute the following query, you will get an error

$users = DB::table('users') ->select(DB::raw('count(*) as user_count, status')) ->where('status', '<>', 1) ->groupBy('status') ->get();

Error

Either you may get the error as below: stripos(): Argument #1 ($haystack) must be of type string, Illuminate\Database\Query\Expression given

or

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'count(*)' in 'field list' (Connection: mysql, SQL: select count(*) as user_count, status from users where status <> 1 group by status)

Also DB::raw() does not work for mysql build in functions like date_format, concat etc.

0 likes
21 replies
Nakov's avatar

You can use selectRaw instead as you are not providing the table in your raw statement:

$users = DB::table('users')->selectRaw('count(*) as user_count, status')
	->where('status', '<>', 1) ->groupBy('status') ->get();

Does this work?

2 likes
rajrajeevkarn's avatar

@Nakov it still throws the same error SQLSTATE[42S22]: Column not found: 1054 Unknown column 'count(*)' in 'field list' (Connection: mysql, SQL: select count(*) as user_count, status from users where status <> 1 group by status)

Nakov's avatar

@rajrajeevkarn what about if you add them in an array:

->selectRaw(['count(*) as user_count', 'status'])
Nakov's avatar

@rajrajeevkarn btw, just installed Laravel 10 and tried similar query with DB raw, and everything works as expected.

Make sure you've got the correct database connection. And just try for example User::all(); and check if that will return any results.

jlrdw's avatar

@rajrajeevkarn

Also, try counting a field, here is an example of a count query:

        $quy = Powner::query()->leftJoin('dc_pets', 'dc_powners.ownerid', '=', 'dc_pets.ownerid')
                ->select('dc_powners.ownerid as oid', 'dc_powners.oname')//->distinct()
                ->selectRaw('count(dc_pets.petid) as CountOfpetid')
                ->groupby('dc_powners.ownerid')
                ->groupby('dc_powners.oname')
                ->orderby('dc_powners.oname')
                ->get();

Results basically give:

 oname, CountOfpetid

Like:

Bob|3
Greg|9
Rob|1

Just suggestion.

Or just use a regular GROUP BY query:

https://www.mysqltutorial.org/mysql-group-by.aspx

Edit:

The above is laravel 10.

mattdaneshvar's avatar

Argument #1 ($haystack) must be of type string, Illuminate\Database\Query\Expression given

This happens because expressions can no longer be cast to strings automatically in Laravel 10.

One way to overcome this is to explicitly call the getValue() method on your expressions. This, even though quite verbose, should do the trick for your example:

$expressionString = DB::raw('count(*) as user_count, status')->getValue(DB::connection()->getQueryGrammar());

$users = DB::table('users') ->select($expressionString) ->where('status', '<>', 1) ->groupBy('status') ->get();

The Database Expressions section in the Upgrade Guide has more details about this change.

4 likes
raveiga's avatar

Hi everyone.

I'm having the same problem. I upgraded my app to laravel 10 and I had to change some queries.

I'm working with the last one and I don't know how to adapt it to Laravel 10. I read about the expressionstring but I don't understand how to use it.

I get this error: "Argument #1 ($query) must be of type string, Illuminate\Database\Query\Expression given"

The query that worked correctly in Laravel 9:

$proveedoresResto = DB::select(DB::raw("SELECT distinct(proveedor_id) from ventas inner join proveedores on ventas.proveedor_id=proveedores.id where proveedores.tipo='P' and ventas.codigo_postal in (select distinct cpostal from cpostales where provincia in (SELECT provincia from cpostal_asociados where user_id='" . $delegado . "' and provincia is not null order by cpostal) UNION (select distinct cpostal from cpostales where area_sanitaria in (select distinct area_sanitaria from cpostal_asociados where user_id='" . $delegado . "' and area_sanitaria is not null))) order by proveedores.nombre"));

Any Idea to fix or adapt this query?

Thank you. Rafa

rajrajeevkarn's avatar

@raveiga Hi, This thread was created by me. I got a solution that I want to share with you. Step 1: go to vendor/laravel/framework/src/Illuminate/Contracts/Database/Query/Expression.php Change line no. 15 public function getValue(Grammar $grammar); to public function getValue();

Step 2: go to vendor/laravel/framework/src/Illuminate/Database/Query/Expression.php

change the function public function getValue(Grammar $grammar) { return $this->value; } to public function getValue() { return $this->value; }

Step 3: In the same class (noted above in step: 2), add a new function public function __toString() { return (string) $this->getValue(); } It would solve your problem

Thank you: Rajeev

2 likes
raveiga's avatar

@rajrajeevkarn

Ok Thank you.

I will try your solution, but I'm going to try to modify my query first to the eloquent format.

1 like
raveiga's avatar

Finally I could translate the query to eloquent format.

Thank you all.

Here it is, if it's useful for anyone:

               $tableA = DB::table("cpostales")
                    ->whereIn('provincia', function ($query) use ($delegado) {
                        $query->from('cpostal_asociados')
                            ->select('provincia')
                            ->where("user_id", "=", $delegado)
                            ->whereNotNull("provincia");
                    })
                    ->distinct()
                    ->select('cpostal')
                    ->orderBy('cpostal');

                $mergedWithTableA = DB::table("cpostales")
                    ->whereIn('area_sanitaria', function ($query) use ($delegado) {
                        $query->from('cpostal_asociados')
                            ->select('area_sanitaria')
                            ->distinct()
                            ->where("user_id", "=", $delegado)
                            ->whereNotNull("area_sanitaria");
                    })
                    ->distinct()
                    ->select('cpostal')
                    ->orderBy('cpostal')
                    ->union($tableA);

                $proveedoresRestoSpain = DB::table('ventas')
                    ->select('proveedor_id')
                    ->join('proveedores', 'ventas.proveedor_id', '=', 'proveedores.id')
                    ->where('proveedores.tipo', '=', 'P')
                    ->whereIn('ventas.codigo_postal', $mergedWithTableA)
                    ->orderBy('proveedores.nombre')
                    ->distinct('proveedor_id')
                    ->get();
1 like
felixpenrose's avatar

@rajrajeevkarn Never change vendor code. This is not controlled by you, should not be committed to a repo and will be overwritten as soon as you update vendor package.

rajrajeevkarn's avatar

@felixpenrose Yes, you are correct. But sometimes when an older project has to upgrade to the latest version, it is very tedious to change the whole code of the project according to the new version. So, my solution is just like a quick remedy for those who have the same situation as I explained above.

jlrdw's avatar

To those above, you shouldn't be changing vendor code.

6 likes
maurocecamore's avatar

Hi all!

I'm new of this cast but i'd like to advise you I had your same problem and I solved in a more elegant manner according to @felixpenrose and @mattdaneshvar suggestions...

Since as you know we are talking about OOP and since Laravel supports all OOP concepts and patterns, I created a new class (named for example DBO, because in my case I'm in Oracle :) )

<?php

namespace App\Facades;

use Illuminate\Support\Facades\DB;

class DBO extends DB
{
    public static function raw($query){
        return parent::raw($query)->getValue(parent::connection('oracle')->getQueryGrammar());
    }
}

... Then, in my app\config.php I took advantage of the aliasing override as follow...

    'aliases' => Facade::defaultAliases()->merge([
        // 'ExampleClass' => App\Example\ExampleClass::class,
        'DB' => App\Facades\DBO::class,
    ])->toArray(),

... and at the end, I simply call my new "DB" using it in my model or controller...

use DB;

and then simply using the method "raw" without neet to reeinger all code.

I hope my comments have been helpful.

Br.

2 likes
coreysan13's avatar

I like @maurocecamore's answer above. A wrapper around the DB::select(DB::raw(...)) calls would have helped isolate the problem from the start.

We solved this at our company by removing DB::raw entirely:

// Before
DB::select(DB::raw("select * from users"));

// After
DB::select("select * from users");
1 like
gsuero's avatar

I tried @maurocecamore solution and I liked it, but since the app I am working on has been abusing DB::Raw for a long time it does not fit my need. I ended up just finding the places where DB::Raw was casted to string and removing it. Thank you all.

markomo's avatar

Hi all, I am stuck in similar situation where ->distinct() does not work for me with leftJoin query. I've tried different variations suggested above including DB::RAW and without it.

When I run my query in Workbench it gives desired result. Example below with SELECT DISTINCT works well:

SELECT DISTINCT
    products.*,
    CASE WHEN reduced_price_products.barcode IS NOT NULL THEN 'Yes' ELSE NULL END AS reduced
FROM
    products
LEFT JOIN
    reduced_price_products ON products.barcode = reduced_price_products.barcode;

But when I use ->distinct() it gives different result (same as above but without DISTINCT).


$query->leftJoin('reduced_price_products', 'products.barcode', '=', 'reduced_price_products.barcode')            
                ->select('products.*')
                ->distinct()
                ->selectRaw("CASE WHEN reduced_price_products.barcode IS NOT NULL THEN 'Yes' ELSE NULL END AS reduced");

A bit odd one, and as well I could not manage to add groupBy as it was throwing bunch of errors.

kokoshneta's avatar

@markomo This has absolutely nothing to do with the original question. You should ask this is a new thread, not revive a year-old, unrelated thread.

amitsolanki24_'s avatar

@rajrajeevkarn #Try this

        $users = DB::table('users')
                          ->select(DB::raw('count(*) as user_count'), 'status')
                          ->where('status', '<>', 1)
                          ->groupBy('status')
                          ->get();

Please or to participate in this conversation.