Laravel eloquent 无法正确获取数据

发布于 2025-01-20 20:01:49 字数 8156 浏览 0 评论 0原文

在我的 laravel vue 应用程序中,我有两个表,user 表和 user_document 表。

在我的 user_document 表中,有一个名为 added_by 的列。

此列存储用户的id

我的应用程序中有两种角色:管理员和普通用户。

我的用户可以通过vue组件将文档上传到系统。管理员也可以为其他用户上传文档。

用户可以在数据表中查看已上传的文档详细信息。

在该数据表中,我显示一个名为添加者的列,其中显示上传文档的用户(用户自己或由管理员)。

我有以下控制器来获取和显示这些记录。

<?php

namespace App\Http\Controllers\Dashboard\Corporate\Employee;

use App\Company;
use App\Models\OtherDocument;
use App\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class CompanyEmployeeOtherDocumentsController extends Controller
{
    /**
     * @param string $locale
     * @return \Illuminate\Http\JsonResponse
     */
    public function index(string $locale, Company $company, User $user)
    {

        $otherDocuments = OtherDocument::where('user_id', $user->id)
            ->with('added_by_user')
            ->when(request('validity_status'), function ($query) {
                $query->where(function ($query) {
                    $query->when( in_array('active', request('validity_status')), function ($query) {
                        $query->where(function (Builder $query) {
                            $query->whereDate('issued_at', '<=', Carbon::now())
                                ->whereDate('expires_at', '>=', Carbon::now()->addMonth());
                        })->orWhere('is_valid_forever',1);
                    })->when( in_array('expires', request('validity_status')), function ($query) {
                        $query->orWhere(function (Builder $query) {
                            $query->whereDate('expires_at', '<=', Carbon::now()->addMonth())
                                ->whereDate('expires_at', '>=', Carbon::now());
                        });
                    })->when( in_array('expired', request('validity_status')), function ($query) {
                        $query->orWhereDate('expires_at', '<', Carbon::now());
                    });
                });
            })
            ->when(request('search_text'), function ($query) {
                $query->where('name', 'like', '%' . request('search_text') . '%');
            })
            ->paginate(request('per_page',config('statguru.pagination.limit')));

        for ($i=0; $i < count($otherDocuments); $i++) {
            $addedByUser = $otherDocuments[$i]->added_by_user;
            if ($addedByUser) {
                $otherDocuments[$i]['added_user_name'] = $addedByUser->first_name . ' ' . $addedByUser->last_name;
            }
        }

        return  response()->json($otherDocuments);

    }
}

在我的 vue 组件中,我有以下标头数组,

HeaderArray() {
            return [
                {text: 'Certificate', value: 'certificate'},
                {text: 'Added by', value: 'added_by_user_name'},
                {text: 'Institute', value: 'institute'},
                {text: 'Expiration', value: 'valid_date', classList: 'text-center'},
                {text: 'Validity', value: 'validity_status', classList: 'text-center'},
                {text: 'Verification', value: 'verification_status', classList: 'text-center'},
            ];
        },

整个解决方案完美运行。

但是现在我不再使用这个 for 循环,而是

for ($i=0; $i < count($otherDocuments); $i++) {
                $addedByUser = $otherDocuments[$i]->added_by_user;
                if ($addedByUser) {
                    $otherDocuments[$i]['added_user_name'] = $addedByUser->first_name . ' ' . $addedByUser->last_name;
                }
            }

尝试通过 eloquent 获得相同的结果

->with(['added_by_user' => function($q){
                $q->select('first_name', 'last_name');
             }]) 

当我将 for 循环替换为这个,它没有向我显示“由用户的名字添加”...我需要在雄辩中更改以正确获取该数据吗?

我正在使用 laravel 9

更新

我已经根据下面的 Malkhazi Dartsmelidze 答案更新了我的代码。

但我无法在数据表上显示名称。

以下是我更新的控制器,

<?php

namespace App\Http\Controllers\Dashboard\Corporate\Employee;

use App\Company;
use App\Models\OtherDocument;
use App\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class CompanyEmployeeOtherDocumentsController extends Controller
{
    /**
     * @param string $locale
     * @return \Illuminate\Http\JsonResponse
     */
    public function index(string $locale, Company $company, User $user)
    {

        $otherDocuments = OtherDocument::where('user_id', $user->id)
        ->with(['added_by_user' => function($q){
            $q->select('id', DB::raw('CONCAT(first_name, " ", last_name) as added_user_name'));
        }]) 
            ->when(request('validity_status'), function ($query) {
                $query->where(function ($query) {
                    $query->when( in_array('active', request('validity_status')), function ($query) {
                        $query->where(function (Builder $query) {
                            $query->whereDate('issued_at', '<=', Carbon::now())
                                ->whereDate('expires_at', '>=', Carbon::now()->addMonth());
                        })->orWhere('is_valid_forever',1);
                    })->when( in_array('expires', request('validity_status')), function ($query) {
                        $query->orWhere(function (Builder $query) {
                            $query->whereDate('expires_at', '<=', Carbon::now()->addMonth())
                                ->whereDate('expires_at', '>=', Carbon::now());
                        });
                    })->when( in_array('expired', request('validity_status')), function ($query) {
                        $query->orWhereDate('expires_at', '<', Carbon::now());
                    });
                });
            })
            ->when(request('search_text'), function ($query) {
                $query->where('name', 'like', '%' . request('search_text') . '%');
            })

            ->paginate(request('per_page',config('statguru.pagination.limit')));

        return  response()->json($otherDocuments);

    }
}

以下是 vue 标头数组,

 HeaderArray() {
            return [
                {text: 'Certificate', value: 'certificate'},
                {text: 'Added by', value: 'added_user_name'},
                {text: 'Institute', value: 'institute'},
                {text: 'Expiration', value: 'valid_date', classList: 'text-center'},
                {text: 'Validity', value: 'validity_status', classList: 'text-center'},
                {text: 'Verification', value: 'verification_status', classList: 'text-center'},
            ];
        },

以下是我收到的数据

{
      "id": 6,
      "user_id": 941,
      "added_by": 869,
      "name": "driving licence",
      "issued_at": "2022-04-06T22:00:00.000000Z",
      "expires_at": "2022-04-29T22:00:00.000000Z",
      "is_valid_forever": 0,
      "document_url": null,
      "document_number": null,
      "file_name": "6-driving-licence.pdf",
      "url": "users/941/other-documents/6-driving-licence.pdf",
      "status": "EXPIRES",
      "created_at": "2022-04-07T03:39:47.000000Z",
      "updated_at": "2022-04-07T03:39:47.000000Z",
      "deleted_at": null,
      "expires_at_formatted": "30-04-2022",
      "validity_status": "EXPIRES",
      "remaining_days": 18,
      "added_by_user": {
        "id": 869,
        "added_user_name": "Satya Nadella",
        "country_code": null,
        "formatted_date_of_birth": "2022-04-11",
        "name": " ",
        "company_role": "admin",
        "profile_image": [
          {
            "url": "/img/statguru-user.png"
          }
        ],
        "inviter_user": "",
        "country": null,
        "media": [
          
        ]
      }
    },

In my laravel vue application I have two tables, user table and user_document table.

In my user_document table, I have a column called, added_by.

This column stores the ids of the users.

There are two roles in my app, admins and general users.

My users can upload documents to the system via vue component. Admin can upload documents for other users as well.

And users can view their already uploaded document details in a datatable.

In that datatable, I'm displaying a column called, Added By, which shows the users who uploaded the document(the user him self or by the admin).

I have following controller to fetch and display those records.

<?php

namespace App\Http\Controllers\Dashboard\Corporate\Employee;

use App\Company;
use App\Models\OtherDocument;
use App\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class CompanyEmployeeOtherDocumentsController extends Controller
{
    /**
     * @param string $locale
     * @return \Illuminate\Http\JsonResponse
     */
    public function index(string $locale, Company $company, User $user)
    {

        $otherDocuments = OtherDocument::where('user_id', $user->id)
            ->with('added_by_user')
            ->when(request('validity_status'), function ($query) {
                $query->where(function ($query) {
                    $query->when( in_array('active', request('validity_status')), function ($query) {
                        $query->where(function (Builder $query) {
                            $query->whereDate('issued_at', '<=', Carbon::now())
                                ->whereDate('expires_at', '>=', Carbon::now()->addMonth());
                        })->orWhere('is_valid_forever',1);
                    })->when( in_array('expires', request('validity_status')), function ($query) {
                        $query->orWhere(function (Builder $query) {
                            $query->whereDate('expires_at', '<=', Carbon::now()->addMonth())
                                ->whereDate('expires_at', '>=', Carbon::now());
                        });
                    })->when( in_array('expired', request('validity_status')), function ($query) {
                        $query->orWhereDate('expires_at', '<', Carbon::now());
                    });
                });
            })
            ->when(request('search_text'), function ($query) {
                $query->where('name', 'like', '%' . request('search_text') . '%');
            })
            ->paginate(request('per_page',config('statguru.pagination.limit')));

        for ($i=0; $i < count($otherDocuments); $i++) {
            $addedByUser = $otherDocuments[$i]->added_by_user;
            if ($addedByUser) {
                $otherDocuments[$i]['added_user_name'] = $addedByUser->first_name . ' ' . $addedByUser->last_name;
            }
        }

        return  response()->json($otherDocuments);

    }
}

And in my vue component I have following header array,

HeaderArray() {
            return [
                {text: 'Certificate', value: 'certificate'},
                {text: 'Added by', value: 'added_by_user_name'},
                {text: 'Institute', value: 'institute'},
                {text: 'Expiration', value: 'valid_date', classList: 'text-center'},
                {text: 'Validity', value: 'validity_status', classList: 'text-center'},
                {text: 'Verification', value: 'verification_status', classList: 'text-center'},
            ];
        },

This whole solution works perfectly.

But now instead of using this for loop

for ($i=0; $i < count($otherDocuments); $i++) {
                $addedByUser = $otherDocuments[$i]->added_by_user;
                if ($addedByUser) {
                    $otherDocuments[$i]['added_user_name'] = $addedByUser->first_name . ' ' . $addedByUser->last_name;
                }
            }

I'm trying to get the same result via eloquent

->with(['added_by_user' => function($q){
                $q->select('first_name', 'last_name');
             }]) 

When I replace the for loop with this, it does not show me the Added by user's first name.... Where do I need to change in the eloquent to fetch that data correctly?

I'm using laravel 9

Update

I have updated my code according to the Malkhazi Dartsmelidze answer below.

Yet I am not being able to display the name on the datatable.

Following is my updated controller,

<?php

namespace App\Http\Controllers\Dashboard\Corporate\Employee;

use App\Company;
use App\Models\OtherDocument;
use App\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class CompanyEmployeeOtherDocumentsController extends Controller
{
    /**
     * @param string $locale
     * @return \Illuminate\Http\JsonResponse
     */
    public function index(string $locale, Company $company, User $user)
    {

        $otherDocuments = OtherDocument::where('user_id', $user->id)
        ->with(['added_by_user' => function($q){
            $q->select('id', DB::raw('CONCAT(first_name, " ", last_name) as added_user_name'));
        }]) 
            ->when(request('validity_status'), function ($query) {
                $query->where(function ($query) {
                    $query->when( in_array('active', request('validity_status')), function ($query) {
                        $query->where(function (Builder $query) {
                            $query->whereDate('issued_at', '<=', Carbon::now())
                                ->whereDate('expires_at', '>=', Carbon::now()->addMonth());
                        })->orWhere('is_valid_forever',1);
                    })->when( in_array('expires', request('validity_status')), function ($query) {
                        $query->orWhere(function (Builder $query) {
                            $query->whereDate('expires_at', '<=', Carbon::now()->addMonth())
                                ->whereDate('expires_at', '>=', Carbon::now());
                        });
                    })->when( in_array('expired', request('validity_status')), function ($query) {
                        $query->orWhereDate('expires_at', '<', Carbon::now());
                    });
                });
            })
            ->when(request('search_text'), function ($query) {
                $query->where('name', 'like', '%' . request('search_text') . '%');
            })

            ->paginate(request('per_page',config('statguru.pagination.limit')));

        return  response()->json($otherDocuments);

    }
}

and following is the vue header array,

 HeaderArray() {
            return [
                {text: 'Certificate', value: 'certificate'},
                {text: 'Added by', value: 'added_user_name'},
                {text: 'Institute', value: 'institute'},
                {text: 'Expiration', value: 'valid_date', classList: 'text-center'},
                {text: 'Validity', value: 'validity_status', classList: 'text-center'},
                {text: 'Verification', value: 'verification_status', classList: 'text-center'},
            ];
        },

And following is the data I recieve

{
      "id": 6,
      "user_id": 941,
      "added_by": 869,
      "name": "driving licence",
      "issued_at": "2022-04-06T22:00:00.000000Z",
      "expires_at": "2022-04-29T22:00:00.000000Z",
      "is_valid_forever": 0,
      "document_url": null,
      "document_number": null,
      "file_name": "6-driving-licence.pdf",
      "url": "users/941/other-documents/6-driving-licence.pdf",
      "status": "EXPIRES",
      "created_at": "2022-04-07T03:39:47.000000Z",
      "updated_at": "2022-04-07T03:39:47.000000Z",
      "deleted_at": null,
      "expires_at_formatted": "30-04-2022",
      "validity_status": "EXPIRES",
      "remaining_days": 18,
      "added_by_user": {
        "id": 869,
        "added_user_name": "Satya Nadella",
        "country_code": null,
        "formatted_date_of_birth": "2022-04-11",
        "name": " ",
        "company_role": "admin",
        "profile_image": [
          {
            "url": "/img/statguru-user.png"
          }
        ],
        "inviter_user": "",
        "country": null,
        "media": [
          
        ]
      }
    },

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

じ违心 2025-01-27 20:01:49

你在这里做错了:

->with(['added_by_user' => function($q){
    $q->select('first_name', 'last_name');
}]) 

关系的工作方式是 laravel 循环该查询的结果并将 users.iduser_documents.added_by 彼此匹配,如果匹配则附上它。

由于您仅选择了 first_namelast_name 列,因此它的 id 始终为 null 并且不匹配任何 用户文档

解决方案:

->with(['added_by_user' => function($q){
    $q->select('id', 'first_name', 'last_name');
}]) 

获取全名的更方便方法:

use Illuminate\Support\Facades\DB;
...
->with(['added_by_user' => function($q){
    $q->select('id', DB::raw('CONCAT(first_name, " ", last_name) as added_user_name'));
}]) 

编辑:

由于前端要求 added_user_name 应该位于对象的第一级,因此您应该映射结果并移动 added_user_name到第一级,或加入 users 表并从中获取结果:
但如果您使用分页,则不建议使用 map 解决方案。我将仅使用 join 编写

使用 join

从查询中删除 ->with 函数并将其替换为 join

OtherDocument::where('user_id', $user->id)
    ->join('users', 'users.id', '=', 'user_document.added_by') // do not know exact names of columns
    ->select(DB::raw('user_document.*'), DB::raw('CONCAT(first_name, " ", last_name) as added_user_name'))
    ->...

You are doing it wrong here:

->with(['added_by_user' => function($q){
    $q->select('first_name', 'last_name');
}]) 

The way relationship is working is that laravel loops trough result of that query and matches users.id to user_documents.added_by each other and if matches then attaches it.

Since you have selected only first_name and last_name columns, id of it always is null and not matches any user_documents.

Solution:

->with(['added_by_user' => function($q){
    $q->select('id', 'first_name', 'last_name');
}]) 

More convenient way to get full name:

use Illuminate\Support\Facades\DB;
...
->with(['added_by_user' => function($q){
    $q->select('id', DB::raw('CONCAT(first_name, " ", last_name) as added_user_name'));
}]) 

Edit:

Since front end requres that added_user_name should be in the first level of object, you should either map through results and move added_user_name to first level, or join users table and get result from it:
But if you are using pagination it's not recommended to use map solution. I'll write only using join

Using join:

Remove ->with function from query and replace it with join.

OtherDocument::where('user_id', $user->id)
    ->join('users', 'users.id', '=', 'user_document.added_by') // do not know exact names of columns
    ->select(DB::raw('user_document.*'), DB::raw('CONCAT(first_name, " ", last_name) as added_user_name'))
    ->...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文