Create Array from comma separated field [duplicate] - php

This question already has answers here:
Split a comma-delimited string into an array?
(8 answers)
Closed 1 year ago.
Hi I am looking for someone to answer what is probably an easy question.
At the moment I have two tables "procedures" and "Job Roles", the idea is that I want to be able to create a child table that links which procedures apply to which job roles. At the moment this is done with two tables, by creating a record in the procedure table and then creating subsequent child records in a table called "procedures_jobtitles" which is just a one to many link table.
I am exploring the idea of having a field in the procedures table that is called "applies to", which would be a drop down box presented as check boxes, the idea is that when i create a procedure, on the add/edit page there is a separate tab where this field is displayed, this would display all job roles, so that the user could just tick the ones that apply.
My problem is by doing it this way the field value is stored as (1,2,5,10,11,12) where those numbers represent foreign keys to the job descriptions table. What I would like is to take the "applies to" field and turn it into an array and extract each value that is separated by a comma, so for the above example it would give me a result of:
1
2
5
10
11
12
I can then run a foreach query and insert these records into the link table by an event after saving. The idea behind this is if you have 1 or 2 job descriptions, manually adding to the child table isnt a problem, however when you have 20 or so job titles it becomes much more time consuming. Ive tried hitting google for this, but im afraid my basic understanding of arrays is limited so I dont know what to look for.
Any help using example fields ive given, would be much appreciated

Use explode()
e.g.
<?php
$mystring = "1,2,5,10,11,12";
$myarray = explode(",",$mystring);
//Output each element from $myarray:
foreach($myarray as $item)
{
echo $item."<br>";
//or do something else, e.g. insert these records into the link table
}

Related

PHP: Best Way To Determine Position In Array [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
What I Wish To Implement
My site does a nightly API data fetch, inserting 100,000+ new entries each night. To save space, each field name is in a seperate table with an allocated ID saving around 1,027 bytes per data set, 2.5675MB approx per night and just under a gigabyte over the course of a year, however this is set to increase.
For each user, a JSON file is requested containing the 112 entries to be added. Instead of checking my table for each name ID, I feel to save time, it would be best to create an array whereas the position in the array will be the ID, so lets use some random vegetable names;
Random List Of Vegetables
"Broccoli", "Brussels sprouts", "Cabbage", "Calabrese", "Carrots", "Cauliflower", "Celery", "Chard", "Collard greens", "Corn salad", "Endive", "Fiddleheads (young coiled fern leaves)", "Frisee", "Fennel"
When I create the insert via my PHP classes, I use the following;
$database->bind(':veg_name', VALUE);
Question
What would be the best method to quickly check what position $x is within the array?
As an alternative solution to matching the entries in PHP (which might at some point run into time and/or memory problems):
The general idea is to let the database to the work. It is already optimized (index structures) to match entries to one another.
So following your example, the database probably has a dimensional table for the field names fields:
ID | Name
---------------------------------
0 | "Broccoli"
1 | "Brussels sprouts"
2 | "Cabbage"
Then there is the "final" table facts, which has a structure like this:
User_ID | Field_ID | Timestamp
Now a new batch of entries should be inserted. For this, we first create a temporary table temp with the following format and insert all raw entries. The last column Field_ID will stay empty for now.
User_ID | Field_Name | Timestamp | Field_ID
In a next step we match each field name with its ID using a simple SQL query:
UPDATE `temp` t
SET Field_ID=(SELECT Field_ID FROM fields f WHERE f.Name=t.Field_Name)
So now the database has done our required mapping and we can issue another query to insert the rows into our fact table:
INSERT INTO facts
SELECT User_ID, Field_ID, Timestamp FROM temp WHERE Field_ID IS NOT NULL
A small side-effect here: All rows in our temp table, that could not be matched (we didn't have the field name in our fields table), are still available there. So we could write some logic to send an error report somewhere and have someone add the field names or otherwise fix the issue.
After we are done, we should remove or at least truncate the temp table to be ready for next nights iteration.
Small remark: The queries here are just examples. You could do the mapping and insertion into your facts table in one query, but then you'd lose the "unmatched" entries or have to redo the work.
Redoing the work might not be an issue now, but you said the number of entries will increase in the future, so this might become an issue.
If you're only doing 2.5 megs/night, that's almost nothing. If you gzipped that before dragging it across, it would reduce it a lot more.
Using array positions could get tricky if you're trying to use that to match something in some other table.
That being said, every array has a numeric index as well, so you can find out what that is at any point.
Try this and you'll see:
$array = array("Broccoli", "Brussels sprouts", "Cabbage", "Calabrese", "Carrots", "Cauliflower", "Celery", "Chard", "Collard greens", "Corn salad", "Endive", "Fiddleheads (young coiled fern leaves)", "Frisee", "Fennel");
var_dump(array_keys($array));
On the array, you can also do this:
$currentKey = array_search("carrot",$array);
That will return the key for a given variable. So if you're looping through an array, you can output the key(index) and go do something else with it.
Also, gzip is a form of compression that makes your data much smaller.
If you have a list of item, e.g. an array containing only strings that represent your values, you can use foreach with a key-value ($users as $index => $user) method instead of just a $users as $user like following :
$users = ["Broccoli", "Brussels sprouts", "Cabbage", "Calabrese", "Carrots", "Cauliflower", "Celery", "Chard", "Collard greens", "Corn salad", "Endive", "Fiddleheads (young coiled fern leaves)", "Frisee", "Fennel"];
foreach( $users as $index => $name ) {
echo "about to insert $name which is the #$index..." . PHP_EOL;
}
Which will echo :
about to insert Broccoli which is the #0...
about to insert Brussels sprouts which is the #1...
about to insert Cabbage which is the #2...
about to insert Calabrese which is the #3...
about to insert Carrots which is the #4...
about to insert Cauliflower which is the #5...
about to insert Celery which is the #6...
about to insert Chard which is the #7...
about to insert Collard greens which is the #8...
about to insert Corn salad which is the #9...
about to insert Endive which is the #10...
about to insert Fiddleheads (young coiled fern leaves) which is the #11...
about to insert Frisee which is the #12...
about to insert Fennel which is the #13...
Live-example available here : https://repl.it/Jpwk
Like #m13r asked, how would an index be useful in your case ?

Best performance for tags in mysql/php [duplicate]

This question already has answers here:
Is storing a delimited list in a database column really that bad?
(10 answers)
Closed 5 years ago.
I have one table with items and one table with tags that can be linked to the items. Should I create a table where I store the relations between them or can I store the tag ids right in the item table like a column with "1,52,375" (tag ids).
I would in most cases lean towards a relation table, but I will mostly add one single tag per item and at the most 10 so I wonder if it's worth it.
If going with the relation table will I need a "loop-in-loop" where I make one query per item to fetch the tags. It seems like a lot of queries or is there a different solution?
I could also fetch all the items and tags separately in two queries and link them with php. Also loop in loop, but less database queries.
What do you think? Thanks!
I've had this issue before and my current best solution is to have the tag table and a column for the tags separated by spaces (spaces in actual tags are replaced with #). Then use MySQL MATCH AGAINST to perform a natural language search for the tag you need in the tag column, the # character will be ignored by match against so it's not an issue. This has worked very well for me so far.

Getting trouble in assigning id value in database in php [duplicate]

This question already has answers here:
auto increment primary leaving gaps in counting
(5 answers)
Closed 7 years ago.
i am making s simple registration page using php and mysql database.
id column of Table is AUTO INCREAMENTED
Registration Process working well i.e., data is getting Inserted in database.
currently i have 3 records in my table.
like
Raghvendra
Surendra
mohit
Now My Problem is:
When i deleted The 3rd Record i.e
mohit
My database looks like
Raghvendra
Surendra
Now, When I add another Record, my table looks like
Raghvendra
Surendra
4.varun
What is want is like
Raghvendra
Surendra
varun
sorry for my english..Help me!
Don't worry about the gaps. Either you need a unique number for each person, in which case, reusing 3 is a bad idea (does it refer to Varun or Mohit?) or you're only concerned with the names, and you can use CSS (an ordered list) to number them on the webpage when they're displayed.
It's generally very useful to preserve the order in which people are added to a database, and trying to "fill in the gaps" prevents that.
Also, remember there's no guarantee that for every user you delete, leaving a gap, there will be a new user available to fill it.
The harsh answer is to stop caring what the id is (it's really just an internal unique identifier, so no need to show it to the user).
If you are displaying a listing to the user, just use an <ol> element.
echo '<ol>';
while ($row = $results->fetch_row()) {
echo '<li>' . $row->name . '</li>';
}
echo '</ol>';
That will render the results are you expected, but you really should just treat the id as an internal thing and not worry about its actual value.

Many to many vs one row [duplicate]

This question already has answers here:
Many database rows vs one comma separated values row
(4 answers)
Closed 8 years ago.
I'm interested how and why many to many relationship is better than storing the information in one row.
Example: I have two tables, Users and Movies (very big data). I need to establish a relationship "view".
I have two ideas:
Make another column in Users table called "views", where I will store the ids of the movies this user has viewed, in a string. for example: "2,5,7...". Then I will process this information in PHP.
Make new table users_movies (many to many), with columns user_id and movie_id. row with user_id=5 and movie_id=7 means that user 5 has viewed movie 7.
I'm interested which of this methods is better and WHY. Please consider that the data is quite big.
The second method is better in just about every way. Not only will you utilize your DBs indexes to find records faster, it will make modification far far easier.
Approach 1) could answer the question "Which movies has User X viewed" by just having an SQL like "...field_in_set(movie_id, user_movielist) ...". But the other way round ("Which user do have viewed movie x") won't work on an sql basis.
That's why I always would go for approach 2): clear normalized structure, both ways are simple joins.
It's just about the needs you have. If you need performance then you must accept redundancy of the information and add a column. If your main goal is to respect the Normalization paradigma then you should not have redundancy at all.
When I have to do this type of choice I try to estimate the space loss of redundancy vs the frequency of the query of interest and its performance.
A few more thoughts.
In your first situation if you look up a particular user you can easily get the list of ids for the films they have seen. But then would need a separate query to get the details such as the titles of those movies. This might be one query using IN with the list of ids, or one query per film id. This would be inefficient and clunky.
With MySQL there is a possible fudge to join in this situation using the FIND_IN_SET() function (although a down side of this is you are straying in to non standard SQL). You could join your table of films to the users using ON FIND_IN_SET(film.id, users.film_id) > 0 . However this is not going to use an index for the join, and involves a function (which while quick for what it does, will be slow when performed on thousands of rows).
If you wanted to find all the users who had view any film a particular user had viewed then it is a bit more difficult. You can't just use FIND_IN_SET as it requires a single string and a comma separated list. As a single query you would need to join the particular user to the film table to get a lot of intermediate rows, and then join that back against the users again (using FIND_IN_SET) to find the other users.
There are ways in SQL to split up a comma separated list of values, but they are messy and anyone who has to maintain such code will hate it!
These are all fudges. With the 2nd solution these easy to do, and any resulting joins can easily use indexes (and possibly the whole queries can just use indexes without touching the actual data).
A further issue with the first solution is data integretity. You will have to manually check that a film doesn't appear twice for a user (with the 2nd solution this can easily be enforced using a unique key). You also cannot just add a foreign key to ensure that any film id for a user does actually exist. Further you will have to manually ensure that nothing enters a character string in your delimited list of ids.

Keeping track of dynamically generated form elements and passing them as POST variables

I have a page that retrieves records from 1 table in a database when a certain condition is met.
What I want to achieve is to provide the use to with an opportunity to update each record displayed using text boxes.
I am having trouble interpreting what logic to proceed with after the user hits the 'submit' button.
Normally, if I'm updating one record (or a static number of records), I will use the apporpriate amount of SQL statements.
Since the amount of records are dynamically generated, what is the best way to update all at once? How would I know which records were retrieved in the first place to update?
FOR EXAMPLE:
OK, We have a table with student ids (ID), names (SNAME), subjects (SUBJ), grade for each subject (GRADE) and general remarks (COMMENTS).
I want to retrieve information about all students that got an 'A', and write UNIQUE congratulatory remarks for each student (such as 'good job', or 'congratulations', or etc.)
I'd retrieve the records and lay them out on the page, with a text box next to each student record for the comments to be entered. Because I don't know how many text boxes to make, I give the text boxes dynamically generated names using the student ID. The user now enters unique comments for each student, and clicks on submit.
Now, how am I supposed to update these records with the values entered in each text box?
I wouldn't know which students were retrieved in the first place - how would I know what names to use? I'm trying to avoid having to execute the query again after submitting - but is there any other way?
Hope this question was not too confusing.
thanks
Further expanding earlier answers:
You need a loop (e.g. foreach) to display and save the textareas. If the names of the textareas include the students ID, you don't need to know the name, because the text is inserted to the database by the primary key (the students ID). You may name your form-elements as array, to iterate over them, for example (where the numbers are the IDs):
<textarea name="comment[2345234]"></textarea>
<textarea name="comment[8957485]"></textarea>
Read it out as described by #evan:
foreach((array)$_POST['comment'] as $studentId => $studentComment)
{
var_dump($studentId, $studentComment);
}
And if you implement this whole thing as self-requesting form (Affenformular in german), you may also use just one single loop to save and output the textareas.
"I don't think you're understanding what I'm trying to ask." Maybe you don't understand the answers, even you stated it. You don't need a students name to save a database record. But if you really want to submit it, you may also use hidden inputs.
Use foreach() to find the values you care about, put them in an array, and process the array.
Expanding on #Ignacio's answer to make it more easily understandable:
foreach($_POST as $name_of_input => $value_of_input)
{
// do stuff - here is something so you can see the results after the submit
echo "$name_of_input :: $value_of_input <br>";
}

Categories