Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Laravel 5.2 problem z relacją belongsToMany
rad11
post 18.07.2018, 11:45:33
Post #1





Grupa: Zarejestrowani
Postów: 1 270
Pomógł: 184
Dołączył: 7.10.2012
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Mam takie tabele:

  1. CREATE TABLE `request_hr` (
  2. `c_id` INT(11) NOT NULL,
  3. `request_id` INT(10) UNSIGNED NOT NULL,
  4. PRIMARY KEY (`c_id`, `request_id`),
  5. INDEX `request_hr_request_id_foreign` (`request_id`),
  6. CONSTRAINT `request_hr_request_id_foreign` FOREIGN KEY (`request_id`) REFERENCES `employment_requests` (`id`),
  7. CONSTRAINT `request_hr_user_id_foreign` FOREIGN KEY (`c_id`) REFERENCES `users` (`c_id`)
  8. )
  9. COLLATE='utf8_unicode_ci'
  10. ENGINE=InnoDB
  11. ;
  12. CREATE TABLE `employment_requests` (
  13. `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  14. `type` ENUM('onboarding','offboarding','ChangeOfPosition') NOT NULL DEFAULT 'onboarding' COLLATE 'utf8_unicode_ci',
  15. `status` INT(11) NOT NULL,
  16. `first_name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
  17. `last_name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
  18. `c_id` INT(10) NULL DEFAULT NULL,
  19. `job_title` TEXT NOT NULL COLLATE 'utf8_unicode_ci',
  20. `team` TEXT NOT NULL COLLATE 'utf8_unicode_ci',
  21. `localisation` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
  22. `room` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
  23. `manager_id` INT(10) UNSIGNED NULL DEFAULT NULL,
  24. `created_by` INT(10) UNSIGNED NOT NULL,
  25. `created_at` TIMESTAMP NULL DEFAULT NULL,
  26. `updated_at` TIMESTAMP NULL DEFAULT NULL,
  27. `deleted_at` TIMESTAMP NULL DEFAULT NULL,
  28. `start` DATE NULL DEFAULT NULL,
  29. `stop` DATE NULL DEFAULT NULL,
  30. `contract_type` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
  31. `vat` TINYINT(1) NOT NULL,
  32. `company1` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
  33. `per_hour1` TINYINT(1) NULL DEFAULT NULL,
  34. `pretax1` TEXT NULL COLLATE 'utf8_general_ci',
  35. `net1` TEXT NULL COLLATE 'utf8_general_ci',
  36. `beginning1` DATE NULL DEFAULT NULL,
  37. `end1` DATE NULL DEFAULT NULL,
  38. `company2` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
  39. `per_hour2` TINYINT(1) NULL DEFAULT NULL,
  40. `pretax2` TEXT NULL COLLATE 'utf8_unicode_ci',
  41. `net2` TEXT NULL COLLATE 'utf8_unicode_ci',
  42. `beginning2` DATETIME NULL DEFAULT NULL,
  43. `end2` DATETIME NULL DEFAULT NULL,
  44. `is_student` TINYINT(1) NOT NULL DEFAULT '0',
  45. `language` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
  46. `range` LONGTEXT NOT NULL COLLATE 'utf8_unicode_ci',
  47. `business_unit_id` INT(11) NOT NULL,
  48. `offboarding_conversation_date` DATE NULL DEFAULT NULL,
  49. `documents_mutual` TINYINT(1) NOT NULL,
  50. `documents_period` TINYINT(1) NOT NULL,
  51. `documents_additional_info` TEXT NULL COLLATE 'utf8_unicode_ci',
  52. `emails_to_inform` TEXT NULL COLLATE 'utf8_unicode_ci',
  53. `autoresponder_text` TEXT NULL COLLATE 'utf8_unicode_ci',
  54. `additional_info` TEXT NULL COLLATE 'utf8_unicode_ci',
  55. `note_taken_access` TEXT NULL COLLATE 'utf8_unicode_ci',
  56. PRIMARY KEY (`id`),
  57. INDEX `employment_requests_manager_id_foreign` (`manager_id`),
  58. INDEX `employment_requests_created_by_foreign` (`created_by`),
  59. CONSTRAINT `employment_requests_created_by_foreign` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`),
  60. CONSTRAINT `employment_requests_manager_id_foreign` FOREIGN KEY (`manager_id`) REFERENCES `users` (`id`)
  61. )
  62. COLLATE='utf8_unicode_ci'
  63. ENGINE=InnoDB
  64. AUTO_INCREMENT=1
  65. ;
  66. CREATE TABLE `users` (
  67. `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  68. `name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
  69. `email` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
  70. `username` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
  71. `notes` VARCHAR(1024) NOT NULL COLLATE 'utf8_unicode_ci',
  72. `uprawnienia` TEXT NULL COLLATE 'utf8_unicode_ci',
  73. `password` VARCHAR(60) NOT NULL COLLATE 'utf8_unicode_ci',
  74. `remember_token` VARCHAR(100) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
  75. `created_at` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
  76. `updated_at` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
  77. `deleted_at` TIMESTAMP NULL DEFAULT NULL,
  78. `c_id` INT(11) NOT NULL,
  79. `budget_mgr_id` INT(11) NOT NULL,
  80. PRIMARY KEY (`id`),
  81. INDEX `users_c_id_IDX` (`c_id`) USING BTREE,
  82. INDEX `users_id_IDX` (`id`) USING BTREE,
  83. INDEX `budget_mgr_id` (`budget_mgr_id`),
  84. FULLTEXT INDEX `users_email_IDX` (`email`),
  85. FULLTEXT INDEX `users_username_IDX` (`username`)
  86. )
  87. COLLATE='utf8_unicode_ci'
  88. ENGINE=InnoDB
  89. AUTO_INCREMENT=1
  90. ;
  91.  


i takie model:

  1. <?php
  2.  
  3. class EmploymentRequest extends Model
  4. {
  5. use SoftDeletes;
  6.  
  7. const BY_MUTUAL_AGREEMENT = 'Za porozumieniem stron';
  8. const BY_PERIOD_OF_NOTICE_OBSERVED = 'Z zachowaniem okresu wypowiedzenia';
  9. const AUTORESPONDER_MIN_STRING_LENGTH = 5;
  10. const OFFBOARDING = 'offboarding';
  11. const ONBOARDING = 'onboarding';
  12. const CHANGE_OF_POSITION = 'changeOfPosition';
  13. const NEW = 0;
  14. const SUPPORTED = 1;
  15. const DONE = 2;
  16. const C_ID = 'c_id';
  17. const DELETED_AT = 'deleted_at';
  18. const FURNITURE = 'furniture';
  19. const SOFTWARE = 'software';
  20. const HARDWARE = 'hardware';
  21. const CHANGE_OF_POSITION_MAPPED = 'Zmiana roli';
  22. const EMPLOYMENT_TYPES = [
  23. self::FURNITURE,
  24. self::SOFTWARE,
  25. self::HARDWARE
  26. ];
  27. const BOARDING_TYPES = [
  28. self::ONBOARDING,
  29. self::OFFBOARDING,
  30. self::CHANGE_OF_POSITION
  31. ];
  32. const BOARDING_TYPES_MAPPING = [
  33. self::CHANGE_OF_POSITION => self::CHANGE_OF_POSITION_MAPPED
  34. ];
  35.  
  36. public $timestamps = true;
  37.  
  38. protected $fillable = [
  39. 'first_name',
  40. 'last_name',
  41. self::C_ID,
  42. 'job_title',
  43. 'start',
  44. 'manager_id',
  45. 'team',
  46. 'room',
  47. 'localisation',
  48. 'created_by' ,
  49. 'contract_type',
  50. 'status',
  51. 'vat',
  52. 'company1',
  53. 'pretax1',
  54. 'net1',
  55. 'per_hour1',
  56. 'beginning1',
  57. 'end1',
  58. 'company2',
  59. 'pretax2',
  60. 'net2',
  61. 'per_hour2',
  62. 'beginning2',
  63. 'end2',
  64. 'is_student',
  65. 'language',
  66. 'range',
  67. 'business_unit_id',
  68. 'stop',
  69. 'type',
  70. 'offboarding_conversation_date',
  71. 'documents_mutual',
  72. 'documents_period',
  73. 'documents_additional_info',
  74. 'emails_to_inform',
  75. 'autoresponder_text',
  76. 'additional_info',
  77. 'note_taken_access'
  78. ];
  79.  
  80. public function supporters()
  81. {
  82. return $this->belongsToMany('App\User', 'request_supporter', 'request_id', 'user_id');
  83. }
  84.  
  85. public function hrsTakenAccess(): BelongsToMany
  86. {
  87. return $this->belongsToMany(User::class, 'request_hr', 'request_id', 'c_id');
  88. }
  89. }
  90.  


Chciałbym z tabeli request_hr pobrać wszystkie c_id dla danego requestu tak więc mam relację belongsToMany w modelu EmploymentRequest która nazywa się hrsTakenAccess ale otrzymuję zapytanie z laravela co wygląda tak:

  1. SELECT `users`.*, `request_hr`.`request_id` AS `pivot_request_id`, `request_hr`.`c_id` AS `pivot_c_id` FROM `users` INNER JOIN `request_hr` ON `users`.`id` = `request_hr`.`c_id` WHERE `request_hr`.`request_id` = ? AND `users`.`deleted_at` IS NULL


co jest złe bo zamiast `users`.`id` chce otrzymać `users`.`c_id` co robię nie tak ?
Go to the top of the page
+Quote Post
Pilsener
post 18.07.2018, 13:12:28
Post #2





Grupa: Zarejestrowani
Postów: 1 590
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

Ostrzeżenie: (0%)
-----


Jak jest złe, skoro masz
Cytat
`users`.*
, więc możesz sobie pobrać zarówno user->id jak i user->c_id
Go to the top of the page
+Quote Post
nospor
post 18.07.2018, 15:20:51
Post #3





Grupa: Moderatorzy
Postów: 36 440
Pomógł: 6289
Dołączył: 27.12.2004




@Pilsener mysle ze chodzi raczej o to
.... ON `users`.`id`


--------------------

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post
Pilsener
post 18.07.2018, 21:07:19
Post #4





Grupa: Zarejestrowani
Postów: 1 590
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

Ostrzeżenie: (0%)
-----


A w jaki sposób to zapytanie powstaje?
I totalny bałagan w nazwach, jak ktoś ma się w tym połapać?
I skoro chcesz relację many-to-many User do EmploymentRequest to dlaczego nie po user.id i employment_request.id?
Relację mapuje się po kluczu głównym i na 99% w ORM nie można tego zmienić a już na pewno nie w archaicznym Eloquent.
I nie polecam używania relacji w Larwie, bo raz, że nie ma nad tym kontroli, dwa - powstaje dużo zbędnych zapytań do bazy a trzy - kiedy trzeba coś zmienić (np. dodać dodatkowy where) musimy to zmieniać w wielu miejscach.
Najlepiej jest stworzyć sobie serwisy typu "EntityRepository" i używać query builderów:
https://laravel.com/docs/5.2/queries#selects
Go to the top of the page
+Quote Post
r4xz
post 19.07.2018, 16:33:23
Post #5





Grupa: Zarejestrowani
Postów: 673
Pomógł: 106
Dołączył: 31.12.2008

Ostrzeżenie: (0%)
-----


Wyprostuję trochę post przedmówcy:

Cytat(Pilsener @ 18.07.2018, 22:07:19 ) *
Relację mapuje się po kluczu głównym i na 99% w ORM nie można tego zmienić a już na pewno nie w archaicznym Eloquent.


  1. return $this->hasMany('App\Comment', 'foreign_key', 'local_key');


Cytat(Pilsener @ 18.07.2018, 22:07:19 ) *
I nie polecam używania relacji w Larwie, bo raz, że nie ma nad tym kontroli, dwa - powstaje dużo zbędnych zapytań do bazy a trzy - kiedy trzeba coś zmienić (np. dodać dodatkowy where) musimy to zmieniać w wielu miejscach.


Stosują po prostu metodę z dodatkowym zapytaniem zamiast joinem. Wydajnościowo wychodzi bardzo podobnie (nie mam już testów aby przywołać). Co do where to można nawet tak zrobić:

  1. return $this->hasMany('App\Comment', 'foreign_key', 'local_key')->where(...);


Jeśli chodzi o problem autora to:

  1. belongsToMany(string $related, string $table = null, string $foreignPivotKey = null, string $relatedPivotKey = null, string $parentKey = null, string $relatedKey = null, string $relation = null)


Jak widać jak narazie określiłeś tylko klucze dla tabeli "pivot" (tzn. "pośredniej"). Widzę że w modelu User masz id, zapewne domyślnie ustawione jako primaryKey, jako że w relacji nie wyspecyfikowałeś dalszych kluczy to bierze właśnie ten klucz (id).

Ten post edytował r4xz 19.07.2018, 16:39:31


--------------------
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 28.03.2024 - 09:21