In a PHP while loop, I have the following:
$sql = mysqli_query($conn,"SELECT * FROM stock ORDER BY partnumber");
$productCount = mysqli_num_rows($sql);
if ($productCount > 0) {
while($row = mysqli_fetch_array($sql)){
$id = $row["id"];
$partnumber = $row["partnumber"];
$description = $row["description"];
$price = $row["listprice"];
$availability = $row["availability"];
$image = "path/$partnumber.jpg";
if(!file_exists($image)) { //substitute image if one does not exist
$image = "path/no-image.jpg";
}
When displaying the images in a table, I have:
<img src="'.$image.'" alt="'.$partnumber.'" />
It works ok with exact matches.
The problem is, many of the images contain lower case x in the filename as a character wildcard.
How can I get these image filenames containing x to display with the partnumbers containing explicit characters in their filenames?
Example filename: AB2Dxxx.jpg
Example partnumber: AB2DTUV
I hope this will help - I've had to adapt it to run locally, but it uses glob and assumes that the wildcards are all at the end of the string, so the filename can step back until a match is found.
The execution path has a folder called images, which will contain our theoretical part images. In lieu of a database, I've defined a simple key/value array containing my test results (it looks like you only rely on the partnumber, so that's all I've defined...).
The images directory contains two files: ABCDEF.jpg and ABCxxx.jpg.
$parts = array( array( "partnumber"=> "ABCDEF" ),
array( "partnumber"=> "ABDCEF" ),
array( "partnumber"=> "ABCDDD" ) );
foreach($parts as $part) {
$partnumber = $part["partnumber"];
$next_pn = $partnumber;
$pn_len = strlen($partnumber);
echo $partnumber." is the part number<br>-------------<br>";
while(strlen($next_pn) > 0 )
{
$image = null;
foreach (glob("images/".$partnumber."*.jpg", GLOB_NOSORT) as $filename) {
$image = $filename;
echo $filename . " matches " . $partnumber."<br>";
}
if($image) {
echo "<br>";
break;
}
$next_pn = substr($next_pn, 0, -1);
$partnumber = str_pad($next_pn, $pn_len, "x");
}
}
This outputs
ABCDEF is the part number
-------------
images/ABCDEF.jpg matches ABCDEF
ABDCEF is the part number
-------------
ABCDDD is the part number
-------------
images/ABCxxx.jpg matches ABCxxx
As you can see, it will basically take a filename and check for a match - if none is found, it takes off a character and replaces it with an x, then checks again. In this case:
ABCDEF matches ABCDEF.jpg instantly;
ABDCEF doesn't match any of the files, and;
ABCDDD matches ABCxxx.jpg on the fourth loop (first checks for ABCDDD, second ABCDDx, third ABCDxx, fourth matches on ABCxxx).
It isn't perfect and might need a bit more work, but it seems like it would do what you're looking to do.
P.S. glob has a lot of options - I've used NOSORT as a flag which tends to help it run a bit quicker when there are lots of files to hunt through.
http://php.net/manual/en/function.glob.php
Related
I have a folder of images that I am trying to change to be the date and time the picture was taken. I managed to make it work for the most part, however if the image has the same DateTimeOriginal (to the second), the subsequent images are deleted and replaced with the last one. This is a problem when I use burst on my camera.
I am trying to have the code add "_1" after each file name, unless the file name exists, then I want the "_1" to increase by 1. So far, the code I have will catch the first duplicate name and work properly, but every other matching filename after just deletes the file before it that has the same name (which was just renamed by the code).
In case it makes a difference, I am using XAMPP to run the PHP code in a local directory on my windows 10 PC, but I do test it online as well and have the same outcome.
The following is the code I have come up with by piecing together other code that I have found, and then attempting to customize it. I have a general understanding of PHP through trial and error, but have no education. I feel like I should be using a "while" statement while(file_exists('pictures/'.$timestamp.'_'.$count.'.jpg')) instead of or in conjunction with the current if statement I have if (file_exists('pictures/'.$timestamp.'_'.$count.'.jpg'))
The entire code I am using is here:
<?php
$count=1;
$handle = opendir(dirname(realpath(__FILE__)).'/pictures/');
while($file = readdir($handle)){
if($file !== '.' && $file !== '..'){
date_default_timezone_set('America/Edmonton');
$dirloc = "pictures/$file";
$newdirloc = "NewPictures/$file";
$exif_data = exif_read_data ($dirloc, $file, 0, true);
$exifString = $exif_data['DateTimeOriginal'];
$exifPieces = explode(":", $exifString);
$newExifString = $exifPieces[0] . "-" . $exifPieces[1] . "-" . $exifPieces[2] . ":" . $exifPieces[3] . ":" . $exifPieces[4];
$exifTimestamp = strtotime($newExifString);
$timestamp = date("y-m-d_H-i-s", $exifTimestamp);
if (file_exists('pictures/'.$timestamp.'_'.$count.'.jpg')) {
$ExistingFile = 'pictures/'.$timestamp.'_'.$count.'.jpg';
$delimiters = ['-', '_', '.'];
$newStr = str_replace($delimiters, $delimiters[0], $ExistingFile);
$NamePieces = explode("-", $newStr);
$count = $NamePieces[6];
++$count;
echo ($file.' has now been changed to '.$timestamp.'_'.$count.'.jpg (Increased count from existing file)<br>');
rename('pictures/'.$file, 'pictures/'.$timestamp.'_'.$count.'.jpg');
}
else {
echo ($file.' has now been changed to '.$timestamp.'_1.jpg (Unique File)<br>');
rename('pictures/'.$file, 'pictures/'.$timestamp.'_1.jpg');
}
}
}
?>
Thanks for helping this newbie figure this out!
Edit:
I think I've narrowed it down to a simpler question.
If it is possible to see if $ANY_NUMBER is in fact any number, what would I say $ANY_NUMBER is = to? With this change, I should be able to get rid of the count=1 at the start, and if it is true that it is any number in that [6] spot, than I should be able to say that count= that [6] spot. Does that make sense?
if (file_exists('pictures/'.$timestamp.'_'.$ANY_NUMBER.'.jpg')) {
$ExistingFile = 'pictures/'.$timestamp.'_'.$ANY_NUMBER.'.jpg';
$delimiters = ['-', '_', '.'];
$newStr = str_replace($delimiters, $delimiters[0], $ExistingFile);
$NamePieces = explode("-", $newStr);
$count = $NamePieces[6];
++$count;
echo ($count);
}
I got a bit of a complex problem. At work we have to count our inventory every month. This is done with a scanner. At each location there can be up to 100 different items. Every item, even the same kind have to be scanned. When each location has been scanned, we print out the list of scanned items. The problem is that each scan has its own line in the txt file (it done not add/subtract multiple counts of the same item)
As the vendor of our system is notoriously slow implementing new functions I thought about a php script that does the following:
1: read every line from the txt file
2: add/substract the count of the same item
3: print out a list with the item number and count.
The txt file is as following:
01234+000001N
Where the first 5 digits is the item number. As it is possible to add and substract the next symbol is + or - then the next 5 digits is the count and the N is the "eol"
So somehow I have to put it all in some sort of array and the sort it by item number. And the add/substract and then finally print out the final list
Assuming you've loaded the file into a string, line by line, and is split by a new line, you can do the following; (read code comments)
$strTxtFile = <<<TXT
01234+000001N
01234+000001N
09876+000002N
01234+000001N
01234+000001N
09876+000002N
01234-000001N
09876+000002N
TXT;
/**
* 01234 should have 3 stock
* 09876 should have 6 stock
*/
$arrProducts = array();
$arrFileLines = explode(PHP_EOL, $strTxtFile);
foreach($arrFileLines as $strFileLine) {
//Split the lines by the action (+/-)
$arrStockAction = preg_split("/(\+|\-)/", $strFileLine, NULL, PREG_SPLIT_DELIM_CAPTURE);
$strProductCode = $arrStockAction[0]; //The first part is the product code
$strAction = $arrStockAction[1]; //The action (+/-) to the stock
$intStockAmount = (int) $arrStockAction[2]; //Cast it to an int to get the number
//Check if the product exists in our array, if not, create it with 0 stock
if( array_key_exists($strProductCode, $arrProducts) === FALSE ) {
$arrProducts[$strProductCode] = 0;
}
if($strAction === "+") {
//Add stock
$arrProducts[$strProductCode] += $intStockAmount;
} else {
//Minus stock
$arrProducts[$strProductCode] -= $intStockAmount;
}
}
print_r($arrProducts);
https://repl.it/ECrW
Similar to the other answer, maybe a little simpler:
foreach(file('/path/to/file.txt') as $line) {
$item = substr($line, 0, 5);
$sign = substr($line, 5, 1);
$qty = substr($line, 6, 6);
if(!isset($result[$item])) {
$result[$item] = $qty;
} else {
$result[$item] += $sign.$qty;
}
}
Or replace the substr() lines with:
preg_match('/(\d{5})(.)(\d{6})/', $line, $matches);
And use $matches[1], $matches[2] and $matches[3].
I just found out I had misread the txt file. The lines is as follow:
01234000001 N
And
01234000001-N
The blank space between the last number and the N represent addition and - substract
I want to get specific content of a website into an array.
I have approx 20 sites to fetch the content and output in other ways i like.Only the port is always changing (not 27015, its than 27016 or so...)
This is just one: SOURCE-URL of Content
For now, i use this code in PHP to fetch the Gameicon "cs.png", but the icon varies in length - so it isn't the best way, or? :-/
$srvip = '148.251.78.214';
$srvlist = array('27015');
foreach ($srvlist as $srvport) {
$source = file_get_contents('http://www.gametracker.com/server_info/'.$srvip.':'.$srvport.'/');
$content = array(
"icon" => substr($source, strpos($source, 'game_icons64')+13, 6),
);
echo $content[icon];
}
Thanks for helping, some days are passed from my last PHP work :P
You just need to look for the first " that comes after the game_icons64 and read up to there.
$srvip = '148.251.78.214';
$srvlist = array('27015');
foreach ($srvlist as $srvport) {
$source = file_get_contents('http://www.gametracker.com/server_info/'.$srvip.':'.$srvport.'/');
// find the position right after game_icons64/
$first_occurance = strpos($source, 'game_icons64')+13;
// find the first occurance of " after game_icons64, where the src ends for the img
$second_occurance = strpos($source, '"', $first_occurance);
$content = array(
// take a substring starting at the end of game_icons64/ and ending just before the src attribute ends
"icon" => substr($source, $first_occurance, $second_occurance-$first_occurance),
);
echo $content['icon'];
}
Also, you had an error because you used [icon] and not ['icon']
Edit to match the second request involving multiple strings
$srvip = '148.251.78.214';
$srvlist = array('27015');
$content_strings = array( );
// the first 2 items are the string you are looking for in your first occurrence and how many chars to skip from that position
// the third is what should be the first char after the string you are looking for, so the first char that will not be copied
// the last item is how you want your array / program to register the string you are reading
$content_strings[] = array('game_icons64', 13, '"', 'icon');
// to add more items to your search, just copy paste the line above and change whatever you need from it
foreach ($srvlist as $srvport) {
$source = file_get_contents('http://www.gametracker.com/server_info/'.$srvip.':'.$srvport.'/');
$content = array();
foreach($content_strings as $k=>$v)
{
$first_occurance = strpos($source, $v[0])+$v[1];
$second_occurance = strpos($source, $v[2], $first_occurance);
$content[$v[3]] = substr($source, $first_occurance, $second_occurance-$first_occurance);
}
print_r($content);
}
I'm trying to get strings from a my_sqli query that only start with a certain letter, however it always outputs the whole array. Here's my code, I'm trying to get the first value, see if it starts with the correct letter, then echo it if it does, then go on to the next.
$strSQL = "SELECT title FROM blogtable ORDER BY title ASC";
$titleResult = mysqli_query($con, $strSQL);
while($rowTitle = mysqli_fetch_array($titleResult))
{
$strTitle = $rowTitle['title'];
$subTitle = substr($strTitle,0,2);
$subNum = ord($subTitle);//This gets me the value of the first letter
if($subNum = $topLetter)//$topLetter = 65, which is capital A
{
echo $strTitle;
echo "<br>";
}
}
So the problem here is that, say if I have 3 things, and only 2 start with A, it will output all 3, but I just want the 2 that start with A.
Change your if statement.
if($subNum == $topLetter)
Explanation: Operator == test for equality and operator = is assignment operator.
I wrote a script that sends chunks of text of to Google to translate, but sometimes the text, which is html source code) will end up splitting in the middle of an html tag and Google will return the code incorrectly.
I already know how to split the string into an array, but is there a better way to do this while ensuring the output string does not exceed 5000 characters and does not split on a tag?
UPDATE: Thanks to answer, this is the code I ended up using in my project and it works great
function handleTextHtmlSplit($text, $maxSize) {
//our collection array
$niceHtml[] = '';
// Splits on tags, but also includes each tag as an item in the result
$pieces = preg_split('/(<[^>]*>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
//the current position of the index
$currentPiece = 0;
//start assembling a group until it gets to max size
foreach ($pieces as $piece) {
//make sure string length of this piece will not exceed max size when inserted
if (strlen($niceHtml[$currentPiece] . $piece) > $maxSize) {
//advance current piece
//will put overflow into next group
$currentPiece += 1;
//create empty string as value for next piece in the index
$niceHtml[$currentPiece] = '';
}
//insert piece into our master array
$niceHtml[$currentPiece] .= $piece;
}
//return array of nicely handled html
return $niceHtml;
}
Note: haven't had a chance to test this (so there may be a minor bug or two), but it should give you an idea:
function get_groups_of_5000_or_less($input_string) {
// Splits on tags, but also includes each tag as an item in the result
$pieces = preg_split('/(<[^>]*>)/', $input_string,
-1, PREG_SPLIT_DELIM_CAPTURE);
$groups[] = '';
$current_group = 0;
while ($cur_piece = array_shift($pieces)) {
$piecelen = strlen($cur_piece);
if(strlen($groups[$current_group]) + $piecelen > 5000) {
// Adding the next piece whole would go over the limit,
// figure out what to do.
if($cur_piece[0] == '<') {
// Tag goes over the limit, just put it into a new group
$groups[++$current_group] = $cur_piece;
} else {
// Non-tag goes over the limit, split it and put the
// remainder back on the list of un-grabbed pieces
$grab_amount = 5000 - $strlen($groups[$current_group];
$groups[$current_group] .= substr($cur_piece, 0, $grab_amount);
$groups[++$current_group] = '';
array_unshift($pieces, substr($cur_piece, $grab_amount));
}
} else {
// Adding this piece doesn't go over the limit, so just add it
$groups[$current_group] .= $cur_piece;
}
}
return $groups;
}
Also note that this can split in the middle of regular words - if you don't want that, then modify the part that begins with // Non-tag goes over the limit to choose a better value for $grab_amount. I didn't bother coding that in since this is just supposed to be an example of how to get around splitting tags, not a drop-in solution.
Why not strip the html tags from the string before sending it to google. PHP has a strip_tags() function that can do this for you.
preg_split with a good regex would do it for you.