belongsTo not returning results as desired - laravel-5

I would like to a user be able to only have one distrito (it means district in Portuguese). A distritocan have more than one user. It's a fairly simple relationship but the problem comes when you have a third table called distritosthat it's only job is to translate numbers into strings (I don't know the name of such tables).
Distrito table
$table->increments('id');
$table->string('distrito');
e.g.
ID DISTRITO
1 - Aveiro
2 - Beja
3 - ...
User tables
$table->string('name');
$table->string('last_name');
$table->string('profile_picture')->default('default.jpg');
$table->string('userProfile')->default('');
$table->float('stars')->default(0);
distrito_user table this table will reference where the user live
$table->integer('user_id'); //id of the user
$table->integer('distrito_id'); //Id of the district where the user lives
User's model
public function distritoUtilizador(){
return $this->belongsTo(DistritoUser::class);
}
DistritoUser's model
protected $table = 'distrito_user';
Calling the eloquent model
$user = Auth::user();
dd($user->distritoUtilizador);
It returns null.
First question: Is this the correct way to solve my problem (the user lives somewhere and I need to fill that location)?
If this is the right way to solve my problem: Why it's not returning the desired results?

For a simple one to many, just store the foreign key to distrito on the user model, no need for intermediate tables.
$table->increments('id')->unsigned();
$table->string('name');
$table->string('last_name');
$table->string('profile_picture')->default('default.jpg');
$table->string('userProfile')->default('');
$table->float('stars')->default(0);
$table->integer('distrito_id')->unsigned();
$table->foreign('distrito_id')->references('id')->on('distrito');
and get rid of the distrito_user table altogether. now use has this method:
public function distrito(){
return $this->belongsTo(Distrito::class, 'id');
}
while distrito has:
public function users(){
return $this->hasMany(User::class);
}
also change distrito migration to:
$table->increments('id')->unsigned();

Related

how to check if user id exists in foreign table

I need to check if user id exists in foreign table. I have two three tables which are staffs, packaging and cutting. Both the tables packaging and cutting has staff_id column I need to check if the staff belongs to packaging or the cutting. So how do I achieve this.
Packaging table
Schema::create('packaging', function (Blueprint $table) {
$table->increments('id');
$table->integer('staff_id');
$table->string('business_name');
$table->string('tax_id');
$table->string('phone_number');
$table->timestamps();
});
Cutting table
Schema::create('cutting', function (Blueprint $table) {
$table->increments('id');
$table->integer('staff_id');
$table->string('business_name');
$table->string('tax_id');
$table->string('phone_number');
$table->timestamps();
});
I tried check using belongsTo and hasOne relation in Staff Model. but it didn't work.
public function packaging()
{
return $this->hasOne(\App\Models\Admin\PackagingCompany::class,'staff_id');
}
You should apply foreign key constraints. See docs
Schema::create('packaging', function (Blueprint $table) {
$table->increments('id');
$table->foreign('staff_id')->references('id')->on('staff');
$table->string('business_name');
$table->string('tax_id');
$table->string('phone_number');
$table->timestamps();
});
This will prevent you from being able to save a packaging record without a valid staff_id
You can also apply validation anywhere an input stores a staff member against a packaging model. This would go in your form request injected into your controller.
public function rules()
{
return [
'staff_is' => 'exists:staff',
];
}
You also mentioned that you need to check if the staff member is associated with the packaging or cutting table.
With the kind of relationship you have in the migrations you've given, a staff member could belong to both packaging AND cutting. Is that what you want?
In which case you can create packaging and cutting relationships on your User model.
public function packaging()
{
$this-> hasMany(Packaging::class)
}
And then query users that have any packaging records by doing:
// Retrieve all users that have at least one packaging record...
$users = User::has('packaging')->get();

Laravel belongsTo relationship returns null

I'm building a rudimentary CRM app using Laravel 6.0. Users can freely create accounts, but to get any functionality out of the app, they need to set up a SubscriptionAccount (or join an existing one), which will then allow them to create/manage customer Accounts, add Users, etc. (each is a one to many).
The User model's relationship to SubscriptionAccount model is giving me issues. For example:
$user = User::find(1);
$user->subscription()->create(['name' => 'Test Subscription']);
$user = $user->fresh();
dd($user->subscription); // returns null
I suspected it had to do with the belongsTo relationship in the User model, but the odd thing is that it actually creates and persists a new SubscriptionAccount while using that relationship (second line above), though if you access users relationship from the new SubscriptionAccount it also returns null.
Here are the models:
// User.php
class User
{
public function subscription()
{
return $this->belongsTo(SubscriptionAccount::class, 'subscription_account_id');
}
}
// SubscriptionAccount.php
class SubscriptionAccount extends Model
{
public function users()
{
return $this->hasMany(User::class, 'subscription_account_id');
}
}
The only thing out of the ordinary is shortening the name of the relationship to subscription from SubscriptionAccount, but that should have been taken care of by specifying the foreign key in both relationships. Here's the migrations:
Schema::create('subscription_accounts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->uuid('uuid')->unique();
$table->string('name');
$table->timestamps();
});
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->uuid('uuid')->unique();
$table->bigInteger('subscription_account_id')->unsigned()->index()->nullable();
$table->string('name');
...
$table->timestamps();
$table->foreign('subscription_account_id')
->references('id')
->on('subscription_accounts');
});
If I create the user from a SubscriptionAccount (i.e. $subscriptionAccount->users()->create([...]); it sets the correct subscription_account_id on the users table, but doesn't work vice versa.
This is a known issue (feature?) with the belongsTo relationship:
https://github.com/laravel/framework/issues/29978
To work around it you can associate the models manually:
$user = User::find(1);
$sub = Subscription::create(['name' => 'Test Subscription']);
$user->subscription()->associate($sub);
$user->save();
So instead of using belongsTo because a subscription account does not belongs to one user, it can belong to many, you might want to use the hasOne relationship instead:
public function subscription()
{
return $this->hasOne(SubscriptionAccount::class, 'id', 'subscription_account_id');
}
It will belongTo one User if you had a user_id within the subscription_accounts table.
Let me know if it makes sense and if it works :)

Eloquent Relationships Not Working as Expected

I am trying to understand what I am missing here.
Apps migration
Schema::create('apps', function (Blueprint $table) {
$table->increments('id');
$table->integer('show_id')->unsigned()->index();
$table->string('name');
$table->integer('provider_id')->unsigned()->index();
$table->timestamps();
});
Show migration
Schema::create('shows', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
So I create an apps model that has the following function
public function Show() {
return $this->hasOne(Show::class);
}
But in php artisan tinker when I do $app->Show; I get the following error:
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1 no such column: shows.app_id (SQL: select * from "shows" where "shows"."app_id" = 1 and "shows"."app_id" is not null limit 1)'
Am I mis-understanding the relationships?
Your relation should be as:
Apps model:
public function show() {
return $this->hasOne(Show::class, 'id', 'show_id');
}
Or it can be:
public function show() {
return $this->belongsTo(Show::class);
}
Docs
You do not have an app_id in your shows migration.
edit: Taking from the Laravel Docs and changing it to fit your situation
Eloquent determines the foreign key of the relationship based on the model name. In this case, the show model is automatically assumed to have a app_id foreign key.
A one-to-one relationship consists of a hasOne and a belongsTo. The table that contains the foreign key field must be on the belongsTo side of the relationship.
Since your apps table contains the show_id field, it is stated that apps belong to shows, and shows has one (or many) apps.
Given this, you need to change your Show relationship on your Apps model to use the belongsTo relationship.
public function Show() {
return $this->belongsTo(Show::class, 'show_id');
}
Unless you rename your relationship method so that it is lowercase (function show()), the second parameter is required. If you renamed the relationship, Laravel could build the proper key name and you could leave off the second parameter:
public function show() {
// For belongsTo, second parameter defaults to {function_name}_id.
return $this->belongsTo(Show::class);
}
In your apps model :
public function Show() {
return $this->belongsTo('yourmodelnamespace\Show','id','show_id');
}
And you need create Show model too ..
Hope it will works~~
You can use relation like this
public function Show() {
return $this->hasOne(Show::class, 'id','id');
}

Many to Many relationship works one way

I have a User and a Quiz models. I have many-to-many relationship defined between them in the following way:
User model
public function subscriptions()
{
return $this->belongsToMany(Quiz::class, 'subs_users', 'user_id', 'quiz_id')->withTimestamps()->withPivot('accepted');
}
Quiz model
public function subscribers()
{
return $this->belongsToMany(User::class);
}
Pivot table
Schema::create('subs_users', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('quiz_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('quiz_id')->references('id')->on('quizzes')->onDelete('cascade');
$table->primary(['user_id', 'quiz_id']);
$table->boolean('accepted')->index();
$table->timestamps();
});
When I call $quiz->subscribers, it returns a collection of users as expected. However, $user->subscriptions always returns an empty array. Why is that?
Edit
It seems, that replacing this line in Quiz
return $this->belongsToMany(User::class);
with
return $this->belongsToMany(User::class, 'subs_users', 'quiz_id', 'user_id')->withTimestamps()->withPivot('accepted');
Solves the issue, but I still can't understand why the first variant does not work.
Look at this:
public function subscriptions()
{
return $this->belongsToMany(Quiz::class, 'subs_users', 'user_id', 'quiz_id')->withTimestamps()->withPivot('accepted');
}
You mixed the foreign key with other key: user_id and quiz_id.
Remember when doing many to many relation that: first of foreign key's declared in belongsToMany is a key related to the current model.
Replacing belongsToMany() relationship in Quiz model with following:
return $this->belongsToMany(User::class, 'subs_users');
Solves the issue. It seems, that when a non-standard name is used for the pivot table, both sides must explicitly state it. In other words, 'subs_user' pivot table name must be present in belongsToMany() relationship declarations in both models.

Stuck at defining relationship in laravel 4

i'm trying to understand laravel by creating a messaging application. User should be able to send message to each other. i have made a similar application using core php.
I'm done with login/authentication and migration and now stuck at defining relationship in models;
i have created 3 tables using migrations:
users
conversations
conversations_reply
This is the Schema of:
users table (For storing detail of users)
$table->increments('id');
$table->string('username', 50);
$table->string('password', 50);
$table->string('name', 50);
$table->string('email', 254);
$table->timestamps();
conversations table(For storing conversation between users)
$table->increments('id');
$table->integer('user_one'); //foreign key of one friend from users table
$table->integer('user_two'); //foreign key of second friend from users table
$table->string('ip');
$table->timestamps();
conversations_reply table(For storing Conversation text)
$table->increments('id');
$table->text('reply');
$table->integer('user_id');
$table->integer('conversation_id'); //foreign key of conversations table
$table->string('ip');
$table->timestamps();
Now, i'm trying to define relationships in models as:
User model wil have hasMany relationship with both Conversation and ConversationReply model.
Conversation will have belongsToMany relationship with User model and hasMany relationship with ConversationReply model.
ConversationReply model will have belongsToMany relationship with both User and Conversation model.
Now i'm stuck at defining relationship in the first model(User)and unable to proceed further because i need to define local and foreign key, but i'm unable to do so because conversations table will have 2 foreign keys(of 2 users) and i can define only one foreign key.
Edit: There should be only two members in a conversation and and two users should have only one conversation(like facebook). Their new messages should be added to their old conversations. In conversations table, ip is the ip address of the user who would start the conversation and in the conversations_reply table, ip is the respective ip of the user
There seems to be a little flaw in your abstraction. You have actually designed user1 and user2 as attributes of the Conversation entity, but they are not attributes. Also, what is the IP of a conversation?
Attributes of a Conversation may be topic, start time, end time, amount of messages and things like that.
And then a conversation has members. Not exactly two but many. So you could just create an entity / model ConversationMembers that connects User and Conversation:
conversation_members table:
$table->increments('id');
$table->integer('conversation_id');
$table->integer('user_id');
$table->string('ip');
$table->string('nickname');
and change the conversations table accordingly:
$table->increments('id');
$table->boolean('public);
// other attributes you're interested in
$table->timestamps();
Now you can define the relationships on your models:
Conversation:
public function members()
{
return $this->hasMany('ConversationMember');
}
public function messages()
{
return $this->hasMany('ConversationReply');
}
ConversationMember:
public function user()
{
return $this->belongsTo('User');
}
public function conversation()
{
return $this->belongsTo('Conversation');
}
User:
public function conversations()
{
return $this->hasManyThrough('Conversation', 'ConversationMember');
}
public function replies()
{
return $this->hasMany('ConversationReply');
}
I hope this helps.

Resources