Lets say that i have the following associations schema:
Person => [
hasMany => [
Courses => [Person.id = Courses.person_id]
],
Courses => [
belongTo => [
Schools => [School.id = Courses.school_id]
]
When I view a person through mydomain/person/view/1 I need to have a table to show the Courses of that Person. Inside this table each Course need to show the name of the School.
So I tried the following on my controller:
public function view($id = null)
{
$person = $this->Persons->get($id, [
'contain' => [
'Courses.Schools',
]
]);
$this->set('persons', $test);
$this->set('_serialize', ['person']);
}
What I get on view is:
Person => [
firstname => test,
lastname => test,
courses => [
0 => [
id => 1,
shool_id => 1,
person_id => 1,
]
]
]
There is no school in the array although I used it in the contain option. So I can't display the name of the school. Am I doing anything wrong? Is there any guideline how can I show these fields on the view.
Basically I am sorry for this. This is a caused because of the debugKit. The debugkit is showing through the variables panel the associations only until the level I have mentioned but I used a var_dump and saw that the associations and the related fields are fetched/loaded correctly. I trusted the debugKit and I thought that they where not loaded.
Related
So I have a many to many relation in Laravel. provider_locations has a ManyToMany relationship with transport_modes so I've made a pivot table, provider_locations_transport_modes
I have a form which generates a nested array like so:
0 => array [
"full_address" => "Full Address"
"phone_number" => "5555555"
"transport_modes" => array [
0 => "2"
1 => "1"
]
]
So on creation, I'm attempting something like
// First create Provider
$provider = Provider::create([
'name' => $data['providerName'],
'provider_code' => $data['providerCode'],
'phone_number' => $data['phoneNumber'],
]);
// Then create provider_location, associated with provider
foreach ($data['providerLocations'] as $providerLocation) {
$provider->ProviderLocations()->create([
'full_address' => $providerLocation['full_address'],
'phone_number' => $providerLocation['phone_number'],
]);
// Now attach values to pivot table?
foreach ($providerLocation['transport_modes'] as $transportMode) {
$provider->ProviderLocations()->TransportModes()->attach($transportMode);
}
}
It's been giving me the error that "Call to undefined method Illuminate\Database\Eloquent\Relations\HasMany::TransportModes()"
TransportMode.php has a belongsToMany relation with provider_locations, and ProviderLocation.php has a belongsToMany relation with transport_modes, so the relation should be set up correctly.
What am I doing wrong?
I currently have a users table and a books table, with a pivot table user_book which has user_id, book_id as well as book_tag (this can be 'H' for happy, 'S' for sad or 'A' for angry)
Against the advice of the backpack team, we are looking to have three multiselect options, which will popoulate with the 3 different types of book tags, i.e. Happy books, Sad books, and Angry books.
I currently have the following definition inside the initFields function:
<?php
namespace App\Http\Controllers\Admin;
class UserCrudController extends UserCrudController
{
// ....
protected function initFields()
{
// crud fields here
$this->crud->addField([
'label' => "Happy books",
'type' => 'select2_multiple',
'name' => 'books_h',
'entity' => 'books',
'model' => "App\Models\Book",
'pivot' => true,
]);
}
}
This however, does not seem to save. Any assistance is greatly appreciated
you need to make sure the the relation books_h is defined correctly in your entity as belongsToMany relationship based on laravel docs https://laravel.com/docs/9.x/eloquent-relationships#many-to-many
like so
public function books_h():
\Illuminate\Database\Eloquent\Relations\BelongsToMany
{
return $this->belongsToMany(Book::class, 'user_book', 'user_id', 'book_id', 'id', 'id')->withPivot('book_tag');
}
then you need to overwrite both create and update methods to update the request for these fields to transfer it to look like so
[
1 => ['book_tag' => 'H'],
2 => ['book_tag' => 'H'],
]
before calling $response = $this->traitUpdate();
refer to this link for more info https://backpackforlaravel.com/docs/5.x/crud-operation-update#override-the-update-method
but I would recommend to use the correct way backpack team mentions https://backpackforlaravel.com/docs/5.x/crud-fields#save-additional-data-to-pivot-table even if you want to have it as 3 separate fields you can define the subfields as hidden with the value you want
I have users that can have multiple parameters. These are called for example user_param_1, user_param_2, ..., user_param_n. This is dynamic. It is a separate table user_parameters, which stores id, user_id, name and value. The relationship is a belongsTo and hasMany between Users and UserParameters. The problem is:
When editing, I want to keep it dynamically and if the user has an user_param_n+1, it should be created. But I already have problems to write the condition for the existing parameters.
I create myself an userParameters array, which contains from the $request variable only the necessary parameters. The array looks like this:
[
0 => [
"name" => "par1"
"value" => "var1"
]
1 => [
"name" => "par2"
"value" => "var2"
]
2 => [
"name" => "par3"
"value" => "var3"
]
]
Then I want to save it. My controller knows the user, so I can access to $user->id.
foreach ($userParameters as $userParameter) {
$user->parameters()->updateOrCreate(['id' => $user->parameters->id, 'user_id' => $user->id], $userParameter);
}
The issue is, that $user->parameters is an array of eloquent models. The condition is wrong. I can't access id directly. But how I can solve it? I need something like "['id' => [IF-DATABASE-ID-EXISTS-IN-ARRAY-$user-parameters]"... but how in an eloquent way?
Thanks in advance!
Best regards
I think you need to get the existing parameter using user_id and parameter_name cuz it's the uniqueness of that parameter row, if there is no parameter with this name it will create it with user_id & parameter_name and parameter_value passed to updateOrCreate function
foreach ($parameters_from_request as $parameter) {
$user->parameters()
->updateOrCreate(
[
'name' => $parameter['name'] ,
'user_id' => $user->id
],[
'name' => $parameter['name'],
'value'=> $parameter['value']
]);
}
I would like to create a junction table tbl_guid_cost_centre that gets taken care of without me manually saving it to the database. I tried adding this to my relations:
'costCentre' => [
self::HAS_ONE,
'CostCentre',
'guid_to',
'foreignKey' => 'guid',
'tbl_guid_cost_centre(guid_to, cost_center_id)',
"order" => "id desc"],
so that my when saving the costCentre, a row is created for it in my tbl_guid_cost_centre. However I'm getting the error:
Property "CHasOneRelation.0" is not defined.
Any suggestion?
You can have your junction table with the keyword through in your relations:
public function relations() {
'guidCostCentre' => [
self::HAS_ONE,
'GuidCostCentre',
['guid_to' => 'guid']
],
'costCentre' => [
self::HAS_ONE,
'CostCentre',
'cost_centre_id',
'through' => 'guidCostCentre'
]
}
You're defining HAS_ONE relation in a wrong way. The first three elements of relation configuration array should be: relation type, related model name and foreign keys definition. All further elements should be indexed by keys related to relation properties. 'tbl_guid_cost_centre(guid_to, cost_center_id)', probably generates this error, because it does not have a key, so it is treaded as a value for 0 property. You didn't share any details, so it is hard to guess what you want to achieve, but you should start from something like this:
'costCentre' => [
self::HAS_ONE,
'CostCentre',
'guid_to',
'order' => 'id desc',
],
And add additional settings at the end array with correct key.
Some examples and explanation you can find in the documentation: https://www.yiiframework.com/doc/guide/1.1/en/database.arr#declaring-relationship
Im trying to save data inside a pivot table with an extra field called data.
when i save i have this array:
[
5 => "files"
4 => "pictures"
3 => "tags"
1 => "thumbs"
]
My table looks like this:
project_id
option_id
name
The ids shown above refer to option_id and the string to name inside the database.
When i try to use sync like this: $project->options()->sync($data);
$data is the array shown above
Im getting a error thats its trying to save the option_id with "files".
Here is how i build up the data that i use for sync:
Im trying to get what you suggested but dont know how to achieve it:
here is how i build up the array:
foreach($request->input('option_id') as $id) {
$option['option_id'][] = $id;
$option['data'][] = $request->input('data')[$id];
}
$data = array_combine($option['option_id'], $option['data']);
This is covered in the manual:
Adding Pivot Data When Syncing
You may also associate other pivot table values with the given IDs:
$user->roles()->sync(array(1 => array('expires' => true)));
In your example, you would have to change your array to look something like below but I believe this would translate to:
$data = [
5 => [ 'name' => "files" ],
4 => [ 'name' => "pictures" ],
3 => [ 'name' => "tags" ],
1 => [ 'name' => "thumbs" ],
];
$project->options()->sync($data);
I believe you may also need to modify how your Project model relates itself to your Options model:
// File: app/model/Project.php
public function options()
{
return $this->belongsToMany('Option')->withPivot('name');
}
This is also noted in the linked-to manual page:
By default, only the keys will be present on the pivot object. If your pivot table contains extra attributes, you must specify them when defining the relationship.
Update
Try creating your $data array like this:
$data = [];
foreach($request->input('option_id') as $id) {
$data[$id] = [ 'name' => $request->input('data')[$id] ];
}