I have the following table structure, which is also on sqlfiddle for convenience:
+---------+-----------+---------+----------+-----------+-------------------+-----------------------------------+--------+--------------+-------------+---------------+-----------+ | rule_id | parent_id | left_id | right_id | rule_type | rule_title | rule_description | public | parse_bbcode | parse_links | parse_smilies | group_ids | +---------+-----------+---------+----------+-----------+-------------------+-----------------------------------+--------+--------------+-------------+---------------+-----------+ | 1 | 0 | 1 | 6 | cat | Sample Category 1 | | 1 | 0 | 0 | 0 | 1 2 7 | | 2 | 1 | 2 | 3 | rule | Sample Rule 1 | This is a sample rule description | 1 | 1 | 1 | 1 | 1 2 7 | | 3 | 0 | 7 | 8 | cat | Sample category 2 | | 1 | 0 | 0 | 0 | 1 7 2 | | 4 | 0 | 9 | 10 | cat | Sample category 3 | | 1 | 0 | 0 | 0 | 1 7 2 | | 5 | 1 | 4 | 5 | rule | Sample rule 3 | lol | 1 | 1 | 1 | 1 | 1 2 7 | +---------+-----------+---------+----------+-----------+-------------------+-----------------------------------+--------+--------------+-------------+---------------+-----------+
As you see, rule_type can be either 'cat' or 'rule'.
cat stands for category, and categories are root nodes: so parent_id is always 0. In my code, we can identify categories by checking either if rule_type = 'cat' or parent_id = 0.
You can also see that I am using nested sets for my project and this is where the problem stands.
I have successfully created functions that:
-
move rules & categories up or down; and
-
put a new rule or category in the end of their respective place.
BUT I am failing to set the RULES’ right_id & left_id if we change its parent_id! I’m also failing to set right_id & left_id if we delete a rule OR category.
Example
I’ll try to explain with an example. Note that this is just an example, not the actual case and I need a general answer.
From the table above, we see that we have 3 categories with rule_id IN (1, 3, 4) and two rules with rule_id IN (2, 5).
The rule with rule_id = 2 is part of the category with rule_id = 1, we can see that from the parent_id column. What if I change the parent_id to 4? How would the right_id & left_id get set so everything is in place again? I know we need to update both rule_id IN (1, 4) to reorder everything, but I don’t know how my query would look like.
Same goes for deleting… For example I delete rule_id = 2 (which is a rule), how would I set right_id & left_id for parent_id = 1 in the correct order? Or when I delete a category? How would I reorder the categories?
I didn’t really try doing anything here, as I have no vision how I would do such a thing, therefore I’m asking for your help, folks.
I hope I made myself clear. If not, let me know and I’ll try to be even more descriptive.
I assume you have successfully set up the PDO connection.
Also, be aware the following examples only work if all the categories are root nodes (like in the subject). It’s not a problem to change this code to work with nested categories.
Deleting a rule
Retrieve its
right_idandleft_idvalue.Delete row from the database.
Update the table set
right_id– 2 whereright_idgreater then theright_idof deleting rule.Same for
left_idExample:
Updating rule’s
parent_idSuppose we are going to move node to the last position of new parent
Retrieve updating rule’s
left_idandright_id($ruleLeftIdand$ruleRightId)Retrieve new parent rule’s
left_idandright_id($newParentRuleLeftIdand$newParentRuleRightId)Check wether a node moving up or down the tree and depending on it generate new
left_idandright_idvalues for the updating rule ($ruleNewLeftIdand$ruleNewRightId)Update rules
left_idandright_iddepending on the updating rule’s destinationUpdate
parent_id,left_id,right_idof the updating ruleIf the updating rule’s
right_keyless then new parent rule’sright_idthen the rule moves down the tree, otherwise it moves up the tree.If the rule moves down the tree we are going to shift
left_idvalue by minus 2 on the rules located between the updating rule’sleft_id($ruleLeftId) and newleft_id($ruleNewLeftId) + 1. Otherwise, shiftleft_idvalue by 2 on the rules located between newleft_id($ruleNewLeftId) and initialleft_id($ruleLeftId).Same for
right_id.Example:
I didnt use any
PDO::Statementjust to save space.I have not tested it properly so post an issue if you find some.