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;
Related
I have an Item and AdvertItem objects in Laravel. I want to create a 1 to 1 relationship between an item and advert item
The item class looks like this
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Item extends Model
{
//
public function Category(){
return $this->belongsTo(Category::class);
}
public function Currency(){
return $this->hasOne(Currency::class);
}
public function AdvertItem(){
return $this->hasOne(AdvertItems::class);
}
}
and the AdvertItem class looks like this
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class AdvertItems extends Model
{
protected $guarded = [];
//
public function items(){
return $this->belongsTo(Item::class);
}
}
but when I call advertItem I only see item_id = 1 instead of item object.
Item table is created like this
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('description');
$table->unsignedBigInteger('currency_lookup_id');
$table->unsignedBigInteger('category_id')->index();
$table->unsignedBigInteger('price');
$table->string("image_path");
$table->string('sale_ind');
$table->Date('eff_from');
$table->Date('eff_to');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('item');
}
}
And advert table is created like this
class CreateAdvertItemsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('advert_items', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('item_id');
$table->unsignedBigInteger('customer_id');
$table->Date('eff_from');
$table->Date('eff_to');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('advert_items');
}
}
please assist.
The following rules will assist you.
Always start relationship names with lower case. Save capitals for Classes not methods.
Models should be Singular
Pay attention to the plurality of names. Things that there should only be one of should be singular. So, in your 1:1 relationships, both relationship names should be singular.
AdvertItem class
public function item(){
return $this->belongsTo(Item::class);
}
then, if you have Item and want AdvertItem, you should load it
$item->load('advertitem');
or the other way around
$advertItem->load('item');
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');
});
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 am working on a project where, I have been assigned a task to create user management for the application. But I have stuck on the table relationship and their migration.
Effort
I have these tables:
Users
user_id
username
password
Profiles
profile_id
user_id
firstname
lastname
email
Address
address_id
profile_id
address
city
state
country
pincode
Configurations
config_id
configuration_name
configuration_type
parent_id
Now I have to create model and migration for the same above structure. For this i have create/modify below model and migration class.
Model: User
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username', 'password',
];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function profile()
{
return $this->hasOne('Profile','user_id');
}
}
Migration: 2014_10_12_000000_create_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('user_id');
$table->string('username');
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('users');
}
}
Model: Profile
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
public function user(){
return $this->belongsTo('User');
}
public function address()
{
return $this->hasOne('Address','address_id');
}
}
Migration: 2016_02_26_101749_create_profiles_table.php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateProfilesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->increments('profile_id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('user_id')->on('users')->onDelete('cascade');
$table->string('lastname')->nullable();
$table->string('firstname')->nullable();
$table->string('gender')->nullable();
$table->string('email')->unique();
$table->string('phonenumber', 20)->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('profiles');
}
}
Model: Addess
namespace App;
use Illuminate\Database\Eloquent\Model;
class Address extends Model
{
public function profile(){
return $this->belongsTo('Profile');
}
public function city() {
return $this->hasOne('Configuration', 'config_id');
}
public function state() {
return $this->hasOne('Configuration', 'config_id');
}
public function country() {
return $this->hasOne('Configuration', 'config_id');
}
}
Migration: 2016_02_26_102805_create_addresses_table.php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAddressesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('addresses', function (Blueprint $table) {
$table->increments('address_id');
$table->integer('profile_id')->unsigned();
$table->foreign('profile_id')->references('profile_id')->on('profiles')->onDelete('cascade');
$table->string('address')->nullable();
$table->integer('city')->unsigned();
$table->foreign('city')->references('config_id')->on('configurations')->onDelete('cascade');
$table->string('pincode')->nullable();
$table->integer('state')->unsigned();
$table->foreign('state')->references('config_id')->on('configurations')->onDelete('cascade');
$table->integer('country')->unsigned();
$table->foreign('country')->references('config_id')->on('configurations')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('addresses');
}
}
Model: Configuration
namespace App;
use Illuminate\Database\Eloquent\Model;
class Configuration extends Model
{
public function children() {
return $this->hasMany('Configuration','parent_id');
}
public function parent() {
return $this->belongsTo('Configuration','parent_id');
}
public function address(){
return $this->belongsTo('Address');
}
}
Migration: 2016_02_26_104519_create_configurations_table.php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateConfigurationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('configurations', function (Blueprint $table) {
$table->increments('config_id');
$table->string('configuration_name');
$table->string('configuration_type');
$table->string('parent_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('configurations');
}
}
Now, when I run php artisan migrate I am getting error that :
.
Please suggest me how to do that. I have to use same table structure and cannot modify it. If any further update require or I forgot something please let me know.
That happen because migration will try to migrate address table before configuration so it will not found the foreign key config_id you're referenced, so you could change the name of migrations files then the migration commad could pass the configurations_table migrate file first then the addresses_table migrate file, so just change :
2016_02_26_104519_create_configurations_table.php
To :
2016_02_26_102005_create_configurations_table.php
_____________^
After that you should run optimize command to regenerating optimized class loader :
php artisan o
And rerun php artisan migrate command now the problem should be solved.
Hope this helps.
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....