Laravel eloquent 无法正确获取数据
在我的 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 id
s 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你在这里做错了:
关系的工作方式是 laravel 循环该查询的结果并将
users.id
与user_documents.added_by
彼此匹配,如果匹配则附上它。由于您仅选择了
first_name
和last_name
列,因此它的id
始终为null
并且不匹配任何用户文档
。解决方案:
获取全名的更方便方法:
编辑:
由于前端要求
added_user_name
应该位于对象的第一级,因此您应该映射结果并移动added_user_name
到第一级,或加入users
表并从中获取结果:但如果您使用分页,则不建议使用
map
解决方案。我将仅使用 join 编写使用
join
:从查询中删除
->with
函数并将其替换为join
。You are doing it wrong here:
The way relationship is working is that laravel loops trough result of that query and matches
users.id
touser_documents.added_by
each other and if matches then attaches it.Since you have selected only
first_name
andlast_name
columns,id
of it always isnull
and not matches anyuser_documents
.Solution:
More convenient way to get full 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 moveadded_user_name
to first level, or joinusers
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 joinUsing
join
:Remove
->with
function from query and replace it withjoin
.