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.
Related
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 created a users table using Laravel's schema builder. Here is the migration:
class CreateUsersTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::connection('mysql-internal')->create('users', function(Blueprint $table)
{
$table->increments('id');
$table->string('username');
$table->string('password');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::connection('mysql-internal')->drop('users');
}
}
After running this migration, I then rolled it back using php artisan migrate:rollback. However, it looks like down method did not respect my connection. The users table was dropped from my default mysql database rather than the mysql-internal that I specified.
Did I do something wrong here? I am using Laravel 4.2.17.
I have a comments table and user table with the relationship: user->hasMany('comments') and comment->belongsTo('user'). For some reason with which eludes me, I keep getting this
FatalErrorException in Comment.php line 22: Call to undefined function App\belongsTo()
My other models have no issue whatsoever with the HasMany relations, however, the comments model has a problem with every single thing i try (even if i use HasMany just to see if it will have a different error).
Here is the Comment model.
use Illuminate\Database\Eloquent\Model;
class Comment extends Model {
protected $table = 'comments';
protected $fillable = [
'anime_id',
'user_id',
'user_comment'
];
public function postedOnAnime($query)
{
$query->where('anime_id', '=', $this.id);
}
public function user()
{
return $this.belongsTo('App\User', 'user_id', 'id');
}
public function anime()
{
return $this.belongsTo('App\Anime');
}
}
Here is the Users table:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->integer('role');
$table->string('name')->unique();
$table->string('email')->unique();
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('users');
}
}
Here is the Comments table
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCommentsTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('comments', function(Blueprint $table)
{
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('anime_id')->unsigned();
$table->text('user_comment');
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
$table->foreign('anime_id')
->references('id')
->on('animes')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('comments');
}
}
Finally, when I call $comment->user() it fails with the error. Does anyone know where this error comes from?
Thanks.
Well, this error occurred because I had '.' in place of '->'. I couldn't figure out why it was always throwing the exact same error regardless if I did $this.belongsTo('App\User'); or $this.hasMany('App\User'); or even $this.thecakeisalie('App\User'); until I sat staring at the text between my many models yet again. Then, lo and behold, its another dumb, tiny and really hard to locate mistake of mine(as it usually is).
return $this.belongsTo('App\User', 'user_id', 'id');
to
return $this->belongsTo('App\User');
I think this is a common mistake coming from other languages where . is used to access properties. In PHP, it should be ->.
$this.belongsTo('...')
should be rewritten as
$this->belongsTo('...')
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 have two types of workbench migrations: creating regular tables and creating pivot tables for Many-to-Many relationships.
Sample of regular migration:
<?php
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function(\Illuminate\Database\Schema\Blueprint $table)
{
$table->increments('id')->unsigned();
$table->string('login')->unique();
$table->string('username')->unique();
$table->string('password');
$table->string('email');
$table->boolean('active')->default(true);
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
Above migration can be rolled back
<?php
use Illuminate\Database\Migrations\Migration;
class CreatePivotRoleUser extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('role_user', function(\Illuminate\Database\Schema\Blueprint $table)
{
$table->integer('role_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->primary(['role_id', 'user_id']);
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('role_user');
}
}
While this cannot, because it gives
"Class 'CreatePivotPermissionRole' not found"
error.
How to fix it?
Your code looks correct.
If CreatePivotPermissionRole is not found, it means it had been deleted before. Check the content of all your down() methods, there must be something wrong there.