Grabbing data from SQL column and splitting it to populate function - php

If I grab data from a column in my database called image_store such as:
/web/images/data/firstImage.png
/web/images/data/secondImage.png
/web/images/data/thirdImage.png
And I want to populate a setImage function which takes the string after /data/ to set as the fileName and the string before /firstImage.png as the directory e.g:
$this->setImage('firstImage.png', '/web/images/data/')
Is there a way I can grab the needed information from the string I get back from the database?

Yes, simply use explode/implode functions and array_pop() to take image name itself:
<?php
$sqlArr = array('/web/images/data/firstImage.png', '/web/images/data/secondImage.png', '/web/images/data/thirdImage.png');
foreach($sqlArr as $fullPath){
$tmp = explode('/', $fullPath);
$imgName = array_pop($tmp);
$imgPath = implode('/', $tmp).'/';
$this->setImage($imgName, $imgPath);
}
?>
This will works with any depth of url paths.

Related

Assigned a variable and returning a value after assignation

I have the following
$basename = !empty($_POST['basename']) ? $_POST['basename'] : null;
$upload_files = array(
'/usr/path/to/dir/' . $basename,
'/usr/path/to/dir/thumbs/' . $basename
Later on, I reassigned the variable $basename, like so
$basename = 'test.jpg';
When echo like so
echo $upload_files[0];
I want to output this
'/usr/path/to/dir/test.jpg'
But obviously, it doesn't.
Is there a trick with php where this is possible, like adding & before the variable or something?
Once you include $basename into a string, PHP loses all track of it as a variable, so subsequent changes have no effect. You could make the values in $upload_files into arrays, imploding them into strings when required, and making the second element a reference to $basename:
$basename = 'file1.gif';
$upload_files = array(
array('/usr/path/to/dir/', &$basename),
array('/usr/path/to/dir/thumbs/', &$basename)
);
echo implode('', $upload_files[0]) . PHP_EOL;
$basename = 'test.jpg';
echo implode('', $upload_files[0]). PHP_EOL;
Output:
/usr/path/to/dir/file1.gif
/usr/path/to/dir/test.jpg
Demo on 3v4l.org
What is your intended use case? If you need to access each pic string, you can store them in an array, and just use the last entry for the 'current' item. Then you'd have access to search or process each if you needed it. You can concat as needed. I'd probably write a function for processing it.
$basenames = [];
// However you're retrieving the filename
array_push($basenames, "file.gif");
// Current file
concatPic(count($basenames)-1);
// To find what key you wants position
$fileIndex = array_search("what_you're_looking_for", $basenames);
concatPic($fileIndex); // To process a specific index
function concatPic($indexValue)
{
return / echo (whatever) "usr/path/..." . $basenames[$indexValue]
};
You can also write a foreach to do all of them at once as well, or even concatenate them before pushing to the array if you want.

php : convert ressource stream in file

I get a ressource stream when I use fopen on a filepath I get from my database :
<?php
$query = "SELECT filepath
FROM files
WHERE id=123";
$result = do_query($query);
/*do_query() is a personal simplification*/
$line = mysql_fetch_array($result);
$file = fopen($line['filepath'], 'r');
/*var_dump on file return "resource(51) of type (stream)"*/
?>
But I my project I need a $_FILE type... Can I convert a ressource stream in $_FILE type?
$_FILES is not a "type", it's merely an array which holds certain information about uploaded files. First of all, if you have some piece of code which is hardcoded to use $_FILES, you should probably change it to accept a generic argument instead. Meaning, instead of:
function foo() {
echo $_FILES['tmp_name']:
}
Rewrite that to:
function foo($path) {
echo $path;
}
You can then call that function and pass it any path from anywhere. In your case you'd pass it $line['filepath'] as is. You don't need to fopen it, because then you get a resource, when you currently just want a path.
If you need to "fake" the $_FILES array, you need to construct it manually:
$_FILES['foo']['name'] = '..';
$_FILES['foo']['type'] = '..';
$_FILES['foo']['size'] = '..';
$_FILES['foo']['tmp_name'] = $line['filepath'];
$_FILES['foo']['error'] = UPLOAD_ERR_OK;
But again, you'll probably want to alter whatever code is hardcoded to use $_FILES instead of this hackaround.

Getting File Name Details from Image File

I am looking for a way to grab details from a file name to insert it into my database. My issue is that the file name is always a bit different, even if it has a pattern.
Examples:
arizona-911545_1920.jpg
bass-guitar-913092_1280.jpg
eiffel-tower-905039_1280.jpg
new-york-city-78181_1920.jpg
The first part is always what the image is about, for example arizona, bass guitar, eiffel tower, new york city followed by a unique id and the width of the image.
What I am after would be extracting:
name id and width
So if I run for example getInfo('arizona-911545_1920.jpg');
it would return something like
$extractedname
$extractedid
$extractedwidth
so I could easily save this in my mysql database like
INSERT into images VALUES ('$extractedname','$extractedid','$extractedwidth')
What bothers me most is that image names can be longer, for example new-york-city-bank or even new-york-city-bank-window so I need a safe method to get the name, no matter how long it would be.
I do know how to replace the - between the name, that's not an issue. I am really just searching for a way to extract the details I mentioned above.
I would appreciate it if someone could enlighten me on how to solve this.
Thanks :)
One of the simplest way in this case is to use regexp, for example:
preg_match('/^(\D+)-(\d+)_(\d+)/', $filename, $matches);
// $matches[1] - name
// $matches[2] - id
// $matches[3] - width
This is the main Idea.
Let's pick a file first.
Filename will be "bass-guitar-913092_1280.jpg"
First of all we will Split this with explode, to dot( . ) in variable $Temp
This will give us an Array of bass-guitar-913092_1280 and jpg
We will choose to have the first Item of the array to continue since is the name we are interested in so we will get it with $Temp[0]
After this we will Split it Again this time to ( _ ).
Now we will have an array of bass-guitar-913092 and 1280
The Second value of the Array is what We need so we will pick it with $Temp[1]
The Last part is simple as the others, We will now Split the file name $Temp[0] with ( - ) We will get the Last value of it which is the id $Temp[count($Temp)-1] and we will remove this from the array list, and Connect everything else with implode and the delimeter we want
Now we can use also the Function ucwords to Capitalize every first letter of each word on the main name.
In the following code, there are 2 ways of getting the name, one with lowercase letters, and one with uppercase first letters of each word, uncomment what you want.
Edited Code as a Function
<?php
function ExtractFileInfo($fileName) {
$Temp = explode(".",$fileName);
$Temp = explode("_",$Temp[0]);
$width = $Temp[1];
$Temp = explode("-",$Temp[0]);
$id = $Temp[count($Temp)-1];
unset($Temp[count($Temp-1)]);
// If you want to have the name with lowercase letters Uncomment the Following:
//$name = implode(" ",$Temp);
// If you Want to Capitalize every first letter of the name Uncomment the Following:
//$name = ucwords(implode(" ",$Temp));
return array($name,$id,$width);
}
?>
This will return an Array of 3 Elements Name, Id and Width
Extracting the data you are looking for would be best via a regex pattern like the following:
(.+)-(\d+_(\d+))
Example here: https://regex101.com/r/oM5bS8/2
preg_match('(.+)-(\d+_(\d+))',"<filename>", $matches);
$extractedname = $matches[1];
$extractedid = $matches[2];
$extractedwidth = $matches[3];
EDIT - Just reread the question and you are looking for extraction techniques not how to post the image from a page to your backend. I will leave this here for reference.
When you post files via a form in html to a PHP backend there are few items that are needed.
1) You need to ensure that your form type is multi-part so that it knows to pass the files along.
<form enctype="multipart/form-data">
2) Your php backend needs to iterate over the files and save them accordingly.
Here is a sample of how to iterate over the files that are being submitted.
foreach($_FILES as $file) {
$n = $file['name'];
$s = $file['size'];
if (!$n) continue;
echo "File: $n ($s bytes)";
}

Create Files Automatically using PHP script

I have a project that needs to create files using the fwrite in php. What I want to do is to make it generic, I want to make each file unique and dont overwrite on the others.
I am creating a project that will record the text from a php form and save it as html, so I want to output to have generated-file1.html and generated-file2.html, etc.. Thank you.
This will give you a count of the number of html files in a given directory
$filecount = count(glob("/Path/to/your/files/*.html"));
and then your new filename will be something like:
$generated_file_name = "generated-file".($filecount+1).".html";
and then fwrite using $generated_file_name
Although I've had to do a similar thing recently and used uniq instead. Like this:
$generated_file_name = md5(uniqid(mt_rand(), true)).".html";
I would suggest using the time as the first part of the filename (as that should then result in files being listed in chronological/alphabetic order, and then borrow from #TomcatExodus to improve the chances of the filename being unique (incase of two submissions being simultaneous).
<?php
$data = $_POST;
$md5 = md5( $data );
$time = time();
$filename_prefix = 'generated_file';
$filename_extn = 'htm';
$filename = $filename_prefix.'-'.$time.'-'.$md5.'.'.$filename_extn;
if( file_exists( $filename ) ){
# EXTREMELY UNLIKELY, unless two forms with the same content and at the same time are submitted
$filename = $filename_prefix.'-'.$time.'-'.$md5.'-'.uniqid().'.'.$filename_extn;
# IMPROBABLE that this will clash now...
}
if( file_exists( $filename ) ){
# Handle the Error Condition
}else{
file_put_contents( $filename , 'Whatever the File Content Should Be...' );
}
This would produce filenames like:
generated_file-1300080525-46ea0d5b246d2841744c26f72a86fc29.htm
generated_file-1300092315-5d350416626ab6bd2868aa84fe10f70c.htm
generated_file-1300109456-77eae508ae79df1ba5e2b2ada645e2ee.htm
If you want to make absolutely sure that you will not overwrite an existing file you could append a uniqid() to the filename. If you want it to be sequential you'll have to read existing files from your filesystem and calculate the next increment which can result in an IO overhead.
I'd go with the uniqid() method :)
If your implementation should result in unique form results every time (therefore unique files) you could hash form data into a filename, giving you unique paths, as well as the opportunity to quickly sort out duplicates;
// capture all posted form data into an array
// validate and sanitize as necessary
$data = $_POST;
// hash data for filename
$fname = md5(serialize($data));
$fpath = 'path/to/dir/' . $fname . '.html';
if(!file_exists($fpath)){
//write data to $fpath
}
Do something like this:
$i = 0;
while (file_exists("file-".$i.".html")) {
$i++;
}
$file = fopen("file-".$i.".html");

how to insert value in a particular location in csv file using php

Is it possible to write at a particular location in a CSV file using PHP?
I don't want to append data at the end of the CSV file. But I want to add data at the end of a row already having values in the CSV.
thanks in advance
No, it s not possible to insert new data in the middle of a file, due to filesystem nature.
Only append at the end is possible.
So, the only solution is to make another file, write a beginning part of source, append a new value, and then append the rest of the source file. And finally rename a resulting file to original name.
There you go. Complete working code:
<?php
//A helping function to insert data at any position in array.
function array_insert($array, $pos, $val)
{
$array2 = array_splice($array, $pos);
$array[] = $val;
$array = array_merge($array, $array2);
return $array;
}
//What and where you want to insert
$DataToInsert = '11,Shamit,Male';
$PositionToInsert = 3;
//Full path & Name of the CSV File
$FileName = 'data.csv';
//Read the file and get is as a array of lines.
$arrLines = file($FileName);
//Insert data into this array.
$Result = array_insert($arrLines, $PositionToInsert, $DataToInsert);
//Convert result array to string.
$ResultStr = implode("\n", $Result);
//Write to the file.
file_put_contents($FileName, $ResultStr);
?>
Technically Col. Shrapnel's answer is absolutely right.
Your problem is that you don't want to deal with all these file operations just to change some data. I agree with you. But you're looking for the solution in a wrong level. Put this problem in a higher level. Create a model that represents an entity in your CSV database. Modify the model's state and call its save() method. The method should be responsible to write your model's state in CSV format.
Still, you can use a CSV library that abstracts low level operations for you. For instance, parsecsv-for-php allows you to target a specific cell:
$csv = new parseCSV();
$csv->sort_by = 'id';
$csv->parse('data.csv');
# "4" is the value of the "id" column of the CSV row
$csv->data[4]['firstname'] = 'John';
$csv->save();

Categories