Passing a new variable to Resource from Controller | Laravel - laravel

I have an API resources in my code,
what i wanted to do is to pass a new data to be return in Resource Collection
Controller:
public function index(Request $request)
{
// #TODO implement
$books = Book::with('authors')->paginate(5);
$pass = 1;
return BookResource::collection($books, $pass, 200);
}
my Resources:
public function toArray($request)
{
return [
// #TODO implement
'id' => $this->id,
'isbn' => $this->isbn,
'title' => $this->title,
'description' => $this->description,
'published_year' => $this->published_year,
'authors' => AuthorResource::collection($this->authors),
'review' => BookReviewResource::collection($this->reviews),
'pass' => $this->pass
];
}
I want the $pass, can be returned in Resources,
how do i achieve that?

Try adding metadata to the collection using additional:
return BookResource::collection($books)->additional([
‘pass’ => $pass,
]);

BookResource
class BookResource extends Resource {
protected $pass;
public function pass($value){
$this->pass = $value;
return $this;
}
public function toArray($request){
return [
'id' => $this->id,
'isbn' => $this->isbn,
'title' => $this->title,
'description' => $this->description,
'published_year' => $this->published_year,
'authors' => AuthorResource::collection($this->authors),
'review' => BookReviewResource::collection($this->reviews),
'pass' => $this->pass
];
}
public static function collection($resource){
return new BookResourceCollection($resource);
}
}
BookResourceCollection
class BookResourceCollection extends ResourceCollection {
protected $pass;
public function pass($value){
$this->pass = $value;
return $this;
}
public function toArray($request){
return $this->collection->map(function(BookResource $resource) use($request){
return $resource->pass($this->pass)->toArray($request);
})->all();
}
Pass params
BookResource::collection($books)->pass(1);
Or using this:
http://localhost:3000/api/books?pass=1
public function toArray($request) {
$pass = $request->pass;
return [
'id' => $this->id,
'isbn' => $this->isbn,
'title' => $this->title,
'description' => $this->description,
'published_year' => $this->published_year,
'authors' => AuthorResource::collection($this->authors),
'review' => BookReviewResource::collection($this->reviews),
'pass' => $pass
];
}

Related

updateOrCreate() updating database using index

I have a submit and update function for my form and in that form, the user can choose to add an additional row of inputs. These inputs will be saved in a new row, basically, one user can have several rows in the database. I have a problem with the update function, where if the user originally has two rows answered, in the update function if they still fill in two rows, both of the rows in the database will be updated, however, only the first row is getting updated. I tried accessing the key for the arrays and updating based on the array keys but it doesn't work.
Here is my whole controller:
<?php
namespace App\Http\Livewire;
use Illuminate\Support\Facades\Validator;
use App\Http\Livewire\Field;
use Illuminate\Http\Request;
use App\Helpers\Constant;
use App\Models\User;
use App\Models\Application;
use App\Models\Model1;
use App\Models\Model2;
use App\Models\Model3;
use App\Models\Model4;
use Livewire\Component;
use DB;
class ModelComponent extends Component
{
public $i = 1;
public $updateMode = false;
public $model2Rows = [];
public $model4Rows = [];
public $showDiv1 = false;
public $showDiv2 = false;
public $showDiv3 = false;
public $showDiv4 = false;
public $m1_field;
public $m1_field2;
public $m2_field;
public $m2_field2;
public $m3_field;
public $m3_field2;
public $m4_field;
public $m4_field2;
public function openDiv($divNum)
{
if($divNum == 1) {
$this->showDiv1 =! $this->showDiv1;
} else if($divNum == 2) {
$this->showDiv2 =! $this->showDiv2;
} else if($divNum == 3) {
$this->showDiv3 =! $this->showDiv3;
} else if($divNum == 4) {
$this->showDiv4 =! $this->showDiv4;
}
}
public function addMoreModel2Rows($i)
{
$i = $i + 1;
$this->i = $i;
array_push($this->model2Rows , $i);
}
public function addMoreModel4Rows($i)
{
$i = $i + 1;
$this->i = $i;
array_push($this->model4Rows , $i);
}
public function removeModel2Rows($i)
{
unset($this->model2Rows[$i]);
}
public function removeModel4Rows($i)
{
unset($this->model4Rows[$i]);
}
public function submit()
{
$user = auth()->user();
$application = Application::create([
'app_type_id' => 1,
'approval_status_id' => 1
]);
$application->users()->save($user);
$rules = [];
$validatedData = [];
if($this->showDiv1){
$rules = array_merge($rules, [
'm1_field' => 'required',
'm1_field2' => 'required',
]);
}
if($this->showDiv2){
$rules = array_merge($rules, [
'm2_field.0' => 'required',
'm2_field2.0' => 'required',
'm2_field.*' => 'required',
'm2_field2.*' => 'required',
]);
}
if($this->showDiv3){
$rules = array_merge($rules, [
'm3_field' => 'required',
'm3_field2' => 'required',
]);
}
if($this->showDiv4){
$rules = array_merge($rules, [
'm4_field.0' => 'required',
'm4_field2.0' => 'required',
'm4_field.*' => 'required',
'm4_field2.*' => 'required',
]);
}
$validatedData = $this->validate($rules);
if($this->showDiv1){
Model1::create([
'user_id' => $user->user_id,
'm1_field' => $validatedData['m1_field'],
'm1_field2' => $validatedData['m1_field2'],
]);
}
if($this->showDiv2){
foreach ($this->m2_field as $key => $value){
Model2::create([
'user_id' => $user->user_id,
'm2_field' => $validatedData['m2_field'][$key],
'm2_field2' => sanitize_money($validatedData['m2_field2'][$key]),
]);
}
}
if($this->showDiv3){
Model3::create([
'user_id' => $user->user_id,
'm3_field' => $validatedData['m3_field'],
'm3_field2' => $validatedData['m3_field2'],
]);
}
if($this->showDiv4){
foreach ($this->m4_field as $key => $value){
Model4::create([
'user_id' => $user->user_id,
'm4_field' => $validatedData['m4_field'][$key],
'm4_field2' => sanitize_money($validatedData['m4_field2'][$key]),
]);
}
}
$user->save();
alert('success','Your details are saved.');
return redirect()->route('website.landing');
}
public function update()
{
// get user info in session
$user = auth()->user();
$i = 0;
$model2 = Model2::where('user_id', $user->user_id)->get();
$model4 = Model4::where('user_id', $user->user_id)->get();
$rules = [];
$validatedData = [];
if($this->showDiv1){
$rules = array_merge($rules, [
'm1_field' => 'required',
'm1_field2' => 'required',
]);
}
if($this->showDiv2){
$rules = array_merge($rules, [
'm2_field.0' => 'required',
'm2_field2.0' => 'required',
'm2_field.*' => 'required',
'm2_field2.*' => 'required',
]);
}
if($this->showDiv3){
$rules = array_merge($rules, [
'm3_field' => 'required',
'm3_field2' => 'required',
]);
}
if($this->showDiv4){
$rules = array_merge($rules, [
'm4_field.0' => 'required',
'm4_field2.0' => 'required',
'm4_field.*' => 'required',
'm4_field2.*' => 'required',
]);
}
$validatedData = $this->validate($rules);
if($this->showDiv1){
EmploymentDetail::updateOrCreate(
[
'user_id' => $user->user_id,
],
[
'm1_field' => $validatedData['m1_field'],
'm1_field2' => $validatedData['m1_field2'],
]);
}
if($this->showDiv2){
foreach ($this->m2_field as $key => $value){
$partTime[$key]->updateOrCreate(
[
'user_id' => $user->user_id,
],
[
'm2_field' => $validatedData['m2_field'][$key],
'm2_field2' => sanitize_money($validatedData['m2_field2'][$key]),
]);
}
}
if($this->showDiv3){
Model3::updateOrCreate(
[
'user_id' => $user->user_id,
],
[
'm3_field' => $validatedData['m3_field'],
'm3_field2' => $validatedData['m3_field2'],
]);
}
if($this->showDiv4){
foreach ($this->m4_field as $key => $value){
if(!empty($model4[$i])){
$model4[$i]->updateOrCreate(
[
'user_id' => $user->user_id,
],
[
'm4_field' => $validatedData['m4_field'][$key],
'm4_field2' => sanitize_money($validatedData['m4_field2'][$key]),
]);
} else {
Model4::create([
'user_id' => $user->user_id,
'm4_field' => $validatedData['m4_field'][$key],
'm4_field2' => sanitize_money($validatedData['m4_field2'][$key]),
]);
}
}
}
alert('success','Your income are updated.');
return redirect()->route('borrower.joint_declaration');
}
public function render()
{
$income_informations = DB::table('income_informations')->get();
$showDiv1 = $this->showDiv1;
$showDiv2 = $this->showDiv2;
$showDiv3 = $this->showDiv3;
$showDiv4 = $this->showDiv4;
return view('livewire.model-component',
[
'income_informations' => $income_informations,
'showDiv1'=>$showDiv1,
'showDiv2'=>$showDiv2,
'showDiv3'=>$showDiv3,
'showDiv4'=>$showDiv4,
]);
}
}
I created a variable to store the arrays because I realized that if I simply use the model name and then do updateOrCreate() it will probably only update the first one. But the result of that update function is that it updates the first row in the database, then creates a new row for the additional row, but I want it to update the other rows in the database instead.
For more context, I followed through this tutorial for the adding input fields and saving function. Now I have trouble trying to do the update function.

Laravel Many to one in Resource

I use laravel 8 & have 3 table:
Products, ProductPrice & ProductsPublisher:
this is my Products model for this relationship:
public function lastPrice(){
return $this->hasMany(ProductPrice::class)->where('status','active')->orderBy('created_at','DESC')->distinct('publisher_id');
}
and this is my productsPrice model for publisher relationship:
public function getPublisher(){
return $this->belongsTo(ProductsPublisher::class,'publisher_id');
}
now, i want to use laravel resource for my api, i wrote products resource:
public function toArray($request)
{
return [
'id' => $this->id,
'price' => lastPrice::make($this->lastPrice),
'status' => $this->status,
'slug' => $this->slug,
'title' => $this->title,
'description' => $this->description,
'txt' => $this->txt,
'lang' => $this->lang,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
but in lastPrice resource, when i wrote like this:
return [
'id' => $this->id,
'main_price' => $this->main_price
];
it give me this error:
Property [id] does not exist on this collection instance.
when i use this code:
return parent::toArray($request);
get response but because i need to use another relationship in my lastPirce for publishers, i cant use that code and should return separately my data.
What i should to do?
thanks
Edit 1:
this is my Controller Code:
$products = Product::where('id',$id)->where('slug',$slug)->where('status','confirm')->first();
if(!$products){
return $this->sendError('Post does not exist.');
}else{
return $this->sendResponse(new \App\Http\Resources\Products\Products($products), 'Posts fetched.');
}
and this is sendResponse & sendError:
public function sendResponse($result, $message)
{
$response = [
'success' => true,
'data' => $result,
'message' => $message,
];
return response()->json($response, 200);
}
public function sendError($error, $errorMessages = [], $code = 404)
{
$response = [
'success' => false,
'message' => $error,
];
if(!empty($errorMessages)){
$response['data'] = $errorMessages;
}
return response()->json($response, $code);
}
thanks.
Edit 2:
i change my lastPrice Resource toArray function to this and my problem solved, but i think this isn't a clean way, any better idea?
$old_data = parent::toArray($request);
$co = 0;
$new_data = [];
foreach ($old_data as $index){
$publisher_data = Cache::remember('publisher'.$index['publisher_id'], env('CACHE_TIME_LONG') , function () use ($index) {
return ProductsPublisher::where('id' , $index['publisher_id'])->first();
});
$new_data[$co]['main_prices'] = $index['main_price'];
$new_data[$co]['off_prices'] = $index['off_price'];
$new_data[$co]['publisher'] = SinglePublisher::make($publisher_data);
$new_data[$co]['created_at'] = $index['created_at'];
$co++;
}
return $new_data;

Laravel - local.ERROR: Error: Call to undefined function App\Imports\create() in Excel Import

I am using Laravel-8 and Maatwebsite-3.1 package for excel upload:
I have this Excel sheet (The data is more thank that):
imports:
use Illuminate\Validation\Rule;
use Maatwebsite\Excel\Row;
use Maatwebsite\Excel\Concerns\OnEachRow;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Concerns\WithCustomValueBinder;
use Maatwebsite\Excel\DefaultValueBinder;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\SkipsErrors;
use Maatwebsite\Excel\Concerns\SkipsOnError;
use Maatwebsite\Excel\Concerns\SkipsFailures;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Validators\Failure;
use Throwable;
class EmployeeImport extends DefaultValueBinder implements OnEachRow, WithStartRow, SkipsOnError, WithValidation, SkipsOnFailure, WithEvents, WithCustomValueBinder
{
// set the preferred date format
private $date_format = 'Y-m-d';
// set the columns to be formatted as
private $date_columns = ['E'];
use Importable, SkipsErrors, SkipsFailures;
public function onRow(Row $row)
{
$rowIndex = $row->getIndex();
if($rowIndex >= 1000)
return; // Not more than 1000 rows at a time
$row = $row->toArray();
$employee_data = [
'first_name' => $row[0],
'other_name' => $row[1] ?? '',
'last_name' => $row[2],
'email' => preg_replace('/\s+/', '', strtolower($row[3])),
'dob' => $this->transformDate($row[4]),
];
$employee = create(Employee::class, $employee_data);
if (User::where('email', '=', $employee->email)->exists()) {
$user = User::update([
'first_name' => $employee->first_name,
'last_name' => $employee->last_name,
'active' => 1,
]);
}else{
$user = User::create([
'email' => $employee->email,
'first_name' => $employee->first_name,
'last_name' => $employee->last_name,
'active' => 1,
]);
}
$employee->update([
'user_id' => $user->id,
]);
}
public function startRow(): int
{
return 2;
}
public function customValidationAttributes()
{
return [
'0' => 'First Name',
'1' => 'Other Name',
'2' => 'Last Name',
'3' => 'Email',
'4' => 'Date of Birth',
];
}
public function rules(): array
{
return [
'*.0' => [
'required',
'string',
'max:50'
],
'*.1' => [
'nullable',
'string',
'max:50'
],
'*.2' => [
'required',
'string',
'max:50'
],
'*.3' => [
'required',
'email',
'max:100',
Rule::unique('employees', 'email')->where(function ($query) {
return $query->where('company_id', Auth::user()->company_id);
})
],
'*.4' => [
'required',
'date_format:Y-m-d',
'before:' . Carbon::now()->subYears(18)->format('Y-m-d')
],
];
}
public function chunkSize(): int
{
return 1000;
}
public function transformDate($value, $format = 'Y-m-d')
{
try {
return \Carbon\Carbon::instance(\PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value));
} catch (\ErrorException $e) {
return \Carbon\Carbon::createFromFormat($format, $value);
}
}
}
Controller:
public function importEmployee(Request $request)
{
$validator = Validator::make($request->all(), [
'document' => 'file|mimes:xls,xlsx|max:5000',
]);
if ($request->hasFile('document'))
{
if($validator->passes()) {
$import = new EmployeeImport;
$file = $request->file('document');
$file->move(public_path('storage/employee_imports'), $file->getClientOriginalName());
Excel::import($import, public_path('storage/employee_imports/' . $file->getClientOriginalName() ));
return $this->success('Employees Imported.', [
'file' => $file
]);
}else{
return $this->error($validator->errors(), 422);
}
}
}
When I submitted, I got this error:
[2021-08-19 09:33:40] local.ERROR: Error: Call to undefined function
App\Imports\create() in
C:\xampp\htdocs\myapp\app\Imports\EmployeeImport.php:98
Stack trace:
#0 C:\xampp\htdocs\myapp\vendor\maatwebsite\excel\src\Sheet.php(301):
App\Imports\EmployeeImport->onRow(Array)
#1 C:\xampp\htdocs\myapp\vendor\maatwebsite\excel\src\Reader.php(114): Maatwebsite\Excel\Sheet->import(Object(App\Imports\EmployeeImport), 2)
#2
C:\xampp\htdocs\myapp\vendor\laravel\framework\src\Illuminate\Database\Concerns\ManagesTransactions.php(29): Maatwebsite\Excel\Reader->Maatwebsite\Excel{closure}(Object(Illuminate\Database\MySqlConnection))
This is the line 98:
$employee = create(Employee::class, $employee_data);
How do I resolve this?
Thanks
Change this line
$employee = create(Employee::class, $employee_data);
to
$employee = Employee::create($employee_data);
create is not a function alone. Check this link
https://laravel.com/docs/8.x/eloquent#inserting-and-updating-models

Laravel - Maatwebsite Excel import stored in storage only but not in DB

I am importing Excel File using Laravel-8 endpoints and Maatwebsite-3.1 package.
The way I did it is that, the Uploaded Excel file will first get to the storage (storage/file_imports/student_imports). Then Laravel pickes it up from there, stores it into the DB table through StudentImport using Maatwebsites.
StudentImport:
<?php
namespace App\Imports;
use App\Models\User;
use App\Models\Student;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Password;
use Illuminate\Validation\Rule;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\SkipsErrors;
use Maatwebsite\Excel\Concerns\SkipsOnError;
use Maatwebsite\Excel\Concerns\SkipsFailures;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Validators\Failure;
use Throwable;
class StudentImport implements
ToModel,
WithValidation,
WithHeadingRow,
SkipsOnError,
SkipsOnFailure,
WithBatchInserts
{
protected $companyId;
public function __construct()
{
$this->companyId = Auth::user()->company_id;
}
use Importable, SkipsErrors, SkipsFailures;
public function model(array $row)
{
$student_data = [
'first_name' => $row[0],
'other_name' => $row[1] ?? '',
'last_name' => $row[2],
'email' => preg_replace('/\s+/', '', strtolower($row[3])),
'gender' => $row[4],
'nationality_id' => $this->getNationality() ?? '',
'school_id' => Auth::user()->school_id,
];
$student = Student::create($student_data);
if (User::where('email', '=', $student->email)->exists()) {
$user = User::update([
'first_name' => $student->first_name,
'other_name' => $student->other_name,
'last_name' => $student->last_name,
'complete_profile' => 1,
'active' => 1,
'user_type' => 'Driver',
'company_id' => Auth::user()->company_id,
'updated_at' => date("Y-m-d H:i:s"),
'updated_by' => Auth::user()->id,
]);
}else{
$user = User::create([
'email' => $student->email,
'username' => strtok($row[3], '#'),
'password' => bcrypt("123456"),
'first_name' => $student->first_name,
'other_name' => $student->other_name,
'last_name' => $student->last_name,
'activation_token' => str_random(10),
]);
}
}
public function headingRow(): int
{
return 1;
}
public function getRowCount(): int
{
return $this->rows;
}
public function customValidationAttributes()
{
return [
'0' => 'First Name',
'1' => 'Other Name',
'2' => 'Last Name',
'3' => 'Email',
'4' => 'Gender',
];
}
public function rules(): array
{
return [
'*.0' => [
'required',
'string',
'max:50'
],
'*.1' => [
'nullable',
'string',
'max:50'
],
'*.2' => [
'required',
'string',
'max:50'
],
'*.3' => [
'required',
'email',
'max:100',
Rule::unique('studentss')->where(function ($query) {
return $query->where('school_id', Auth::user()->school_id);
})
],
'*.4' => [
'required',
'string',
'max:20'
],
];
}
public function batchSize(): int
{
return 1000;
}
public function chunkSize(): int
{
return 1000;
}
public function onFailure(Failure ...$failures)
{
// Handle the failures how you'd like.
}
public function customValidationMessages()
{
return [
'1.in' => 'Custom message for :attribute.',
'nim.unique' => 'Custom message',
];
}
}
Controller:
public function importStudent(Request $request)
{
try {
$user = Auth::user()->id;
$validator = Validator::make($request->all(), [
'document' => 'file|mimes:xlsx|max:10000',
]);
if($validator->fails()) {
return $this->error($validator->errors(), 401);
} else {
$check = User::where('id', $user)->pluck('id');
if($check[0] !== null || $check[0] !== undefined) {
$file = $request->file('document');
$file->move(public_path('storage/file_imports/student_imports'), $file->getClientOriginalName());
Excel::import(new StudentImport, public_path('storage/file_imports/student_imports/' . $file->getClientOriginalName() ));
return $this->success('Students Successfully Imported.', [
'file' => $file
]);
} else {
return $this->error('Not allowed', 401);
}
}
} catch(\Exception $e) {
return $this->error($e->getMessage());
}
}
As I stated earlier it will first store the Excel file into:
storage/file_imports/student_imports
Then pick it from there and store in the DB.
This code is in the controller above.
The file is store in the
public/storage/file_imports/student_imports
as expected, but nothing is found in the DB. Yes it displays Success with no error.
What could be the problem and how do I resolve it?
Thanks
model method in your StudentImport class must return new instance of Eloquent model.
You shouldn't make create or update method call through your model in here.
Maatwebsite-Excel manage your insert process with own manager. Check source code.
https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/src/Imports/ModelImporter.php#L74
https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/src/Imports/ModelImporter.php#L92
https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/src/Imports/ModelManager.php#L45
https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/src/Imports/ModelManager.php#L64

How to use the 'privacy' attribute function in Laravel Rebing GraphQL?

i'm working on a graphql API using Laravel GraphQL.
As shown in the documentation "Privacy" section, it should be possible to add callback function to a GraphQLType fields privacy attribute. The field is supposed to return null, when the callback returns false.
Similar to the example in the laravel graphql Docs, i've added a privacy callback like so:
public function fields(): array {
return [
'email' => [
'type' => Type::string(),
'description' => 'The email of user',
'privacy' => function(User $user): bool {
return $user->isMe();
}
],
];
}
It appears to me, that this callback function never gets called.
I read something about a possible requirement, that i should resolve my query using the $getSelectFields function to query the $fields manually $with the selected columns. But unfortunately the $select
public function resolve($root, $args, $context, ResolveInfo $info, Closure $getSelectFields) {
$fields = $getSelectFields();
$with = $fields->getRelations(); // empty array
$select = $fields->getSelect(); // empty array
return User::select($select)->with($with)->get();
}
In my case this does not make any difference.
In my query resolver i do as following:
public function resolve($root, $args, $context, ResolveInfo $info, Closure $getSelectFields) {
/** #var SelectFields $fields */
$fields = $getSelectFields();
$select = $fields->getSelect();
$with = $fields->getRelations();
exit(var_dump($fields)); // #RESULT
}
My result looks like this:
object(Rebing\\GraphQL\\Support\\SelectFields)#4668 (2) {
[\"select\":\"Rebing\\GraphQL\\Support\\SelectFields\":private]=> array(0) {}
[\"relations\":\"Rebing\\GraphQL\\Support\\SelectFields\":private]=> array(0) {}
}
So my question is: "How do i use the privacy attribute callback in Laravel Rebing GraphQL?"
I'm using:
PHP 7.3
Laravel 7.17
Rebing Graphql Laravel 5.1
Thanks in advance,
greets Jules
Some more Details about my use case
EpUser.php
namespace App\GraphQL\Type;
use App\CommunityImage;
use App\User;
use Carbon\Carbon;
use GraphQL\Type\Definition\Type;
use Illuminate\Support\Facades\Auth;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Type as GraphQLType;
class EpUser extends GraphQLType {
protected $attributes = [
'name' => 'EpUser',
'description' => 'A type',
'model' => User::class,
];
public function fields(): array {
return [
'id' => [
'type' => Type::nonNull(Type::int()),
'description' => 'The id of the user',
'privacy' => function(User $user): bool {
return false;
}
],
'email' => [
'type' => Type::string(),
'description' => 'The email of user',
'privacy' => function(User $user): bool {
return $user->isMe();
}
],
'firstName' => [
'type' => Type::string(),
'description' => 'The firstName of user'
],
'lastName' => [
'type' => Type::string(),
'description' => 'The lastName of user'
],
'fullName' => [
'type' => Type::string(),
'description' => 'The fullName of user',
'selectable' => false,
'resolve' => function(User $user) {
return $user->firstName . " " . $user->lastName;
}
],
'gender' => [
'type' => Type::string(),
'description' => 'The gender of the user'
],
'isOnline' => [
'type' => Type::boolean(),
'description' => '',
'selectable' => false,
'resolve' => function(User $user, $args) {
return $user->isOnline();
}
]
];
}
[...]
And this is the UsersQuery which should respond with a user pagination object, that contains an array of users with a privacy attribute:
UsersQuery.php
namespace App\GraphQL\Query;
use App\Artist;
use App\FilePath;
use Closure;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Query;
use Illuminate\Support\Facades\Auth;
use GraphQL\Type\Definition\ResolveInfo;
use Rebing\GraphQL\Support\Facades\GraphQL;
use App\User;
class UsersQuery extends Query {
protected $attributes = [
'name' => 'UsersQuery',
'description' => 'A query',
'model' => User::class,
];
public function type(): Type {
return GraphQL::type('userPagination');
}
public function authorize($root, array $args, $ctx, ResolveInfo $resolveInfo = NULL, $getSelectFields = NULL): bool {
return Auth::check();
}
public function args(): array {
return [
'id' => [
'type' => Type::int(),
'description' => 'The id of the user'
],
'slug' => [
'type' => Type::string(),
'description' => 'The slug of the user'
],
'pagination' => [
'type' => Type::nonNull(GraphQL::type('paginationInput')),
'description' => 'The pagination of the users to query',
'rules' => 'required',
],
'search' => [
'type' => Type::string(),
'description' => 'a string to search for users'
],
'roles' => [
'type' => Type::listOf(Type::string()),
'description' => 'The roles of the user',
'rules' => 'sometimes|required|array|in:user,developer,administrator'
]
];
}
public function resolve($root, $args, $context, ResolveInfo $info, Closure $getSelectFields) {
if(isset($args['id']) || isset($args['slug'])) {
if(isset($args['slug'])) {
$user = User::where('slug', $args['slug'])->first();
} else {
$user = User::find($args['id']);
}
return [
'items' => $args['pagination']['limit'] > 0 && $user ? [$user] : NULL,
'itemTotal' => $user ? 1 : 0
];
}
$sortBy = $args['pagination']['sortBy'] ?? 'id';
$sortByDesc = isset($args['pagination']['sortByDesc']) ? $args['pagination']['sortByDesc'] : true;
$sortByType = $sortByDesc ? 'desc' : 'asc';
$search = false;
if(isset($args['search']) && $args['search']) {
$search = true;
$query = User::search($args['search']);
} else {
$query = User::query();
}
if(!empty($sortBy)) {
$query->orderBy($sortBy, $sortByType);
}
// Todo: eloquent search can't serach for whereHas
if(isset($args['roles']) && !$search) {
if(is_array($args['roles'])) {
foreach($args['roles'] as &$role) {
$query->whereHas('roles',
function($q) use ($role) {
$q->where('name', $role);
});
}
} else {
$query->whereHas('roles',
function($q) use ($args) {
$q->where('name', $args['roles']);
});
}
}
if($search) {
$userPaginationObject = [
'itemTotal' => $query->count(),
'items' => $query->getWithLimitAndOffset($args['pagination']['limit'],
$args['pagination']['offset'])
];
} else {
$userPaginationObject = [
'itemTotal' => $query->count(),
'items' => $query->limit($args['pagination']['limit'])->offset($args['pagination']['offset'])->get()
];
}
return $userPaginationObject;
}
}

Resources