Skip to content

feat: add Many-to-Many relationship between Projects and Users - #21

Merged
deborannies merged 1 commit into
mainfrom
development
Nov 23, 2025
Merged

feat: add Many-to-Many relationship between Projects and Users#21
deborannies merged 1 commit into
mainfrom
development

Conversation

@deborannies

@deborannies deborannies commented Nov 23, 2025

Copy link
Copy Markdown
Owner

Description
This Pull Request implements the Many-to-Many (NxN) relationship between Projects and Users, allowing the creation of research teams. Now, a Project can have multiple Members, and a User can participate in multiple Projects.

This implementation covers the full stack: Database schema, Core Framework improvements, MVC logic, UI integration, and Automated Tests.

Changes Implemented

  1. Database

Created the pivot table project_user with foreign keys and ON DELETE CASCADE.

Added a UNIQUE constraint to prevent duplicate members in the same team.

  1. Core Framework (Bonus)

Feature Upgrade: Enhanced the BelongsToMany class in the Core.

Added attach(int $id) method to handle INSERT operations on pivot tables.

Added detach(int $id) method to handle DELETE operations on pivot tables.

  1. Application Logic (MVC)

Model: Added the team() method to the Project model using the belongsToMany relationship.

Controller: Implemented addMember and removeMember methods in ProjectsController with authentication checks.

View: Updated projects/show.phtml to list team members and provide "Add/Remove" controls.

  1. Testing & Quality

Added Unit Tests for the Project model integration.

Added Unit Tests specifically for the BelongsToMany core class logic.

Updated the Populate script (ProjectUserPopulate) to automatically seed team associations.

How to Test
Setup Database:

Bash

./run db:reset
./run db:populate
Verify that projects now have team members assigned automatically.

Run Automated Tests:

Bash

./run test
Expected result: All tests passed (Green).

Manual Testing (UI):

Go to a Project details page.

Use the "Adicionar Membro à Equipe" section to select a user and add them.

Verify the user appears in the list.

Click "Remover Membro" and verify the user is removed.

Try adding the same user twice (System should prevent duplicates).

@deborannies
deborannies merged commit 488887e into main Nov 23, 2025
1 of 2 checks passed
Comment thread .phpunit.result.cache

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adicionar no .gitignore

$projectId = (int)$params['id'];
$userIdToAdd = (int)$params['user_id'];

$project = Project::findById($projectId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Permite que o usuário logado adicione membros em qualquer projeto, até naqueles não pertencem a ele.

$projectId = (int)$params['id'];
$userIdToRemove = (int)$params['user_id'];

$project = Project::findById($projectId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Permite remover membros de qualquer projeto do sistema.

<?php foreach ($teamMembers as $member): ?>
<li class="list-group-item d-flex justify-content-between align-items-center">
<div>
<strong><?= htmlspecialchars($member->name) ?></strong>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Qual a necessidade de htmlspecialchars?

Comment on lines +97 to +112
<?php if ($this->isAdmin()): ?>
<hr>
<h5 class="card-title mt-3">Adicionar Membro à Equipe</h5>

<form action="<?= route('projects.addMember', ['id' => $project->id]) ?>" method="POST" class="row g-3 align-items-end">
<div class="col-md-8">
<label for="user_id" class="form-label">Selecionar Pesquisador:</label>
<select name="user_id" id="user_id" class="form-select" required>
<option value="">-- Escolha um usuário --</option>
<?php foreach ($allUsers as $user): ?>
<option value="<?= $user->id ?>">
<?= htmlspecialchars($user->name) ?> (<?= htmlspecialchars($user->email) ?>)
</option>
<?php endforeach; ?>
</select>
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apenas esconde a view, mas não protege o backend!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adicionar ao .gitignore ./public/assets/images/*

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants