C'è un modo per implementare l'ereditarietà dei ruoli usando la relazione ricorsiva sulla tabella Roles , facendo riferimento al ruolo a un altro record:

Questa relazione aggiungerà 1 : n ereditarietà all'interno di Roles disco. Potresti ottenere l'intero albero della gerarchia con questa funzione memorizzata:
CREATE FUNCTION `getHierarchy`(`aRole` BIGINT UNSIGNED)
RETURNS VARCHAR(1024)
NOT DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE `aResult` VARCHAR(1024) DEFAULT NULL;
DECLARE `aParent` BIGINT UNSIGNED;
SET `aParent` = (SELECT `parent` FROM `Roles` WHERE `id` = `aRole`);
WHILE NOT `aParent` IS NULL DO
SET `aResult` = CONCAT_WS(',', `aResult`, `aParent`);
SET `aParent` = (SELECT `parent` FROM `Roles` WHERE `id` = `aParent`);
END WHILE;
RETURN IFNULL(`aResult`, '');
END
Quindi, potresti ottenere tutti i concessi autorizzazioni con qualcosa del genere:
SELECT
`permission_id`
FROM
`Permission_Role`
WHERE
FIND_IN_SET(`role_id`, `getHierarchy`({$role}))
AND
grant;
Se non è abbastanza, potresti creare un'altra tabella per l'ereditarietà:

Ma, in questo caso, era necessario un altro algoritmo di ottenimento della gerarchia.
Per risolvere la sovrascrittura problema dovrai ottenere le autorizzazioni del ruolo e le autorizzazioni dell'utente. Quindi, scrivi user autorizzazioni su roles autorizzazioni per session .
Inoltre, suggerisco di rimuovere grant colonne in Permission_Role e Permission_User . Non è necessario mappa ogni permesso per ciascuno di essi. Quanto basta per usare EXISTS query:se c'è un record, l'autorizzazione è concessa, altrimenti non lo è. Se devi recuperare tutte le autorizzazioni e gli stati, puoi utilizzare LEFT JOIN s.