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

denewey's avatar

Error Generated By Explicitly Set Table Name

I have an inherited site with a 'Location' model that I set up. The database table for this model is 'top_locations', which is explicitly set in the model with the line:

protected $table = 'top_locations';

This table has, among other columns, the columns of 'id' and 'name'.

Unfortunately, there is also a 'locations' table in the database, which has the columns, 'location_id' and 'location_name'. This table was originally set up by a db admin for the purpose of processing data and changing column names and such would wreak havoc on the data processing. That's why I set up the 'top_locations' table for the 'Location' model. The 'locations' table is one over-arching table that includes 3 levels of location->zone->subzone, with recursive reference one to the other.

I created the 'top_locations' table in order to create the correct Eloquent structure for the 'Location' model, for which I also created a 'Zone' model with a 'zones' table as a child to the 'top_locations' table and a 'SubZone' model with a 'sub_zones' table as a child to the 'zones' table.

Since the 'top_locations' , 'zones' and 'sub_zones' tables need to remain in sync with the 'locations' table I created triggers in the database that automatically update the appropriate tables when the 'locations' table is updated. This is also necessary because the db admin has his own tool for updating the 'locations' table so that has to be the stable location for updates. To align the Controller code with this structure, the store() method uses a raw query to insert into the 'locations' table.

However, I am unable to do this with the patch() method because there is a validation function that is triggered that checks to see if the location name already exists. But it is looking for the field 'name' (found in the 'top_locations' table) and it is looking in the 'locations' table which has the field 'location_name' . This is the error message:

SQLSTATE[42703]: Undefined column: 7 ERROR: column "name" does not exist LINE 1: ...lect count(*) as aggregate from "locations" where "name" = $... ^ (SQL: select count(*) as aggregate from "locations" where "name" = Admin FAN Press and ("venue_id" in (190, 57, 156, 288, 321, 56, 354, 24, 6, 51, 22, 123, 23, 8, 11, 222, 90, 9, 387) and "id" <> 232))

The code I have for the update is:

$location_name = $request->input('name');
        $location_type_id = $request->input('location_type');

        $query = "UPDATE public.locations SET location_name = $location_name,";
        $query .= " location_type_id = $location_type_id ";
        $query .= "WHERE location_id = $id";

        try {
            DB::connection('console')->update($query);
        } catch (\Illuminate\Database\QueryException $e) {
            return redirect()->back()
                ->with('failure', trans('app/settings/locations.view.form.messages.failed'));
        }

I don't know why the validation function isn't picking up the explicitly defined 'top_locations' table that is set in the 'Location' table.

The stack trace references code from 3 middleware classes:

Illuminate\Pipeline\Pipeline Illuminate\Pipeline\{closure}
…/app/Http/Middleware/CompanyAdminMiddleware.php29
35
Illuminate\Pipeline\Pipeline Illuminate\Pipeline\{closure}
…/app/Http/Middleware/ImpersonateMiddleware.php24
29
Illuminate\Pipeline\Pipeline Illuminate\Pipeline\{closure}
…/app/Http/Middleware/AppMiddleware.php107

CompanyAdminMiddleware.php code:

public function handle($request, Closure $next)
    {
        $user = Auth::user();

        if (!$user->hasRole('sys_admin') && !$user->hasRole('comp_admin')) {
            if ($request->ajax() || $request->wantsJson()) {
                return response('Unauthorized.', 401);
            }

            return redirect(route('app.dashboard'));
        }

        return $next($request);  //line 29
    }

ImpersonateMiddleware.php code:

public function handle($request, Closure $next)
    {
        if($request->session()->has('impersonate'))
        {
            Auth::onceUsingId($request->session()->get('impersonate'));
        }

        return $next($request); //line 24
    }

AppMiddleware.php code:

public function handle($request, Closure $next)
    {
        $domain = $this->getDomain();
        $subdomain = $this->getSubdomain($request->getHost(), $domain);
        $isApp = strpos($request->route()->getPrefix(), 'app') !== false;
        $user = $request->user();

        if (!$user || !$isApp) { // No user, load company based on sub domain.
            $company = $this->getCompany($subdomain);

            if (!$company && !strlen($subdomain) || array_search($subdomain, self::$systemSubDomains) !== false) { $company = Company::find(1); } // No matched company, but empty sub domain
            else if (!$company) { abort(404); } // No related sub domain
        }
        else { // Uses user company sub domain
            $userCompanySubdomain = $user->company->subdomain;

            if (!strlen($subdomain)) { // Force sub domain
                return redirect()->away(str_replace($domain, "{$userCompanySubdomain}.{$domain}", $request->fullUrl()));
            } else if ($subdomain !== $userCompanySubdomain) { // Check if user's sub domain match company's sub domain.
                return redirect()->away(str_replace($subdomain, $userCompanySubdomain, $request->fullUrl()));
            }

            $company = $user->company;

            // Not sure if we need this!
            //$user->updated_at = Carbon::now();
            //$user->save();
        }

        session([
            'subdomain' => $subdomain,
            'company' => $company
        ]);

        return $next($request); //line 107
    }

How can I get the validation code to search in the 'top_locations' table or short of that how can I bypass that validation?

0 likes
2 replies
Sinnbeck's avatar

Sorry haven't gotten to read everything. It's really long. But just making sure you know that this code allows sql injection

$query = "UPDATE public.locations SET location_name = $location_name,";

Use the query builder or eloquent

denewey's avatar

This uses the Query Builder statement, DB::connection('console')->update($query);

DB::connection('console')->update($query);

But to be more accurate I revised it to:

 try {
            $affected = DB::table('public.locations')
                      ->where('location_id', $id)
                      ->update(['location_name' => $location_name, 'location_type_id' => $location_type_id]);
        } catch (\Illuminate\Database\QueryException $e) {
            return redirect()->back()
                ->with('failure', trans('app/settings/locations.view.form.messages.failed'));
        }

Please or to participate in this conversation.