PHP/MySQL Reorder Menu with Position set in table - php

In MySQL I have a table with a name, id, position, and content values.
The content is loaded onto a page in php by querying by id. The position is used in php to create a dynamic menu with the menu items ascending by position value.
So for example, say There were 3 rows with each row having a position value of 1, 2, or 3.
I am trying to build a form to allow the user to change the position of the menu, items, or add a new one. So if the row in position 3 wants to be changed to position value 1, then 2 needs to become 3 and 1 needs to become 2. Or if a new item is added, the position its taking and all below it need to be shifted up a value.
What would be the best way of approaching this?
Any suggestions would be appreciated.

If you add new item- frst update all items with position value equal or more:
UPDATE MenuItems SET position = position + 1 WHERE position >= newItemPosition;
If you are updating - update only item with position higher than higherItemPosition (they will only switch places).
UPDATE MenuItems SET position = position - 1 WHERE position = higherItemPosition;
If newItemPosition is updated to lower value I would do sth like that:
UPDATE MenuItems SET position = position + 1 WHERE position = lowerItemPosition;

Two ideas come to mind:
have the menu as an AJAX loaded div and then react to the change and reload the div, which means you could rerun the SQL
load the answers into a javascript array and present them that way as you then have drag change abilities.

Before we swarm the database with queries, create indexes (e.g. primary key) that covers the position field, update several rows with their index entries per change, and so on, let's consider the following:
How long would a menu get, in the worst case?
Do you really need to obtain individual rows from the menu, or whenever you need to display a menu you need to SELECT all of its rows?
Most often, these cases can be solved with a much simpler, pragmatic approach that will also be far easier for you as a programmer. If the menu isn't going to be too long and you probably need all of it every time you need to read it, why not keep it as a list (of items of whatever type) in your program, and serialize it with whatever method (e.g. JSON or Python Pickle) before storing it in the database as a single row with a text field? If the menu is in a list, reordering its elements will be pretty simple, a read operation for the menu would demand a single row SELECT for the database, and a write operation would require a single UPDATE, without caring for keeping a Position field updated.

Related

Pairing fields in a table for a select query

Hi, so I have this database project I'm working on that involves transcribing archival sources to make them more accessible.
I'm revamping the database structure, so I can make the depiction of the archival data more accurate to the manuscript sources. As part of that, I have this new table, which has both the labels/titles for columns of data in the documents, plus a "used"field which acts both as a flag for if the field is used, and also for what position it should be in left to right (As the order changes sometimes).
I'm wondering if there's a way to pair the columns together so I can do a query that - when asking for a single row to be returned= sorts the "used" functions numerically (returning all the ones that aren't -1), and also returns all the "label" fields also sorted into the same order (eg if guns_used is 2, and men_used is 1 and ship_name_position is 0, the query will put them in the correct order and also return guns_label, men_label and shipname_label in the correct order).
I'm also working with/around wordpress, so I have the contents of the whole wpdb thing available to me too.
I'm hoping to be able to "pair" the fields in some way so that if I order one set, the other gets ordered as well.
Edit:
I really would prefer to find a way to do this in a query but until I find a way to do that I'm going to
a)Select the entire row that I need
b)Have a long series of if statements- one for each pair of _label/_used fields- and assigning the values I want to the position in the array indicated by the value of the _used field.

Allowing user to add/remove/order fields and recording in database

I am trying to add some functionality to my website which allows users to add/remove/put certain fields in order.
For example: There are 5 paragraphs and I want the user to be able to put these in the order they like and also delete some if they do not find them useful.
I know I will have to use jQuery for this (sortable) but need some advice on how to store this order/selected elements in a database (using mysql and php).
You can use a 2-dimensional array in JavaScript combined with an index field in the MySQL database, like this:
var list_index = new Array();
list_index[0] = [245, 1, 1, 'BMW'];
list_index[1] = [256, 2, 2, 'Porsche'];
The first key is the MySQL Index of the entry. The second index key represents the index on the HTML (live) list. The third index key represents the index key in your database. So it can look like this too when you would swap Porsche to the top in your list:
list_index[0] = [256, 2, 1, 'BMW'];
list_index[1] = [245, 1, 2, 'Porsche'];
Keeping this values in mind you can use jQuery to post the updated the index keys to your PHP code and update them in the database.
First thing that comes to me is to have a table "preferences". If you website has limited elements you can have columns defining all of them and a page to manage the preferences of that user.
If your website is quite big and always changing, you migh have to think about defining properties, values and effects in one table, and in preferences store property, value and element that aples.
Use Ajax. Inside database create table UsersParagraphs - 1 row will reflect order numbers of paragraphs for certain user. On your website u can create movable divs (with paragraphs) dynamically using data from table Paragraphs. After change of div order by user, u can this action reflect in table Paragraphs.

Changing order of records from the front end

I am faced with a problem coding my next feature. I want the user to be able to rearrange records and change the display_order value. I'm using Jquery UI's draggable and droppable to facilitate this.
I can see how a simple swap of display_order values would work. But I want to set a display order for a record and ideally have the others shuffle around so there are no repeated display_order values. Apart from not getting my head around how I would do that it seems like it would be hard to code and inefficient, shuffling every value around in the list.
So I am open to other suggestions of how this sort of thing is normally, or should be done.
I though of maybe using a value like 3.000 to represent the order and then when I want to make a record take its place make its value 3 - 0.001 so its 2.999 and will sort between 2 and 3. But I can see so many things wrong with that idea and doesn't seem like a good path to follow.
Thanks for any input!
add a sorting column to your table, smallint,
mediumint or int depending on the
expected number of total entries
A new entry is appended to the end, max(sorting) + 1
when reordering an item, get the new position it will be in and alter the higher sorting entries accordingly:
mysql_query('UPDATE yourTable set sorting = '.$yourNewposition.' where id='.$yourUniqueId .' LIMIT 1');
mysql_query('UPDATE yourTable set sorting = sorting + 1 where sorting >= '.$yourNewposition.' AND id != '.$yourUniqueId );

MySql & PHP: How to find which row has an item in the leading spot in a CSV list?

This is kind of a weird question so my title is just as weird.
This is a voting app so I have a table called ballots that has a two important fields: username and ballot. The field ballot is a VARCHAR but it basically stores a list of 25 ids (numbers from 1-200) as CSVs. For example it might be:
22,12,1,3,4,5,6,7,...
And another one might have
3,4,12,1,4,5,...
And so on.
So given an id (let's say 12) I want to find which row (or username) has that id in the leading spot. So in our example above it would be the first user because he has 12 in the second position whereas the second user has it in the third position. It's possible that multiple people may have 12 in the leading position (say if user #3 and #4 have it in spot #1) and it's possible that no one may have ranked 12.
I also need to do the reverse (who has it in the worst spot) but I figure if I can figure out one problem the rest is easy.
I would like to do this using a minimal number of queries and statements but for the life of me I cannot see how.
The simplest solution I thought of is to traverse all of the users in the table and keep track of who has an id in the leading spot. This will work fine for me now but the number of users can potentially increase exponentially.
The other idea I had was to do a query like this:
select `username` from `ballots` where `ballot` like '12,%'
and if that returns results I'm done because position 1 is the leading spot. But if that returned 0 results I'd do:
select `username` from `ballots` where `ballot` like '*,12,%'
where * is a wildcard character that will match one number and one number only (unlike the %). But I don't know if this can actually be done.
Anyway does anyone have any suggestions on how best to do this?
Thanks
I'm not sure I understood correctly what you want to do - to get a list of users who have a given number in the 'ballot' field ordered by its position in that field?
If so, you should be able to use MySQL FIND_IN_SET() function:
SELECT username, FIND_IN_SET(12, ballot) as position
FROM ballots
WHERE FIND_IN_SET(12, ballot) > 0
ORDER BY position
This will return all rows that have your number (e.g. 12) somewhere in ballot sorted by position you can apply LIMIT to reduce the number of rows returned.

MySQL based web app: Easiest way for users to choose order or items?

I'm working on something where users can rearrange items, and at a later time, those items need to be displayed in the order chosen. As a simple example, consider a list of items:
A, B, C, D, E, F, G.
The MySQL table would be something simple: user_id, letter, sortnumber
The user is allowed to change the order in incremental steps. They might move A to after D, G to the beginning, etc. In addition to this, they can add, and remove items. So they might delete C, or add X. In each of these steps, I send data to PHP, which will process it, and set the items in MySQL.
There are two ways I see going about this:
Each time they add/remove/reorder
something, send the entire list to
PHP, delete all the data they
previous had in there, and just
insert the new list. Problem is,
this is a lot of
deletions/insertions each time they
do anything. They might move A to after B, and then suddenly I delete 7 records, and insert 7 more. On the plus side, it's dead simple.
Each "move" they do (e.g. an add, or a remove, or a reorder), send the information for that. E.g. they moved An after F, and tell me "move An after F" I now have to check that both A and F exist on the list, then I have to decrement all "sortnumber" between A and F (including F). If they say "delete Z" I have to find it on the list, delete it, and decrement all sortnumbers of records after it.
So I'm just curious... Has anybody had to deal with something where order matters, and if so, how did you go about it?
Add a Sequence column to the table - as a floating point number.
When an item is moved between Row-A and Row-B set its sequence number to the Average of those adjacent columns
Index the Sequence column :)
When the user wants to save the new order of the items, have it compare the new order to the old order and only perform updates on ones who have their sortnumber changed. If they delete an item, you don't need to shift the sortnumbers down. If you sort a list with a number that is missing in the middle, it will still be in the correct order.
The final sequence order is the only one that matters. If you move six items around to get a particular order, you don't really need to care what the sequence of the list is at the points between how it was when you started and what it's like when you're done.
Add and remove items without worrying about the sequence order, and then update the items to set the sequence value when you click a button that says, "Save Sort".
This gives you two advantages:
It's much less overhead every time you change an item, which also means it'll be faster.
It's dead simple to set the sequence -- all you have to do is send a list of the item IDs in the desired order and then iterate over it, updating the sequence value starting at 0 and going up.
Here's the same answer I gave to Thomaschaaf's question:
This is not and easy problem. If you
have a low number of sortable
elements, I would just reset all of
them to their new order.
Otherwise, it seems it would take just
as much work or more to "test-and-set"
to modify only the records that have
changed.
You could delegate this work to the
client-side. Have the client maintain
old-sort-order and new-sort-order and
determine which row[sort-order]'s
should be updated - then passes those
tuples to the PHP-mySQL interface.
You could enhance this method in the
following way (doesn't require
floats):
If all sortable elements in a list are initialized to a sort-order
according to their position in the
list, set the sort-oder of every
element to something like
row[sort-order] = row[sort-order * K]
where K is some number > average
number of times you expect the list to
be reordered. O(N), N=number of
elements, but increases insertion
capacity by at least N*K with at least
K open slots between each exiting pair
of elements.
Then if you want to insert an element between two others its as
simple as changing its sort-order to
be one that is > the lower element and
< the upper. If there is no "room"
between the elements you can simply
reapply the "spread" algorithm (1)
presented in the previous paragraph.
The larger K is, the less often it
will be applied.
The K algorithm would be selectively
applied in the PHP script while the
choosing of the new sort-order's would
be done by the client (Javascript,
perhaps).
Have a primary key and a sortnumber for each item. If you have a php array including the primary keys, you can remove items and insert items into the array using array_splice().
// base array
$items = array( 7, 11, 9, 4, 5);
// remove item 11
array_splice($items, array_search(11), 1);
// insert 11 before item 4
array_splice($items, array_search(4), 0, 11);
// input now contains 7, 9, 11, 4, 5
Then loop through the array and update sorting with primary keys
$i = 0;
foreach($items as $item) {
// UPDATE item_table SET sorting = '$i' WHERE id = '$item';
i++;
}
Just add another column. Call it order.
You have the order of rows and each row has an id or primary key. Just go through your rows one at a time, and set the order as you go. So:
UPDATE item_table SET order = 0 WHERE id="fred";
UPDATE item_table SET order = 1 WHERE id="larry";
UPDATE item_table SET order = 2 WHERE id="john";
UPDATE item_table SET order = 3 WHERE id="sydney";
I am sure there are trickery ways of doing this mathematically, but sometimes the simple answers are best.
Then when you make a query add SORT BY order.

Categories