How to pass arguments to Laravel factories? - laravel

I have a users table and a one-to-zero/one relation with a businesses table (users.user_id => businesses.user_id). On my users table I have a discriminator which tells me if the user is of type business and therefore I need to have details on the businesses table as well.
I want to create my Users with my factory which currently is working and then only create business details where the discriminator points to a business account.
I have three options in my mind:
Create from users factory and then using '->each()' do some checks on the discriminator and create a new business user using a the factory. However I cannot pass to the business factory the user_id that the user was assigned.
First create the users. Then in my Business seeder, retrieve all Users that match a 'business' discriminator. Then for all of these users run a factory that creates the business details. But again, I would have to link somehow the user_id of the already create user with the business factory user_id.
In my business factory, create a new User and retrieve the id, thus making the link between users.user_id and business.user_id. However I am using a random generator for user.user_type so even if I have the businesses table filled it might be for users that have the discriminator as 'personal'.
Is there another way? Can I pass arguments from my Seeder to the factory?

The attributes you pass to the create function will be passed into your model definition callback as the second argument.
In your case you don't even need to access those attributes, since they'll automatically be merged in:
$business = factory(App\Business::class)->create();
factory(App\User::class, 5)->create([
'business_id' => $business->id,
]);
Adapt this to your needs.

My code for adding polymorphic 'Admin' users was:
// run model factory
factory(App\Admin::class, 3)->create()->each(function ($admin) {
$admin->user()->save(
// solved: https://laravel.com/docs/master/database-testing#using-factories (Overriding attributes)
factory(App\User::class)->make([
'userable_id' => $admin->id,
'userable_type' => App\Admin::class
])
);
});
Hope this helps.

Send attribute,
factory(App\User::class)->create(['businessId' => $businessId]);
Retrieve it,
$factory->define(App\User::class, function (Faker $faker, $businessInfo) {
//$businessInfo['businessId']
});

Related

MorphTo with conditions

I am working with field MorphTo and I try to make conditions for the resources.
For example I have 4 resources:
Accounts
PaymentMethodCreditCard
PaymentMethodBankAccount
Transactions
Every Account can add as many Payment Methods as he wants.
And in the transaction I work with MorphTo to select the Payment Method that the account selected.
My problem starts when I try to create a transaction from Nova and get a list of all the Payment Methods in the db without any relation to the account.
My ideal idea was like that:
MorphTo::make('Transactions')
->withoutTrashed()
->dependsOn('Account', function (MorphTo $field, NovaRequest $request, FormData $formData) {
if(isset($formData->Account)){
$field->types([
PaymentMethodCreditCard::class => fn($q)=>$q->where('account_id', $formData->Account),
PaymentMethodBankAccount::class => fn($q)=>$q->where('account_id', $formData->Account),
]);
}
}),
But of course it will not work, Someone has any idea how I can add conditions to the resource?
I'll give you two answers. Since the question does not exactly clarify whether the Account value is changable during the edit process or it's predefined.
Account value does not change.
If the account value does not change after the resource is loaded, then the solution you are looking for is Relatable Filtering
public static function relatablePaymentMethods(NovaRequest $request, $query)
{
$resource = $request->findResourceOrFail();
return $query->where('account_id', $resource->Account);
}
Account value can change
If the account value can change, then you'll need to create your own "Morph To" behavior using Select and Hidden fields.
With Select field, you can utilize the dependsOn and options functions, to change the query results when the Account changes.

Is that possible to initialize all the tenants DB at once and take all the records in a table? Laravel Multi tenant

As my diagram, I want to get all the records of table 1 in every tenants from the central domain side. Is that possible to initialize all the tenants at once and take all the records?
Or should I initialize tenants one by one and push records to an array?
I am using the tenancyforlaravel (archtechx/tenancy) package
Updated 1
In tenancyforlaravel tenancy package has a feature to connect tenant DB.It is called initialization. Normally It automatically identifies the database and initializes it by domain address. Also can manually initializes but need to give tenant id. Source link
Finally, I figure out how to do that after long days. It is very very easy with this package. There is a helper function. Only need to use this runForMultiple helper function. below has the example code,
tenancy()->runForMultiple(null, function (Tenant $tenant) {
foreach (Product::get() as $product) {
array_push($this->products, [
'shop_id' => $tenant->id,
'shop_name' => $tenant->name,
'id' => $product->id,
'name' => $product->name,
]);
}
});

Laravel update creates a new record

AM trying to update existing record with eloquent via
return Users::where('id', $id)
->update(['names' => $request->input("name")]);
But the above creates a new record. What am i missing on this?
I would like this to be one line as above.
You have missed many things, such as coding convention of Laravel. Indeed, we usually create model in singular firm but you created "Users". Instead of "Users" you can create "User" model. And the syntax is also incorrect. So you can follow the below code. It should work if you have created table, model and controller in a correct way.
return User::where('id', $id)->first()->update(['name' => $request->input("name")]);
Or
return User::findOrFail($id)->update(['name' => $request->input("name")]);

Create indirect relationships and return the sum of two relationships

I have a program to share services between people. Basically I am facing a problem trying to get the conversations between users. Here is the idea:
My program allows users to offer services to other users, but also to acquire services from other users. Each user can register an unlimited number of services.
When a user finds a service that he/she wants to get, he creates a deal and starts a conversation with the counterpart.
The structure of my tables is the following (I am only including the relationship columns):
Users table
id // This is the user identifier
Services table
id // This is the service identifier
user_id // This is the identifier of the user who created the service
Deals table
id // This is the deal identifier
user_id // This is the identifier of the user acquiring the service
service_id // This is the identifier of the service being acquired in this deal
Conversations table
id // This is the identifier of the conversation
deal_id // This is the identifier of the deal that the conversation belongs to
Here is my problem:
I want to be able to retrieve the conversations for each user, both as applicant and as a seller.
I created this relationship (in User.php) for conversations in which the user is acquiring the service:
public function conversationsApplicant(){
return $this->hasManyThrough( Conversations::class, Deal::class );
}
I would like to create also the conversationsSeller() function
public function conversationsSeller(){
return $this->????;
}
I am guessing I should add some kind of relationship between a Conversation and a Service in Service.php. It would be something like $this->services()->with( 'deals' )->with( 'conversations' );
The final goal would be to have a method that returns both relationships in one $user->conversations()->get().
public function conversations(){
return $this->conversationsApplicant() + $this->conversationsSeller();
}
To retrieve the relationship I was thinking that maybe there is a workaround using a SQL query, but I am not sure if that will return the relationship as I need it. Here is the query that I need to perform:
SELECT
conversations.*
FROM
mydb.conversations, mydb.services, mydb.users, mydb.deals
WHERE
users.id = services.user_id AND
services.id = deals.service_id AND
deals.id = conversations.deal_id AND
users.id = $user->id;
Here is how you implement merged relationship simply
public function getCombinedChats($value)
{
// There two calls return collections
// as defined in relations.
$Applicant= $this->conversationsApplicant;
$Seller= $this->conversationsSeller;
// Merge collections and return single collection.
return $Applicant->merge($Seller);
}

Laravel get related data from 3 tables

I have three tables: users, emails,attachments. User table is connected with emails by user_id. Emails table is connected with attachments by email_id.
My question is: How should I make it look eloquent in laravel to get all users their emails and their attachments? (I know how get all user and they emails but I don't know how to add attachments.)
Depending on your database relationship,you may declare a relationship method in your Email model, for example:
// One to One (If Email has only one attachment)
public function attachment()
{
return $this->hasOne(Attachment::class);
}
Otherwise:
// One to Many (If Email contains more than one attachment)
public function attachments()
{
return $this->hasMany(Attachment::class);
}
To retrieve the related attachment(s) from Email model when reading a user using id, you may try something like this:
$user = User::with('email.attachment')->find(1); // For One-to-One
$user = User::with('email.attachments')->find(1); // For One-to-Many
Hope you've already declared the relationship method in the User model for Email model using the method name email.
Note: make sure, you have used right namespace for models. It may work if you've done everything right and followed the Laravel convention, otherwise do some research. Also check the documentation.

Resources