Well, actually this does not have to do anything with Laravel at all. This is MySQL. If you run the following SQL code, you end up with the same situation.
drop table if exists `a_b`;
drop table if exists `a`;
drop table if exists `b`;
create table `a` (`id` int unsigned not null) default character set utf8mb4 collate utf8mb4_unicode_ci;
alter table `a` add primary key `pk_a`(`id`);
create table `b` (`id` int unsigned not null) default character set utf8mb4 collate utf8mb4_unicode_ci;
alter table `b` add primary key `pk_b`(`id`);
create table `a_b` (`a_id` int unsigned not null, `b_id` int unsigned not null) default character set utf8mb4 collate utf8mb4_unicode_ci;
alter table `a_b` add constraint `a_b_a_id_foreign` foreign key (`a_id`) references `a` (`id`) on delete cascade on update cascade;
alter table `a_b` add constraint `a_b_b_id_foreign` foreign key (`b_id`) references `b` (`id`) on delete cascade on update cascade;
alter table `a_b` add primary key `pk_a_b`(`a_id`, `b_id`);
MySQL automatically creates a index for a foreign key, if one does not exist. The primary key is already good enough to be an index for a_b_a_id_foreign, so only a_b_b_id_foreign get's created. If you remove the primary key SQL statement, both indexes are created and if you change the order of the primary key to b_id, a_id, the a_b_a_id_foreign is created and the a_b_b_id_foreign is not needed.