storing arrays into mySQL with php explode() - php

I am making a website for a cars show, i want to store images in the database (just the URL) and what i want to do is for all the images to be added to the same cell in the table.
then at retrieval time, i want to use the explode() command in php so i can seperate each URL and use a loop to display them.
the problem i am facing it i do not know what i should use for a delimiter, i cannot use anything that can be used in windows, mac or Linux which can be used in a file name, and i am afraid of using a system reserved key and cause a problem.
i am also concerned about the data type that will hold this information, i am thinking TEXT is best here but i heard many saying it causes problem.
to be clear, the idea is:
when someone uploads 3 images, the images will be uploaded into a folder, then the names will be taken and put into 1 string (after the directories names are added) with a separator between them that then will be stored in the database.
Then, i take that string, use explode() and store the separated data in an array and use a loop to display an image with the source being the stored data in the array.
i need a special delimiter or another way... can someone help me do this or tell me another way of saving the images somehow without a potential risk! i have seen many website which uses dynamic bullet points (lists) but i was never able to get a code or even an idea of how to do them.
EDIT:
The current way i am using is having 10 rows, 1 for each image.. but the problem here is that the user will not be able to add more than 10 images, and if he has less than 10 images then there will be few empty images being displayed. (i know a solution for the empty images, but it is impossible to add more images..)

You can to use any type of
serialization(serialize, json_encode), when put your array and
deserialization(unserialize, json_decode), when want to use it.
But! I advice you to create a new table for your images, with car_id field, for example.
Then you can just join it and get it all.
It can be CarImages ('id', 'car_id', 'image_file')
Also I recommend to add foreign key constraint on CarImages.car_id->Cars.id,
then your orphaned images will cascade removed, when cars will removed.
Storing of serialized values is always bad idea.

If you can't store one row per image on a separate table for any technical debt reason, then you should json_encode the array on images paths and store the result in database.

Solution one :
Create a table called Images contains 3 columns (id,image_path,user_id) and everytime the user uploads an image insert it into this table, and in your script if you want to display the uploads for a specified user get it by the user_id :
$user_id = 1 // The specified user id;
mysqli_query($connect, "SELECT * FROM images WHERE user_id = '$user_id'");
// And Loop here trough images
Solution Two :
Inserting images paths into one column.
Table files contains 1 column called path
Inserting the values to the files table :
$array = array(
'/path/to/file/1',
'/path/to/file/2',
'/path/to/file/3'
);
foreach($array as $path) {
$path = $path . '|';
mysqli_query($connect, "INSERT INTO files (path) VALUES ('$path');
}
Now display the results :
$query = mysqli_query($connect, "SELECT path FROM files");
$row = mysqli_fetch_assoc($query);
$paths = explode('|', $row['path']);
foreach($paths as $path) {
echo $path . '<br>';
}

If you do not change your database then you should try.I think below link useful for you
json
json-encode serialize
you can use anyone.
If You design Your Tables like
Table-user
user_id
username
another table for user images
Table-images
serial_num
user_id
image_url
then you can store many images for 1 user.here user_id of images table actually the foreign key of user table's user_id.
You are using relational database so it's good for you otherwise you can use nosql database

Related

PHP CSV Import Questions

I'm working with importing CSV files into a database, and it is a multi-step process.
Here are the steps:
Step 1: User uploads a CSV file.
Step 2: User associates the data to a data type. For example, if a record in the CSV contains the following data: John,Doe,jondoe#gmailcom, the user would select firstname from a dropdown box to associate to the data value John, lastname from a dropdown box that associates to the data value Doe, and emailaddress from a dropdown box that associates to the data value johndoe#gmail.com
Step 3: Insert data into database
My questions are the following:
1./ On step 3, I would have in my possession the columns which the user chose and the original data.
Here is what the original data looks like:
$data = array(
0 => array('John','Doe','johndoe#gmail.com'),
1 => array('Foo','Bar','foobar#gmail.com')
);
And here is what my columns chosen from step 2 looks like:
$columns = array('firstname','lastname','emailaddress')
How do I create a sql query that can be like the following:
INSERT into contacts (id,firstname,lastname,emailaddress) values (null,'John','Doe','johndoe#gmailcom')
As you can see, the sql query has the columns chosen in the order that they are within the array and then subsequently the values. I was thinking that since the columns are chosen in the order of the data, I can just assume that the data is in the correct order and is associated to the specific column at that position (for example, I can assume that the data value 'John' was associated to the first position of the columns array, and vice versa).
2./ I was thinking of a possible scenario that when the user does the initial upload of the file, they could potentially send a csv file with the first record having a blank field. The problem is, I determine how many columns to have the user associate to the data based on the number of columns within a csv record. In this case, we have 2 columns and every subsequent record has 3 columns. Well, I'm not going to loop through the entire set of records to determine the correct number of columns. How do I resolve this issue? Any ideas?
EDIT
I think I figured out the answer to question 2. On the parsing of the csv file, I can get a count for each record and the highest count at the end of the parsing is my count. Seems right? Any issues with that?
To parse the data from the CSV file, look at fgetcsv. http://php.net/manual/en/function.fgetcsv.php
It'll load a line from the file and return an array of the CSV fields.
$data = array();
while (($lineFields = fgetcsv($handle)) !== false) {
$data[] = $lineFields;
}
This assumes you are using PHP5 and opened the file with $handle. In PHP4 fgetcsv needs a second parameter for max length of line to read.
For the query:
$sql = "INSERT into contacts (id," + implode(',', $columns) + ") values";
I'm not including anything after the values. You should be creating prepared statements to protect against sql injections. Also if you are using MySQL, id should be an autoincrement field and omitted from inserts (let MySQL generate it). If you are using Postgres, you'll need to create a sequence for the id field. In any case let the database generate the id for you.

PHP organize uploaded photos

I am building a PHP application that lets users upload photos. To make it manageable, a folder shall have maximum of 5000 photos. Each uploaded photo will be assigned an ID in the database, and the photo will be renamed to the ID.
How do I check if a certain folder has 5000 photos? Should I check the ID of the last row in the photo table?
Folders shall be named incrementally. eg. folder_1, folder_2, etc.
My proposed steps:
Retrieve last insert ID of photo table
(Last_insert_ID + 1) % 5000 = Some_number (The folder number it should be saved in)
Save photo to folder_some_number. If folder not exist, create new one.
Or is there a better way to do this?
I'm guessing database reads are going to be faster than file system reads like this.
You'd be better off running an sql query and getting a count per folder, grouped.
// Example Query
SELECT COUNT(file), folderId As Count FROM photos WHERE folderId IN ('1', '2') GROUP BY folder
// It would be beneficial to have a flag on the folders that would enable or disable them
// that way you're not iterating through folders that we already know are > 5k
// You would run this and have seperate query that would pull in these folder names
// and passing them to the above query.
SELECT foldername, folderId FROM folders WHERE countFlag = 0;
//Example Conditional.
if($Count > 5000):
// Over 5k Do Something
//Since were over 5k, set this folders flag to 1
// that way we arent iterating through it again
$countFlag = 1;
else:
// Under 5k Do Something else
endif;
Note: If you need actual code samples, i can whip something up real quick. The above examples leave out actual working code and are just for theory purposes. You will need to iterate through the returned rows as they are grouped by folder.
$last_id; // for example 9591
$current_folder = floor($last_id/5000);
$picture_num_in_folder = $last_id-($current_folder*5000);
if ($picture_num_in_folder == 5000)
// new dir and such (new folderid = $current_folder+1 and $picture_num_in_folder = 1)
else
// just place the picture with unique ID $last_id+1 called image_$picture_num_in_folder+1 in folder $current_folder
Don't use autoincrement ids for calculations. When you delete files, you'll get holes in your ID sequences which will throw off your math. Save the filepath to your db table. Then do a simple COUNT:
SELECT filepath, COUNT(filename) AS num FROM mytable
GROUP BY filepath;
You can save new files to filepaths where num < 5000.
Using the insert ID might not be very accurate, as there a number of error conditions that can cause an ID to be "skipped". You could store the folder number in a separate column, called "folder_number" or similar. That way you can get the highest folder number, and then do a count on the number of records in that folder, if it's less than 5000, add it in the same folder, otherwise run your logic to increment the folder count (creating the physical folder at the same time).
That should be faster than using the file system to check, which could be quite slow for the volume of files you're talking about.
Let me suggest another approach:
Use a hash on the picture's ID and use the first few characters as a path for example,
lets assume the image ID is 1 for which the hash is c4ca4238a0b923820dcc509a6f75849b.
Create the directory structure /rootpath/images/c/4/c/ and in it save the image.
You can use mkdir() to create nested directories like mkdir( '/dir/c/4/c/', 0777, true );.
This way you automatically distribute the load across many folders and the ID itself is the path.
If my memory serves, WordPress uses something similar...
if you want to organize your folders and files this way, you dont need to check if the folder has 5000 files, just assign the files to the corresponding folder.
If there are less than 5000 files in a x folder that should be full (because of the last ID is bigger than 5000*x) that means that some images have been removed. You can't reasign that ID to a row in your database so you can't refill the space of the removed files.

How to store configuration variables in mysql?

M'y script's variables are currently stored in a php File as an array. I want to store them in mysql database, however I don't if I should store them as rows or columns. If I use columns it would be easier to retrieve them (only one query), but if I have too many variables the page would have to scroll horizontally and I think it would be hard to find data in phpmyAdmin. If I use rows then how would I retrieve all of them using a single query and store them in the $config array?
Any ideas or suggestions?
Create config table, with 2 columns
Name | Value
and select it with
SELECT * FROM config
so it will look like
Name | Value
offline | 1
message | Hello guys! This is my custom message
to get them into $config, use
$result = (mysql_query("SELECT * FROM config"));
while($row = mysql_Fetch_assoc($result){
$config[$result['Name']] = $result['Value'];
}
that's it!
Depends.. Are the variables user-based? Do you need to search them? One way to store is in a serialized format (string data in a text field) -- this will suffice if you don't need to search the variables. Otherwise, just store one row per (user-)key-value combination.

store more than one value into a db field to be retrieved as separate values

Is it possible to store more than one value and query the database and assign each value as a separate entity?
For example, I have a database with a column wallpaper can I store say this into it.
wall_1.png, wall_2.png, wall_3.png
and then query the database and pull out 3 different variables that hold the wallpaper name.
so I'd have $defaultWall = "wall_1.png" $wall2 = "wall_2.png" $wall3 = "wall_3.png" <-- being pulled from the database.
also I have a table called settings, the user can set all their settings here. One column is for their wallpaper preference for their profile. I would like for them to have a series of uploaded wallpapers on hand if they choose to change later on. So by doing this I wanted to store an array of wallpaper urls into the db and have a tiny image preview gallery pull each wallpaper for processing and resizing from the database.
Yes, you can. But more than one value in table field doesn't satisfy to the Normalization Forms.
Try to create one table with wallpapers for this row.
The correct way, from DDL logic, is to define another table for wallpaper images, which have foreign keys that link them to the row of that table which has the Wallpaper column in your case.
If you don't find any reason to do so, and you ARE using only PHP, use serialize and unserialize php functions to access that data from the field. You can store any data structures that way.
Take a look at the expand() function in PHP!
http://www.php.net/manual/en/function.explode.php
Note
I don't think this is the best way to handle such values, if you want to be able to link any amount of wallpapers (or none) to an object I would choose to use another table.
create table tblMain (ItemId, Name, etc)
create table tblWallpapers (WallpaperId, WallpaperName)
create table tblMainUsesWallpapers (Wallpaperid, ItemId)
then just select the values like so:
select * from tblWallpapers w
inner join tblMainUsesWallpapers muw
on w.WallpaperId = muw.WallpaperId
inner join tblMain m
on muw.ItemId = m.ItemId
where m.ItemId = x

php mysql - document retrieveal and display

I built a document upload admin screen, where my client can browse and upload pdf documents to a mysql dbase.
I have two separate tables for the Agendas, and one for Minutes. both have separate table names "upload" and "upload_mins".
on the index.php page, I have the page fetch each row of the database, and display all of the valid documents on a "download" page.
I have come a across a problem.
Each dbase is set to increment ID. now that there is two databases, they are coming to utilize the same ID.
so I am pulling from the Agenda table:
http://www.example.com/clerk.php?ID=77
and I am pulling from the Minutes table also:
http://www.example.com/clerk.php?ID=77
and they happen to have the same increment ID.
Is there some way to avoid this? Can I add a field parameter to the minutes to make sure that they don't have the same URL when pulling documents?
Create a integer field, or txt field?
i.e. http://www.example.com/clerk.php?ID=77&min=yes
If these are just documents, you could store them in a single table but have a column called type that differentiates between minutes and agendas. That way, IDs will be unique.
You could also extend the types column be a foreign key to a types table, so you can extend it to include additional document types such as spreadsheets in the future easily.
This would also aid the front-end display, as you would only need one query to fetch the documents within a batch or timeframe, but add them to differing arrays. For example:
// get the last 20 uploaded documents
$sql = "SELECT * FROM documents ORDER BY created DESC LIMIT 0,20";
$res = mysql_query($sql);
while ($doc = mysql_fetch_object($res)) {
$type = $doc->type;
if (!isset($docs[$type]) || !is_array($docs[$type])) {
$docs[$type] = array();
}
$docs[$type][] = $doc;
}
// loop over agendas
foreach ($docs['agendas'] as $agenda) {
echo '' . $agenda->title . '';
}
// loop over minutes
foreach ($docs['minutes'] as $minutes) {
echo '' . $minutes->title . '';
}
...
You say that the problem you are having is with URLs being duplicated. You have 2 different options to solve that.
The first is to create an identifier that tells you which table you want. You could have agenda.php and minutes.php, or you could have clerk.php?ID=77&type=1 and clerk.php?ID=77&type=2.
This will allow you to know which table you are referencing. This is also the approach I would recommend. There is no reason to avoid duplicate keys in different tables as long as you have a way of knowing which table you need.
The second option is to put all your records into a single table. You can then add a type column that specifies what type of document it is. You can then leave your clerk.php file alone, but need to change the upload page to populate the type column.
If you are just storing PDFs in the database, you shouldn't need anything in this table except id, type, and the document itself.

Categories