SOLVED i should not have called out my attributes in the models. For some reason this was keeping it from working.
I have the following structure of two models, Listing and Image. Table Images has FK listing_id that references id on table Listing.
My Eloquent Model for Listing:
namespace App\Models;
use Illuminate\Database\Eloquent\Model as Model;
class Listing extends Model {
protected $table = 'listings';
protected $connection = 'mysql';
public $id;
public $name;
public $value;
public $itemDescr;
public $user_id;
public $category_id;
protected $fillable = [
'id',
'name',
'value',
'itemDescr',
'user_id',
'category_id'
];
/**
* Return images
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function images()
{
return $this->hasMany('App\Models\Image');
}
}
My Eloquent Model for Image:
namespace App\Models;
use Illuminate\Database\Eloquent\Model as Model;
class Image extends Model
{
protected $table = 'images';
protected $connection = 'mysql';
public $id;
public $imageType;
public $title;
public $filename;
public $path;
public $author_id;
public $listing_id;
public $user_id;
public $size;
public $width;
public $height;
protected $fillable = [
'imageType',
'title',
'filename',
'path',
'author_id',
'listing_id',
'user_id',
'size',
'width',
'height'
];
/**
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function listings()
{
return $this->belongsTo('App\Models\Listing', 'listing_id');
}
}
My controller:
/**
* Return the full list of listings
*
* #param Request $request
*
* #return string
*/
public function itemList(Request $request)
{
$listings = Listing::with('images')->get();
return $listings;
}
I cannot seem to return my listing WITH the image objects -- they are always null. Here is a sample response:
{ id: 6, name: "rare listing item", value: "100", itemDescr: "this is a descr", user_id: 1, category_id: 6,
created_at: "2016-05-30 13:47:33", updated_at: "2016-05-30 13:47:33",
images: [ ] }
The database shows two images with listing_id of 6 for this particular item. I cannot figure out what could be wrong, I've tried nearly all suggestions. Any ideas?
In Laravel table columns and their values is held in $attributes property, Laravel uses __get() magic method to get the $attributes data. By defining public $listing_id as property on your model it just like telling Laravel: "Hey this is the listing_id and not the one that held $attributes property so please return this instead".
When you define the relationship:
return $this->belongsTo('App\Models\Listing', 'listing_id', 'id');
The public $listing_id property will be returned which is the value is null. Remove those public property definition and it should be works.
Related
The relationship is User who can have many Events they are associated to.
I want to be able to make an API call to get all the events associated by the user. I have changed my primary key from id to uuid. I have made the foreign key association to the Events table as well. The primary key in the events table is also a column called UUID.
I am getting error
Return value of App\Http\Controllers\UsersController::getAllEvents() must be an instance of App\Http\Resources\UserResource, instance of Illuminate\Database\Eloquent\Relations\HasMany returned
My routes table:
Route::apiResource('/users', 'UsersController');
Route::apiResource('/events', 'EventsController');
Route::get('/users/allevents/{user}', 'UsersController#getAllEvents');
So the URL im hitting is:
http://127.0.0.1:8000/api/users/allevents/0a0jqZ7qzuhemKnzB3wOPUc2Ugp2
0a0jqZ7qzuhemKnzB3wOPUc2Ugp2 is the UUID of a user. I want to get all the events associated to that user.
My User model:
class User extends Model
{
use Notifiable;
use SoftDeletes;
protected $dates = ['deleted_at'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'uuid', 'email', 'firstName', 'lastName', 'level', 'venmo'
];
public function getRouteKeyName()
{
return 'uuid';
}
public function events() {
return $this->hasMany(Event::class);
}
}
My Event Model:
class Event extends Model
{
use SoftDeletes;
protected $table = 'events';
protected $dates = ['deleted_at'];
// public function getRouteKeyName()
// {
// return 'uuid';
// }
protected $fillable = [
'id', 'availableSpots', 'uuid', 'chosenDate', 'date', 'epochTime', 'level', 'price', 'time', 'created_at', 'updated_at', 'user_uuid'
];
public $incrementing = false;
protected $primaryKey = 'uuid';
protected $keyType = 'string';
public function user(){
return $this->belongsTo(User::class, 'user_uuid', 'uuid');
}
}
My UsersController:
class UsersController extends Controller
{
public function show(User $user): UserResource
{
return new UserResource($user);
}
/**
* #param Request $request
* #param User $user
* #return UserResource
*/
public function update(Request $request, User $user): UserResource
{
$user->update($request->all());
return new UserResource($user);
}
/**
* #param User $user
* #return UserResource
* #throws \Exception
*/
public function destroy(User $user): UserResource
{
$user->delete();
return new UserResource($user);
}
public function getAllEvents(User $user): UserResource {
return $user->events();
}
}
You are using wrong type of the method return it doesn't return UserResource it return events array so by removing the wrong type it will work
public function getAllEvents(User $user) {
return $user->events;
}
public function getAllEvents(User $user)
{
return $user->events;
}
I want to retrieve data using eloquent model and return it in the following json response.
user[
transactions[],
clients[
ubications[],
contactos[],
plans[],
]
]
Currently I am receiving user,transcation and clients data but I am not able to retreive the data inside client property e.g ubications[],contactos[] and plans[].So I need help regarding the sub properties as I have already implemented the relationship.
Here are the models I am using
User.php
class User extends Authenticatable
{
use Notifiable,HasApiTokens;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function token(){
return $this->access_token;
}
public function transaction(){
return $this->hasMany(Transaction::class);
}
public function plan(){
return $this->hasManyThrough(Plan::class,Client::class);
}
public function ubication(){
return $this->hasManyThrough(Ubicacion::class,Client::class);
}
public function contacto(){
return $this->hasManyThrough(Contacto::class,Client::class);
}
public function client(){
return $this->hasMany(Client::class);
}
}
Client.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Client extends Model
{
protected $fillable=[
'nombre',
'ruc',
'status',
'user_id'
];
public function contacto(){
return $this->hasMany(Contacto::class);
}
public function feedback(){
return $this->hasMany(Feedback::class);
}
public function plan(){
return $this->hasMany(Plan::class);
}
public function ubication(){
return $this->hasMany(Ubicacion::class);
}
public function user(){
return $this->belongsTo(User::class);
}
}
You can use nested data Eager Loading:
Laravel Documentation Eager Loading
$user = User::find(1)
->with('clients', 'clients.contacto', 'clients.ubications', 'clients.plans')
->get();
I'm trying to figure out how to implement a many to many relationship with a custom intermediate model (pivot table). This is my model:
banners
- id
- title
- description
banner_regions (Pivot)
- id
- region_id
- banner_id
- active
regions
- id
- name
- slug
Eloquent Models code:
class Banner extends Model
{
/**
* Get all of the regions for the banner.
*/
public function regions()
{
return $this->belongsToMany('App\Region', 'banner_regions')
->withPivot('active')
->using(BannerRegion::class);
}
}
class BannerRegion extends Model
{
}
class Region extends Model
{
/**
* Get all of the banners for the region.
*/
public function banners()
{
return $this->belongsToMany('App\Banner', 'banner_regions')
->withPivot('active')
->using(BannerRegion::class);
}
}
Banner Controller code:
class BannerController extends Controller
{
protected $model;
public function __construct(Banner $model)
{
$this->model = $model;
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$region = $request->region; // region model instance
// ??
}
}
So, my question here is how to retrieve the banners for a particular region?
SOLUTION
I've changed my code and now it works as expected.
I changed BannerRegion pivot model to be Pivot instead of Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class BannerRegion extends Pivot
{
// It is just for casting int values into boolean values.
// Useful for JSON responses.
protected $casts = [
'active' => 'boolean',
'for_customers' => 'boolean',
];
}
Banner Model. Nothing to add here, but I've made some changes in order to improve the JSON response, like $appends.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Banner extends Model
{
protected $hidden = ['id', 'regions'];
// Add data from the pivot model
protected $appends = ['for_customers'];
public function getForCustomersAttribute()
{
// Get the attribute 'for_customers' from the pivot model
return $this->regions
->keyBy('pivot.banner_id')
->get($this->id)
->pivot
->for_customers;
}
/**
* Get all of the regions for the banner.
*
*/
public function regions()
{
return $this->belongsToMany('App\Region', 'banner_regions')
->withPivot('for_customers', 'active')
->using('App\BannerRegion');
}
/**
* Scope a query to only include active banners for a specific region.
*
* #param \Illuminate\Database\Eloquent\Builder $query
* #param App\Region $region
* #return \Illuminate\Database\Eloquent\Builder
*/
public function scopeFindbyRegionAndActive($query, Region $region)
{
return $query->whereHas('regions', function($query) use ($region) {
return $query->whereRegionId($region->id)->whereActive(true);
});
}
}
In my Banner controller, I just added:
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(Region $region)
{
return $this->model->findbyRegionAndActive($region)->get();
}
Region param is resolved by Dependency Injection (laravel.com/docs/5.4/routing#route-model-binding).
Finally, my route:
Route::group(['prefix' => '/regions/{region}'], function()
{
// Banners
Route::resource('banners', 'BannerController', ['only' => 'index']);
});
The endpoint:
/regions/my-region/banners
The JSON response:
[
{
"title": "a title...",
"description": "a descritpion...",
"link": "http://localhost",
"for_customers": true
}
]
i'm trying make an accessor, for post permalink. If i understand correctly it will change my premalink when i create new entry, but it doesn't
<?php
class Story extends Model
{
use UuidTrait;
public $incrementing = false;
protected $table = 'stories';
protected $fillable = [
'title', 'text', 'tags', 'user_id', 'permalink',
];
public function user()
{
return $this->belongsTo('App\Model\User', 'user_id');
}
/**
* Set the permalink.
*
* #param string $value
* #return void
*/
public function sePermalinkAttribute($value)
{
if(empty($value)){
$value = $this->attributes['title'];
}
$this->attributes['permalink'] = str_slug($value);
}
}
But i get NULL when save my model. Why does accessor not working?
$user->stories()->create($data['data']);
I'm trying to get the 'name' field of the 'users' table in my Articles (REST) controller.
These are my models:
// models/Article.php
class Article extends Eloquent {
protected $fillable = [];
protected $table = 'articles';
public function user(){
return $this->belongsTo('User','user_id');
}
public function upload(){
return $this->has_one('Upload');
}
}
// models/User.php
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $fillable = array('email','password','name');
public function articles(){
return $this->hasMany('Article','user_id');
}
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->getKey();
}
public function getAuthPassword()
{
return $this->password;
}
public function getReminderEmail()
{
return $this->email;
}
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
}
// controllers/ArticlesController.php
class ArticlesController extends \BaseController {
public function index() // GET (all)
{
$articles = Article::all();
foreach ($articles as $article) {
// ** ERROR ** Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$id
var_dump("title: ".$article->titulo." | user: ".$article->user()->id .' | email: '.$article->user()->email );
}
}
// other functions [....]
}
So..How can I get the fields from 'users' table properly?? I've been searching in the Laravel doc and this web and... I haven't' found the error :(
I've set up the database relationships on the migrations files and I've checked out the mysql databases relations diagram and everything is ok.
Have you checked the keys properly. belongsTo's second parameter should be the local key whereas hasMany's second parameter is the foreign key.