Form model binding for polymorphic relationship - laravel

I have set up a polymorphic relation where the table structure is like:
companies
id - integer
name - string
company_branches
id - integer
name - string
incharges
id - integer
name - string
inchargable_id - integer
inchargable_type - string
I have also set up the models accordingly and the data is saved correctly. The problem that I'm having is showing the data of the incharges table during editing by using model binding. The view for editing is like:
{!! Form::model($company, array("route" => array("companies.update", $company->id), "method"=>"PUT", "files"=>true)) !!}
<label>Company Name</label>
<div>
{!! Form::text('name') !!}
</div>
<label>Incharge Name</label>
<div>
{!! Form::text('incharge_name') !!}
</div>
{!! Form::close() !!}
The data that appears in the name text field while editing is correct. But how do I display the incharge name for editing? I can acess the incharge name by doing $company->incharge->name.
EDIT: In the PersonInCharge model, I have set up the polymorphic relation as:
public function inchargable()
{
return $this->morphTo();
}
In Company model:
public function incharge()
{
return $this->morphOne('PersonInCharge', 'inchargable');
}
In CompanyBranch model:
public function incharge()
{
return $this->morphOne('PersonInCharge', 'inchargable');
}

Try, {!! Form::text('incharge[name]') !!}
Further more you need to (lazy)-eager-load your relation for the form model binding. You can use the Model::with('realtion') or set the $with = ['relation'] property in your Eloquent model. More information about Laravel (Lazy-)Eager-Loading.

Try:
{!! Form::text('incharge_name', $company->incharge->name) !!}
Add in a join to your controller in this fashion:
$company = Company::where('id',$companyID)
->leftJoin('incharges', 'inchargable_id.company_id', '=', 'company.id')
->first();
(need to use the correct fields though!)

Related

Relationship between two tables - Laravel, Inertia, Vuejs

I'm new to the subject, I have two tables related to each other, one for departments and one for users, I want to know how many users there are in each department
DepartmentController.php
public function index()
{
return Inertia::render('back/app/departments/index', [
'filters' => request()->all('visibility', 'status', 'search'),
'departments' => Department::orderBy('name')->get(),
'total_members' => User::where('department_id')->count(),
dd(User::where('department_id')->count()),
]);
}
Index.vue
<td class="flex items-center text-sm leading-5 text-gray-500 px-6 py-4 whitespace-no-wrap">
<span class="font-medium">{{ department.total_members }}</span> {{ $trans('labels.members') }}
</td>
<td class="px-6 py-4 whitespace-no-wrap text-right text-sm leading-5 font-medium">
<inertia-link :href="route('app:projectdepartment.index', {id: department.id})">
{{ $trans('labels.view-activity') }}
</inertia-link>
</td>
If you have the users relationship set up on your Department model, you could use the withCount() method:
Department::withCount('users')->orderBy('name')->get()
This will give you a users_count property on each department.
Assuming you have the relationships defined on each model as noted, you could also define an accessor or as was already stated get the number of related models by way of withCount or also with loadCount after retrieving an individual Department model.
Models/User.php
public function department()
{
return $this->belongsTo(Department::class, 'department_id');
}
public function getActiveUserCountAttribute($value)
{
// Perform additional logic on the users relationship
return $this->users()->where('active',1)->count();
}
Models/Department.php
public function users()
{
return $this->hasMany(User::class);
}
Remember that one of the benefits of withCount is that it doesn't load the related models, avoiding an n+1 problem. If you use withCount, you wouldn't need the accessor defined on the Department model but would need the User relationship defined on Department.
Note that you could also use the loadCount method after you have already retrieved the Department model, e.g. for an individual show page as opposed to a collection.
// From your show method in your controller
$department = Department::where('name',$request['name'])->first();
$department->loadCount('users');
To eager load the 'active_user_count' attribute on each Department model, you would use the $with property. With this defined, you would not need to use the withCount or similar in your controller method.
// Department.php
// A relationship that should always be loaded with every Department request.
protected $with = ['active_user_count']
Laravel docs:
https://laravel.com/docs/8.x/eloquent-relationships#counting-related-models

How to query data from laravel relationship using vue.js? [ laravel, vue ]

I want to query my data in relationship using vue.js and still, I cant make it work.
Also, I got an errors like below.
[Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"
When I changed my code like this
<span v-for="user in users">
{{ user.address.city }}
</span>
And in my Controller
public function index(Request $request)
{
$query = Customers::with('address')
->with('purchases')
->paginate(10);
return CustomersResource::collection($query);
}
<div v-for="user in users">
<span v-if="user.address && user.address.name">{{ user.address.name }}</span>
</div>
Always check if your object exists before accessing it.
Add withDefault after your relationship.
public function address(){
return $this->belongsTo('App\Address','user_id','id')->withDefault([
'name' => '-'
]);
}
There is existing code that depends on the result of any Eloquent relationship to either be null, a Model instance, or a Collection of Model instances. However, the current functionality of the withDefault() method opens up the potential for returning an object that is not one of those three expected values.

Showing category title

I've created a page where you can select a parent category for an item. My database has a column called productparentcat_id that has the category's ID.
Then problem I'm having is even though the correct ID is saved, when I try to get it to show when I try to edit the page it doesn't show. I get this error
"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'productscat.id' in 'field list' (SQL: select productscat.id from products where products.productparentcat_id = 347 and products.productparentcat_id is not null
I know that the sql statement is wrong and that my code if wrong, but I can't see where I've went wrong. I'm hoping someone with fresh eyes can spot it.
My edit function in my ProductsController
public function edit($id)
{
$products = Product::find($id);
$category_options = ProductsCat::pluck('title', 'id');
$selected_parent = $products->productParentCat()
->pluck('id')
->toArray();
if(is_null($products)){
return redirect()->route('products.edit');
}
return view('products::admin.edit', compact('selected_parent', 'products', 'category_options'));
}
My edit.blade.php
<div class="form_input">
<div>
{!! Form::label('productparentcat_id', 'Parent Category') !!}
</div>
<div>
{!! Form::select('productparentcat_id', $category_options, $selected_options, array("class" => "form-control")) !!}
</div>
</div>
My Product model
public function productParentCat()
{
return $this->hasMany('App\Modules\Products\Models\Product', 'productparentcat_id');
}
If there is anything else I need to give please let me know.
public function productParentCat()
{
return $this->hasMany('App\Modules\Products\Models\Product', 'productparentcat_id');
}
this should be related to the category model not the product model
replace App\Modules\Products\Models\Product with your category model

Laravel 5.3 Best practices - load lists from other models to populate dropdowns

i'm new to Laravel and i'm using InfyOm laravel generator to create an app.
I came to an issue and would like to know what is the best practice to do this:
I have a model "Mission". When creating a mission, it need to have a client id and agent id associated with it.
In my view, i want to display 2 dropdown lists, one containing all the active clients (id + name) and the other containing all the active agents (id + name).
my controller
public function create()
{
return view('missions.create');
}
my view blade
{!! Form::select('client_id', ?????? , null, ['class' => 'form-control']) !!}
Thanks for your suggestions
Most convenient way is to use pluck() method to build a list from a collection, for example:
public function create()
{
return view('missions.create', [
'users' => User::pluck('name', 'id')
]);
}
Then use $list variable:
{!! Form::select('client_id', $users , null, ['class' => 'form-control']) !!}

convert DB:table query to eloquent

I have a method in my controller where I return an array of books from a database like so:
$books= DB::table('books')->where('category_id', $category_id)->orderBy('title', 'asc')->paginate(20);
Now I want to be able to use an eloquent relationship with the resulting array of books like this in my view:
#foreach($books as $book)
<p>Title: {!! $book->title !!}
<p>Category: {!! $book->category() !!}
#endforeach
From my understanding this will not work because the $books array is not in Eloquent. How can I make it so it does this?
I assume you already have Book and category model and both have relationship to each other
Try this:
$books= Book::with('category')->orderBy('title', 'asc')->paginate(20);

Resources