Loading a belongs to relationship inside of a laravel resource collection - laravel

I'm having some issues loading my relationships into a ResourceCollection to be consumed by an API, I want to load blogs that each belong to a category.
The blog model which uses a belongsTo relationship
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
class BlogPost extends Model {
use HasFactory, SoftDeletes;
protected $fillable = [
'title',
'content',
'seo_title',
'seo_content',
];
public function categories(): BelongsTo {
return $this->belongsTo(BlogCategory::class);
}
}
The Category model has a hasMany to blogs
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class BlogCategory extends Model {
use HasFactory;
protected $fillable = [
'slug'
];
public function blogs(): HasMany {
return $this->hasMany(BlogPost::class);
}
}
Inside of the blog_post migration, I added a foreign key to blog_categories
$table->foreignId('category_id')->constrained('blog_categories');
Then, in my BlogPost ResourceCollection I tried loading the relationship,
#[ArrayShape(['data' => "\Illuminate\Support\Collection", 'category' => AnonymousResourceCollection::class])] public function toArray($request): array {
return [
'data' => $this->collection,
'category' => BlogCategoryCollection::make($this->whenLoaded($this->categories))
];
}
I call the collection inside of the index function of my controller
public function index(): BlogPostCollection
{
return new BlogPostCollection(BlogPost::all());
}
And when I hit the api/blogs endpoint I get the error :
Property [categories] does not exist on this collection instance.

Managed to fix it in the end.
Changed the BlogPostResourceCollection to the following
return [
'data' => $this->collection,
'categories' => BlogCategoryCollection::collection($this->whenLoaded('categories'))
];
seems to work in the end.

Related

How to get the "catagory name" in Laravel?

How to get "category name" show in the product table not as "category_id"?
I already try to combine any solutions for this. But still can't solve this prob.
I'd love to hear other suggestions from the masters here.
Category Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Kategori extends Model
{
use HasFactory;
protected $casts = [
'updated_at' => 'datetime:d/m/Y, H:i:s'
];
public function Kategori()
{
return $this->hasMany('App\Models\Produk');
}
}
Product Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Produk extends Model
{
use HasFactory;
protected $casts = [
'updated_at' => 'datetime:d/m/Y, H:i:s'
];
public function Produk()
{
return $this->belongsTo('App\Models\Kategori', 'kategori_id');
}
}
Category Table
Product Table
Product Controller >>>> in my opinion may be my prob at here, but not so sure.
<?php
namespace App\Http\Controllers;
use App\Models\Produk;
use RealRashid\SweetAlert\Facades\Alert;
use Yajra\Datatables\DataTables;
use Illuminate\Http\Request;
class ProdukController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function json(){
return Datatables::of(Produk::all())->make(true);
}
public function index(){
return view('back.produk.show');
}
}
Pass the other model using your relationship
public function json(){
return Datatables::of(Produk::with('produk')->get())->make(true);
}
to which say that is named $produks, you can access it as
$produk->produk->nama;
As a side note, Do name your relationships the names of the other model.
for example, in the Kategori class, the relationship to Produk should be named produks (it is a hasMany relationship) as opposed to Kategori. Similarly, in the Produk class, the relationship to Kategori being named kategori() to which from the above answer you access it like
$produk->kategori->nama;
You should use:
public function json(){
return Datatables::of(Produk::with('Kategori')->all())->make(true);
}
I recommend to use camelCase for method names. I'm not sure how Datatables will handle this case.
In your ProdukController you need pass below code.
$result = Produk::with('Produk')->get();
When you dd($result);, you should see the related models in the relations array attribute.
To access the relations' properties from there, it is simply
$result->Produk->catagory_name

Polymorphic - Create inserting record and following up with blank record

I've setup a Polymorphic Relationship on my model for this, I've had to create matching fields to the table that the morph refers to.
So I've created a
Translation Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Translation extends Model
{
protected $table = 'translations';
protected $primaryKey = 'id';
protected $fillable = ['title', 'text_line1', 'text_line2', 'quote', 'language', 'content', 'translationable_type','translationable_id', 'content'];
use SoftDeletes;
public function translationable()
{
return $this->morphTo();
}
}
This is the Polymorph, Then in a seperate model - "Slides"
I've created this:
Slide Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Slide extends Model
{
/**
* Slide table
*/
protected $table = 'slides';
protected $primaryKey = 'id';
public function translations()
{
return $this->morphToMany('App\Models\Translation', 'translationable', 'translations', '', 'translationable_id');
}
}
Then in a controller, I've made a test script...
$slide = Slide::find(16);
$translations = array(
'text_line1' => $slide->text_line1,
'text_line2' => $slide->text_line2,
'language' => 'fr',
'translationable_id' => $slide->id,
'translationable_type' => 'App\Slide'
);
$slide->translations()->create($translations);
When I run this, It creates the record, But also creates another record that is totally blank other than referencing the translationable_id and translationable_type
Anyone know why it would do this?
Cheers.

Argument 1 passed to App\Http\Controllers\ApiController::showAll() must be an instance of Illuminate\Database\Eloquent\Collection

I want to to retrieve all buyers for a specific saller.When I remove pluck and others methods chaining after get method it's working. But is not exact thing that I want. How Can I solve this provlem?
(source: licdn.com)
<?php
namespace App\Http\Controllers\Seller;
use App\Http\Controllers\ApiController;
use App\Seller;
use Illuminate\Http\Request;
class SellerBuyerController extends ApiController
{
public function index(Seller $seller)
{
$buyers = $seller->products()
->whereHas('transactions')
->with('transactions.buyer')
->get()->pluck('transactions')
->collapse()->pluck('buyer')
->unique('id')
->values();
return $this->showAll($buyers);
}
protected function showAll(Collection $collection, $code = 200)
{
return $this->successResponse($collection, $code);
}
protected function successResponse($data, $code)
{
return response()->json($data, $code);
}
}
Seller model hasMany relation to products
<?php
namespace App;
use App\Scopes\SellerScope;
class Seller extends User
{
public function products()
{
return $this->hasMany(Product::class);
}
}
Product Model hasMany relation to transactions
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Product extends Model
{
use SoftDeletes;
protected $fillable = [
'name', 'description', 'quantity', 'status', 'image', 'seller_id',
];
public function transactions()
{
return $this->hasMany(Transaction::class);
}
}
Transaction Model and relation to buyer
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Transaction extends Model
{
use SoftDeletes;
protected $fillable = [
'quantity', 'buyer_id', 'product_id'
];
public function buyer()
{
return $this->belongsTo(Buyer::class);
}
}
You are missing an import at the top:
use Illuminate\Support\Collection;
otherwise it assumes Illuminate\Database\Eloquent\Collection is to be used.
And values() obviously returns the support collection, not an eloquent one.
If you have a relationship from Buyer to Transaction you can go at this from the other direction to get buyers. You also need to make sure there is a relationship from Product to Seller (make sure you have the inverse of every relationship setup)
Buyer::whereHas('transactions.products.seller', function ($query) use ($seller) {
$query->where('id', $seller->id); // might have to be a more specific key name
})->get();
You would end up with a Eloquent Collection of Buyers who have transactions including products from a particular seller.
you should put use Illuminate\Support\Collection; in folder traits over apiResponser.php

Class 'App\Models\Registration' not found even though i have import it

Class 'App\Models\Registration' not found, i have import Registration class
i am trying to save student_id with it corresponding subjects array
When i dump dd($request->all()) i get the excepted results which is
"student_id" => "1"
"subjects" => array:2 [▼
0 => "1"
1 => "2"
]
but i get an exception when i trying saving into the database
this is my registration scheme
Schema::create('registrations', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('student_id')->index();
$table->string('subjects');
$table->foreign('student_id')->references('id')->on('students');
$table->timestamps();;
});
this is my registration model
class Registration extends Model
{
protected $table = 'registrations';
protected $fillable = ['student_id','subjects'];
protected $cast = [
'student_id' => 'Integer',
'subjects' => 'array',
];
public function student(){
$this->belongsTo(Student::class);
}
public function subjects()
{
$this->hasMany(Subject::class);
}
}
i am using checkbox array to get the subjects
<input class="form-check-input" name="subjects[]" value="{{$subject->id}}" type="checkbox">
this is registration controller code, i have imported registration model
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Models\Registration;
use App\Http\Controllers\BaseController;
class RegistrationController extends BaseController
{
public function store(Request $request)
{
$registration = Registration::create(request()->validate([
'student_id' => 'required|integer',
'subjects' => 'required',
'subjects.*'=> 'accepted',
]));
}
i want to save the student_id with the subjects array
student subjects
1 [2,4,5]enter code here
I think you need to add a namespace.
<?php
namespace App\Models;
class Registration extends Model { ... }
?>
Also your model must be stored inside the directory App/Models/Registration.php.
i think you create your Registration model in App directory...please check your directory.then use
use App\Registration;
If It on App\Models directory then In Registration Model,
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Registration extends Model { }

ORM not working in Default UserController & User Model in laravel

I want to get User wise Role. here is I'm facing error ....
UserController.php ( user controller file )
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\UserRequest;
use App\Employee;
use App\Role;
use App\User;
use App\Site;
use App\Client;
use App\ProjectType;
use App\UserPermission;
use Auth;
use DB;
use App\Project;
class UsersController extends BaseController {
public function __construct() {
$this->isSetClientAndProjectType();
$data = User::with('Role')->first();
echo "<pre>";print_r(json_decode($data)); die;
}
}
User.php ( user model file )
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Authenticatable {
use SoftDeletes;
use Notifiable;
protected $fillable = [
'name', 'role_id', 'password', 'siteid', 'email', 'status', 'allowed_to_bypass_pm', 'allowed_to_bypass_admin'
];
protected $hidden = [
'password', 'remember_token',
];
// Get users roles
public function Role() {
return $this->hasMany('App\Role', 'role_id', 'id');
}
}
Error is
How can i solve this error?
Help me guys.
Thank You.
If a user has many "roles" it should be public function roles().
You have defined:
A single user has a role_id
Therefore you need:
If a user has a single role it would be:
public function role() {
return $this->belongsTo('App\Role');
}
The reverse on the Role model would be:
public function users() {
return $this->belongsToMany('App\User');
}
Since many users can have the same role.
Hope this helps.
You need to add belongsTo relationship
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Authenticatable {
use SoftDeletes, Notifiable;
protected $fillable = [
'name', 'role_id', 'password', 'siteid', 'email', 'status', 'allowed_to_bypass_pm', 'allowed_to_bypass_admin'
];
protected $hidden = [
'password', 'remember_token',
];
// Get user's role
public function role() {
return $this->belongsTo('App\Role');
}
}
Now fetch data
$user = User::with('role')->find(1);
$role = $user->role;
You need to make sure your table structure and foreign key references are compatible with the model relationship methods used.
For example, you have used "HasMany" relationship on User model. For that, you will have to make sure that each record/row in users table(User model) "has many" associated records/rows in roles table(Role model).
Here HasMany method assumes a foreign key "role_id" on roles table(Role Model). On not finding of which, it throws error.
You first need to take in consideration the table structure of roles and users table(User and Role model) as per your requirement, and than add model relationship methods accordingly.
It can be a bit tricky if you are using the methods for the first time, you can refer the laravel documentation for the same:
eloquent-relationships

Resources