Hello guys I have made couple of classes with mappings as follows:
class Like extends Model
/**
* Returns like's author
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function owner(){
return $this->belongsTo('App\User');
}
/**
* Returns tweet
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function tweet(){
return $this->belongsTo('App\Tweet');
}
Class Tweet extends Model
/**
* Returns tweet's author
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function owner(){
return $this->belongsTo('App\User');
}
/**
* Returns tweet's likes
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function likes(){
return $this->hasMany('App\Like');
}
Class User extends Authenticatable
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'email', 'password', 'www', 'first_name', 'last_name', 'status'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
];
/**
* Returns user's tweets
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function tweets(){
return $this->hasMany('App\Tweet');
}
/**
* Returns user's likes
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function likes(){
return $this->hasMany('App\Like');
}
Now the problem is that two of my maping are not working. In Like model 'owner' method returns null, although its should return one record, 'tweet' method for the other hand works as expected.
In Tweet model the 'owner' method also returns null. All other methods are working as expected. I can't find where I have made mistake, and cannot rly understand why tweet method from Like model is working and owner is not....
Maybe Migrations find might be helpfull
public function up()
{
Schema::create('likes', function (Blueprint $table) {
$table->increments('id');
$table->integer('tweet_id');
$table->integer('user_id');
$table->string('status');
$table->timestamps();
});
}
public function up()
{
Schema::create('tweets', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->string('content');
$table->string('score');
$table->string('views');
$table->string('status');
$table->timestamps();
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('email')->unique();
$table->string('password',60);
$table->string('www');
$table->string('first_name');
$table->string('last_name');
$table->string('status');
$table->timestamps();
});
Both your Tweet & Like Models have owner() as their belongsTo() relationship method. Which is fine, but you'll have to specify the foreign key as second argument:
/**
* Returns like's author
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function owner()
{
return $this->belongsTo('App\User', 'user_id');
}
Laravel docs:
Eloquent determines the default foreign key name by examining the name of the relationship method and suffixing the method name with _id.
You have to specify the foreign key:
Schema::table('tweets', function ($table) {
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});
Related
belongsTo dont work
Model Class:
class Product extends Model
{
public function category()
{
return $this->belongsTo("App\Models\Category",'category_id');
}
}
but belongsTo with "id" (not category_id) works and select categories with same id as product
and when I change it on "category_id" it dont works
database :
class CreateProductsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string("title");
$table->string("description");
$table->integer("price");
$table->string("size");
$table->bigInteger("type_id")->unsigned();
$table->foreign("type_id")->references("id")->on("types");
$table->bigInteger('category_id')->unsigned()->default(0);
$table->foreign('category_id')->references('id')->on('categories');
$table->integer("views")->default(0);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('products');
}
}
I have following MySQL table structure:
posts table:
posts: {id(PK), title, content, slug, date, writer_id, created_at, updated_at}
writers table:
writers: {id(PK), name, type, created_at, updated_at}
Migration classes in database/migrations directory:
posts table:
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->longText('content');
$table->string('slug');
$table->date('date');
$table->date('modified_date');
$table->integer('publish');
$table->integer('trash');
$table->integer('wid');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
Changed the type of column:
class RenamePostColumn extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('posts', function ($table) {
$table->longText('content')->change();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('posts', function ($table) {
$table->longText('content')->change();
});
}
}
Renamed a column:
class RenamePostColumnWid extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('posts', function ($table) {
$table->renameColumn('wid', 'writer_id')->change();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('posts', function ($table) {
$table->renameColumn('writer_id', 'wid')->change();
});
}
}
writers table:
class CreateWritersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('writers', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('name');
$table->string('type');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('writers');
}
}
Following are my modals in app directory:
Post.php:
class Post extends Model
{
public function writer()
{
return $this->belongsTo(Writer::class);
}
}
Writer.php:
class Writer extends Model
{
public function posts()
{
return $this->hasMany(Post::class);
}
}
Now I have created a repository class in app/Repositories directory.
PostRepository.php:
class PostRepository
{
public function forSingle($slug)
{
return Post::whereSlug($slug)->get();
}
}
I debugged above query with:
return Post::whereSlug($slug)->toSql();
It returns the following query:
select * from `posts` where `slug` = ?
My routes are in routes/web.php file.
web.php:
Route::get('/post/{slug}', 'PostController#single');
Finally I have my controller in app/Http/Controllers directory.
PostController.php:
use App\Repositories\PostRepository;
class PostController extends Controller
{
protected $post;
function __construct(PostRepository $post)
{
$this->post = $post;
}
public function single($slug)
{
return view('single', [
'post' => $this->post->forSingle($slug)
]);
}
}
I have rendered a view file as follows:
single.blade.php
#if (count($post) > 0)
#foreach ($post as $blog)
<h3>{{$blog->title}}</h3>
<p>{!!$blog->content!!}</p>
#foreach($blog->writer as $writer)
<span>{{$writer->name}}</span>
#endforeach
#endforeach
#endif
Here is my problem. Everything works fine until I add
#foreach($blog->writer as $writer)
<span>{{$writer->name}}</span>
#endforeach
This section gives me error saying:
Trying to get property of non-object (View:\resources\views\single.blade.php)
I have printed the $blog in view by {{$blog}}. It does not return any writer attribute. Can you help me with this?
PS: I have not defined primary key foreign key relationships in MySQL database tables.
When it is inverse one to many eloquent, we need to explicitly tell that we need the other table data. Changing following in the PostRepository.php fixed the issue.
class PostRepository
{
public function forSingle($slug)
{
return Post::whereSlug($slug)->with('writer')->get();
}
}
You have to define foreign key or index
In my projects, I use index relation
so what you have to do is to add index relation in writer_id like this
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->longText('content');
$table->string('slug');
$table->date('date');
$table->date('modified_date');
$table->integer('publish');
$table->integer('trash');
$table->integer('wid')->unsigned()->index(); // add this
$table->timestamps();
});
}
Please try the previous
I have created two tables, First is Posts table and seconds is Comments table.
I'm using sqlite database.
I'm getting null as result for comment function using hasMany method in Post Model.
Posts table migration file:
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('Posts', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('Posts');
}
}
Comments table migration file:
class CreateCommentsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('Comments', function (Blueprint $table) {
$table->increments('id');
$table->integer('post_id')->unsigned()->index();
$table->text('body');
$table->timestamps();
});
Schema::table('Comments', function (Blueprint $table) {
$table->foreign('post_id')->refrences('id')->on('Posts');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('Comments');
}
}
Post Model:
class Post extends Model
{
//
public function comment(){
return $this->hasMany(Comment::class);
//I have also tried: return $this->hasMany(Comment::class,'post_id','id');
}
}
The data has been entered in both the tables and I'm getting results when I do
$post=new App\Post;
$post->get();
But when I try to get all the comments for a post using
$post->comment;
I'm getting
=>Illuminate\Database\Eloquent\Collection {#633
all:[],
}
Why am I getting null as a result?
You're not. You're getting an empty Collection object. This means there are no results for your post found.
You can do $post->comment->count() === 0 and get true.
Your relationship appears wrong. You said you tried something else; that one looks more correct, going by the documentation.
https://laravel.com/docs/5.0/eloquent
return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
With this, if you are still getting an empty set as a return, I would encourage you to install the Laravel debug bar and check out the raw SQL being ran. Your data is either incorrect or there is some problem that isn't being explained in your post.
Edit: You can also try setting up a belongsTo relationship on the Comment for good measure.
I know how to create a model - php artisan make:model nameofmodel, i know that in the migration of the model i have to declare what columns will the table have:
class CreateNameofmodelTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('nameofmodels', function(Blueprint $table)
{
$table->increments('id');
$table->string('name')->unique();
$table->string('description');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('nameofmodels');
}
}
But if i want to relate two models using a FK, what are the configurations i have to set in the migration file or in the model file?
Suppose you have another model User with table name users. you can have relationship defined between addresses and users as following,
public function up()
{
Schema::create('addresses', function(Blueprint $table)
{
$table->increments('id');
$table->string('add1');
$table->string('add2');
$table->string('city');
$table->string('contact_no');
$table->enum('is_primary',['yes','no'])->default('no');
$table->integer('user_id')->unsigned();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
In User model class,
class User extends Model {
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'users';
public function addresses()
{
return $this->hasMany('App\Address');
}
}
in Address class
class Address extends Model {
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'addresses';
public function user()
{
return $this->belongsTo('App\User');
}
}
More detailed information about creating table can be found on Official Schema Docs on Laravel. And More information about Relation ship here
UPDATE
According to this question, you will have to create referenced table first before referencing table. In our case, users must exists before you run migration to create addresses table.
Simple Use-case
suppose, in controller you want to find out how many addresses particular users have, you can do like following,
$addressCount = User::find($userId)->addresses->count();
Please note User::find($userId)->addresses returns collection of related models while User::find($userId)->addresses() returns object of type HasMany
you can also traverse collection as below,
foreach(User::find($userId)->addresses as $address)
{
echo '<pre>';
print_r($address);
}
On the other side, you can get user associated with particular address as below,
$user = Address:find($addressId)->user; //returns object of type `User`
echo $user->first_name;
following will not work
$user = Address:find($addressId)->user(); //returns object of type `belongsTo`
echo $user->first_name;
Note, above Address:find($addressId)->user will not return collection but a single object of class User. This is because a belongsTo relationship.
I hope I made things clear for you. But nothing as good as official docs.
Laracast videos are even better to get on with Laravel.
you cal use like this...
class CreateNameofmodelTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('nameofmodels', function(Blueprint $table)
{
$table->increments('id');
$table->string('name')->unique();
$table->string('description');
$table->timestamps();
});
Schema::create('your table name', function(Blueprint $table) {
$table->foreign('user_id')->references('id')->on('nameofmodels');
}
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('nameofmodels');
}
}
check it..may be it is working perfectly....
I'm trying to get to a ProfileType through my User model, i.e. $user->profile->profiletype; I'm not able to retrieve an object, however. Basically, User hasOne Profile, and Profile belongsTo User and ProfileType. ProfileType hasMany Profile.
My table names are users, profiles and profile_types.
models/User.php
use Cartalyst\Sentry\Users\Eloquent\User as SentryUserModel;
class User extends SentryUserModel {
/**
* Indicates if the model should soft delete.
*
* #var bool
*/
protected $softDelete = true;
public function profile()
{
return $this->hasOne('Profile');
}
}
models/Profile.php
class Profile extends Eloquent {
protected $fillable = array('username', 'slug', 'completed');
/**
* #return
*/
public function user()
{
return $this->belongsTo('User');
}
public function profiletype()
{
return $this->belongsTo('ProfileType');
}
}
models/ProfileType.php
class ProfileType extends Eloquent {
/**
* #return
*/
public function profiles()
{
return $this->hasMany('Profile');
}
}
Profile and ProfileType migrations
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
// profile_types table
class CreateProfileTypesTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('profile_types', function(Blueprint $table) {
$table->integer('id', true);
$table->string('name');
$table->string('slug');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('profile_types');
}
}
// profiles table
class CreateProfilesTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('profiles', function(Blueprint $table) {
$table->integer('id', true);
$table->string('username');
$table->string('slug');
$table->boolean('completed');
$table->integer('user_id');
$table->integer('profile_type_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('profiles');
}
}
I think you may have found a bug with the way Laravel handles foreign keys. It should know that the foreign key of profile_types is profile_type_id but it's actually looking for profiletype_id.
So you can either change that column in your table so you don't have to worry about sending extra parameters each time you need another relationship on that table, or in your Profile model, you can make your function like this...
function profiletype
{
return $this->belongsTo('ProfileType', 'profile_type_id');
}
Then you should be able to find a user's profile type with...
$user = User::find(1);
echo $user->profile->profiletype->name;
echo $user->profile->profiletype->slug;