Fatal error : Using $this when not in object context in [duplicate] - php

This question already has answers here:
PHP Fatal error: Using $this when not in object context
(9 answers)
Closed 7 years ago.
I have the below function, But when I run the code make error like:
Fatal error: Using $this when not in object context in E:....
How to fix it. I replace $this-> with self:: but it failed too.
Please help in this regards,
<?php
function cehck_files()
{
$file1 = 'C:\xampp\htdocs\test\test1.php';
$file2 = 'C:\xampp\htdocs\test\test2.php';
$test = $this->compareFiles($file1,$file2,true);
$test_display = $this->toTable($test);
echo "<pre>";
print_r($test_display);
print_r($test);
echo "</pre>";
}
function compareFiles($file1, $file2, $compareCharacters = false) {
return $this->compare(file_get_contents($file1),file_get_contents($file2),$compareCharacters);
}
function compare($string1, $string2, $compareCharacters = false) {
$start = 0;
if ($compareCharacters){
$sequence1 = $string1;
$sequence2 = $string2;
$end1 = strlen($string1) - 1;
$end2 = strlen($string2) - 1;
} else {
$sequence1 = preg_split('/\R/', $string1);
$sequence2 = preg_split('/\R/', $string2);
$end1 = count($sequence1) - 1;
$end2 = count($sequence2) - 1;
}
// skip any common prefix
while ($start <= $end1 && $start <= $end2 && $sequence1[$start] == $sequence2[$start]) {
$start ++;
}
// skip any common suffix
while ($end1 >= $start && $end2 >= $start && $sequence1[$end1] == $sequence2[$end2]) {
$end1 --;
$end2 --;
}
// compute the table of longest common subsequence lengths
$table = self::computeTable($sequence1, $sequence2, $start, $end1, $end2);
// generate the partial diff
$partialDiff =
self::generatePartialDiff($table, $sequence1, $sequence2, $start);
// generate the full diff
$diff = array();
for ($index = 0; $index < $start; $index ++){
$diff[] = array($sequence1[$index], UNMODIFIED);
}
while (count($partialDiff) > 0) $diff[] = array_pop($partialDiff);
for ($index = $end1 + 1; $index < ($compareCharacters ? strlen($sequence1) : count($sequence1)); $index ++) {
$diff[] = array($sequence1[$index], UNMODIFIED);
}
// return the diff
return $diff;
}
function computeTable($sequence1, $sequence2, $start, $end1, $end2) {
$length1 = $end1 - $start + 1;
$length2 = $end2 - $start + 1;
// initialise the table
$table = array(array_fill(0, $length2 + 1, 0));
// loop over the rows
for ($index1 = 1; $index1 <= $length1; $index1 ++) {
// create the new row
$table[$index1] = array(0);
// loop over the columns
for ($index2 = 1; $index2 <= $length2; $index2 ++){
// store the longest common subsequence length
if ($sequence1[$index1 + $start - 1] == $sequence2[$index2 + $start - 1]) {
$table[$index1][$index2] = $table[$index1 - 1][$index2 - 1] + 1;
} else {
$table[$index1][$index2] =
max($table[$index1 - 1][$index2], $table[$index1][$index2 - 1]);
}
}
}
// return the table
return $table;
}
function generatePartialDiff( $table, $sequence1, $sequence2, $start ) {
$diff = array();
// initialise the indices
$index1 = count($table) - 1;
$index2 = count($table[0]) - 1;
// loop until there are no items remaining in either sequence
while ($index1 > 0 || $index2 > 0){
// check what has happened to the items at these indices
if ($index1 > 0 && $index2 > 0 && $sequence1[$index1 + $start - 1] == $sequence2[$index2 + $start - 1]) {
// update the diff and the indices
$diff[] = array($sequence1[$index1 + $start - 1], UNMODIFIED);
$index1 --;
$index2 --;
} elseif ($index2 > 0 && $table[$index1][$index2] == $table[$index1][$index2 - 1]) {
// update the diff and the indices
$diff[] = array($sequence2[$index2 + $start - 1], INSERTED);
$index2 --;
}else{
// update the diff and the indices
$diff[] = array($sequence1[$index1 + $start - 1], DELETED);
$index1 --;
}
}
// return the diff
return $diff;
}
function toTable($diff, $indentation = '', $separator = '<br>') {
$html = $indentation . "<table class=\"diff\">\n";
// loop over the lines in the diff
$index = 0;
while ($index < count($diff)){
// determine the line type
switch ($diff[$index][1]){
// display the content on the left and right
case UNMODIFIED:
$leftCell =
self::getCellContent(
$diff, $indentation, $separator, $index, UNMODIFIED);
$rightCell = $leftCell;
break;
// display the deleted on the left and inserted content on the right
case DELETED:
$leftCell =
self::getCellContent(
$diff, $indentation, $separator, $index, DELETED);
$rightCell =
self::getCellContent(
$diff, $indentation, $separator, $index, INSERTED);
break;
// display the inserted content on the right
case INSERTED:
$leftCell = '';
$rightCell =
self::getCellContent(
$diff, $indentation, $separator, $index, INSERTED);
break;
}
// extend the HTML with the new row
$html .=
$indentation
. " <tr>\n"
. $indentation
. ' <td class="diff'
. ($leftCell == $rightCell
? 'Unmodified'
: ($leftCell == '' ? 'Blank' : 'Deleted'))
. '">'
. $leftCell
. "</td>\n"
. $indentation
. ' <td class="diff'
. ($leftCell == $rightCell
? 'Unmodified'
: ($rightCell == '' ? 'Blank' : 'Inserted'))
. '">'
. $rightCell
. "</td>\n"
. $indentation
. " </tr>\n";
}
// return the HTML
return $html . $indentation . "</table>\n";
}
?>

You are using $this for a function which is not a method of any class.
Instead of
$test = $this->compareFiles($file1,$file2,true);
Use:
$test = compareFiles($file1,$file2,true);
Also, change
return $this->compare(file_get_contents($file1),file_get_contents($file2),$compareCharacters);
To
return compare(file_get_contents($file1),file_get_contents($file2),$compareCharacters);
And to the remaining changes in this way.

Related

Fatal error: Call to undefined method DateTime::diff()

When my code is moved from local server to live server it shows an error like this :
Fatal error: Call to undefined method DateTime::diff()
Code:
<?php
date_default_timezone_set('Asia/Calcutta');
$sFinalDate = date('Y-m-d', strtotime($sDate));
$sNow = new DateTime();
$iRemain = new DateTime( $sFinalDate.$sTime);
$iInterval = $iRemain->diff($sNow);
$sTimeCounter = $iInterval->format("%h: %i :%s ");
$sCalculate = $iInterval->format("%a:%h:%i");
?>
Though I found a number of people who ran into the issue of 5.2 and
lower not supporting this function, I was unable to find any solid
examples to get around it. Therefore I hope this can help some others:
<?php
function get_timespan_string($older, $newer) {
$Y1 = $older->format('Y');
$Y2 = $newer->format('Y');
$Y = $Y2 - $Y1;
$m1 = $older->format('m');
$m2 = $newer->format('m');
$m = $m2 - $m1;
$d1 = $older->format('d');
$d2 = $newer->format('d');
$d = $d2 - $d1;
$H1 = $older->format('H');
$H2 = $newer->format('H');
$H = $H2 - $H1;
$i1 = $older->format('i');
$i2 = $newer->format('i');
$i = $i2 - $i1;
$s1 = $older->format('s');
$s2 = $newer->format('s');
$s = $s2 - $s1;
if($s < 0) {
$i = $i -1;
$s = $s + 60;
}
if($i < 0) {
$H = $H - 1;
$i = $i + 60;
}
if($H < 0) {
$d = $d - 1;
$H = $H + 24;
}
if($d < 0) {
$m = $m - 1;
$d = $d + get_days_for_previous_month($m2, $Y2);
}
if($m < 0) {
$Y = $Y - 1;
$m = $m + 12;
}
$timespan_string = create_timespan_string($Y, $m, $d, $H, $i, $s);
return $timespan_string;
}
function get_days_for_previous_month($current_month, $current_year) {
$previous_month = $current_month - 1;
if($current_month == 1) {
$current_year = $current_year - 1; //going from January to previous December
$previous_month = 12;
}
if($previous_month == 11 || $previous_month == 9 || $previous_month == 6 || $previous_month == 4) {
return 30;
}
else if($previous_month == 2) {
if(($current_year % 4) == 0) { //remainder 0 for leap years
return 29;
}
else {
return 28;
}
}
else {
return 31;
}
}
function create_timespan_string($Y, $m, $d, $H, $i, $s)
{
$timespan_string = '';
$found_first_diff = false;
if($Y >= 1) {
$found_first_diff = true;
$timespan_string .= pluralize($Y, 'year').' ';
}
if($m >= 1 || $found_first_diff) {
$found_first_diff = true;
$timespan_string .= pluralize($m, 'month').' ';
}
if($d >= 1 || $found_first_diff) {
$found_first_diff = true;
$timespan_string .= pluralize($d, 'day').' ';
}
if($H >= 1 || $found_first_diff) {
$found_first_diff = true;
$timespan_string .= pluralize($H, 'hour').' ';
}
if($i >= 1 || $found_first_diff) {
$found_first_diff = true;
$timespan_string .= pluralize($i, 'minute').' ';
}
if($found_first_diff) {
$timespan_string .= 'and ';
}
$timespan_string .= pluralize($s, 'second');
return $timespan_string;
}
function pluralize( $count, $text )
{
return $count . ( ( $count == 1 ) ? ( " $text" ) : ( " ${text}s" ) );
}
?>
source http://php.net/manual/en/function.date-diff.php
if you using php 5.3 then there would be another issue
working above example on php>=5.3

php pagination of an array with previous and next tab

I have this array which contain around 1000 records. I want to display 20 array records per page.
$list=array(
array([title]=>"sony", [description]=>"camera"),
array([title]=>"sony", [description]=>"mobiles"),
array([title]=>"lenovo", [description]=>"laptop"),
array([title]=>"lenovo", [description]=>"mobiles")
);
I have used the following code for pagination. It is giving me a long row for pagination. Can someone help me to include previous and next code to my existing code so that my pagination will look good.
$page = isset($_REQUEST['page']) && $_REQUEST['page'] > 0 ? $_REQUEST['page'] : 1;
function display($list, $page = 1)
{
$start = ($page - 1) * 2;
$list = array_slice($list, $start, 15);
foreach ($list as $key => $val) {
echo $val['title'] . '<br/>';
echo $val['description'] . '<br/>';
echo "<br>";
}} $len = count($list);
$pages = ceil($len / 2);
if ($page > $pages or $page < 1)
{
echo 'page not found';
}
else
{
display($list, $page);
for ($i = 1 ; $i <= $pages ; $i++)
{
$current = ($i == $page) ? TRUE : FALSE;
if ($current) {
echo '<b>' . $i . '</b>';
}
else
{
?>
<?php echo $i;?>
<?php
}
}
}
Here's an example with the data array from your question.
The example
The page size is assumed to be 2 (20 in your question).
The size of the data array does not matter.
The start parameter is provided (as in your example) thru a GET parameter http://localhost/flipkart-api/fkt_offer.php?…start=index_or_page. This parameter is available in the script as $_GET['start'].
The previous and next start indices are to be calculated ($start +/- $maxpage, etc.).
To keep this example simple, I took the start index, not the page number, as parameter. But you also could use a page number and calculate the index, of course.
For the reason of brevity I omitted error checking ("what if no more items", etc.).
Code:
<?php
// The data array
$list=array(
array('title'=>"sony", 'description'=>"camera"),
array('title'=>"sony", 'description'=>"mobiles"),
array('title'=>"lenovo", 'description'=>"laptop"),
array('title'=>"lenovo", 'description'=>"mobiles")
);
// Evaluate URL
$proto = ((isset($_SERVER["HTTPS"])) && (strtoupper($_SERVER["HTTPS"]) == 'ON')) ? "https://" : "http://";
$hname = getenv("SERVER_NAME");
$port = getenv("SERVER_PORT");
if ( (($port==80)&&($proto=='http://')) || (($port==443)&&($proto=='https://')) ) { $port = ''; }
$params = '';
foreach ($_GET as $key=>$value) {
if (strtolower($key)=='start') continue;
$params .= (empty($params)) ? "$key=$value" : "&$key=$value";
}
$url = $proto . $hname . $port. $_SERVER['SCRIPT_NAME'] . '?' . $params;
// Page contents
$last = count($list)-1;
$start = (isset($_GET['start'])) ? intval($_GET['start']) : 0;
if ($start<0) $start = 0; if ($start > $last) $start = $last;
$maxpage = 2;
echo "<p>Start index = $start</p>" . PHP_EOL;
$curpage = 0;
for($xi=$start; $xi<=$last; $xi++) {
if ($curpage >= $maxpage) break;
$curpage++;
echo 'Entry ' . $curpage .
': ' . $list[$xi]['title'] .
' - ' . $list[$xi]['description'] .
'<br />' . PHP_EOL;
}
// Navigation
$prev = $start - $maxpage; if ($prev<0) $prev = 0;
$next = ( ($start+$maxpage) > $last) ? $start : $start + $maxpage;
$prev = ( ($start-$maxpage) < 0) ? 0 : $start - $maxpage;
echo '<p>Previous ';
echo 'Next</p>';
?>
Result (e.g)
Start index = 2
Entry 1: lenovo - laptop
Entry 2: lenovo - mobiles
Previous Next

automatic number increase in php based web form [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
So I have created an html form which then posts the results to a php file that overlays them on a PDF and then emails that PDF to myself and the email that was put in the form. All I want to do now is find a simple way to make it so that the PDF includes a sequential number.
For example: When the form is filled out for the first time the number 0001 is input automatically into the PDF and 0002 for the second time and so on.
Is there an easy PHP function to accomplish this?
Essentially I am creating an online invoicing form so when I do service calls I can create an invoice on the spot from a web browser which is then emailed to my office and the client.
Any help would be greatly appreciated.
For an incrementing number, you could keep a number in a database and then extract it, add 1 to it, use it, and then put it back in the DB for next time, but this seems complicated. Somebody in the comments mentioned using the timestamp, which would be done like so:
$invoicenumber = time(); //This number will always be unique
The time function works like so (copied from w3schools):
The time() function returns the current time in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT).
Since actual seconds can only go up (increment), this number will never be the same twice.
I hope this is helpful.
-Edit
You can also display this date/time in a readable format like so:
$time = time();
echo date("Y-m-d H:i:s",$time);
-Edit 2
If you want an incrementing number, you basically need a very simple database to save it, which might be as simple as a table called invoices, with a column called invoicenumber, which stores your invoice number in it. You could / probably should use this to store other invoice information in it too, so you'd have each invoice number saved (which means we want to only get the highest one)
Then your code would look like this, for each time you want to use it:
Firstly you'd have a database information file (settings.php or something similar) with your database definitions in it, which might look like this:
define('DB_HOST', 'localhost');
define('DB_USER', 'db_username');
define('DB_PASS', 'db_password');
define('DB_NAME', 'database_name');
Your code would look like this:
//Establish a mysql connection
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
//Set up a query to get the highest number
$query = "SELECT invoicenumber FROM invoices ORDER BY invoicenumber DESC LIMIT 1";
//Get the result
$result = $mysqli->query($query);
$row = $result->fetch_assoc();
//If we have a record
if($row){
//New invoice number
$invoicenumber = $row['invoicenumber']++;
//Else (database is empty, so start at the beginning)
}else{
$invoicenumber = 1;
}
//Now we have our invoice number, so do whatever you want with it
/**
* Code here to use the number
* */
//Now we wanna add the new invoice to the database, so
/**
* Add any other info to this statement if you want.
* If any of it is user submitted data, be sure to use prepared statements
* (just look at php.net's documentation on prepared statements)
* w3schools also has some nice tutorials on how to safely insert stuff
* in to a database, so check it all out :)
* */
$query = "INSERT INTO invoices(invoicenumber) VALUES($invoicenumber)";
//Execute the query
if($mysqli->query($query)){
//Show success
echo "Invoice $invoicenumber has been added to the database.";
}else{
//Show error
echo "Unfortunately we could not add invoice $invoicenumber to the database.";
}
//Now we can clear up our resources
$stmt->free_result(); $stmt->close(); $mysqli->close();
Please note: this is a very basic example. Yours will have additions and enhanced security if you are using user submitted data, so please do your homework and make sure that you fully understand each line of this code before you proceed to use it.
I do exactly the same with patient accession numbers on patient reports.
include('/home/user/php/class.pdf2text.php');
$p2t = new PDF2Text();
$p2t->setFilename($pdf);
$p2t->decodePDF();
$data = $p2t->output();
$len = strlen($data);
$pos = strpos($data,$accession);
if (pos){
$in .= "$accession,";
$checked++;
}
else{
$missingPDF += 1;echo "\n<p> <span class='bold red'>INCORRECT ACCESSION NUMBER c=$row[0] p=$row[1]</span>\n";
}
if ($checked > 0){
$in = substr($in,0,-1) . ')';
$sql = "UPDATE `Patient` SET `PDF`=1 WHERE $in";
}
pdf2text.php
class PDF2Text {
// Some settings
var $multibyte = 4; // Use setUnicode(TRUE|FALSE)
var $convertquotes = ENT_QUOTES; // ENT_COMPAT (double-quotes), ENT_QUOTES (Both), ENT_NOQUOTES (None)
var $showprogress = true; // TRUE if you have problems with time-out
// Variables
var $filename = '';
var $decodedtext = '';
function setFilename($filename) {
// Reset
$this->decodedtext = '';
$this->filename = $filename;
}
function output($echo = false) {
if($echo) echo $this->decodedtext;
else return $this->decodedtext;
}
function setUnicode($input) {
// 4 for unicode. But 2 should work in most cases just fine
if($input == true) $this->multibyte = 4;
else $this->multibyte = 2;
}
function decodePDF() {
// Read the data from pdf file
$infile = #file_get_contents($this->filename, FILE_BINARY);
if (empty($infile))
return "";
// Get all text data.
$transformations = array();
$texts = array();
// Get the list of all objects.
preg_match_all("#obj[\n|\r](.*)endobj[\n|\r]#ismU", $infile . "endobj\r", $objects);
$objects = #$objects[1];
// Select objects with streams.
for ($i = 0; $i < count($objects); $i++) {
$currentObject = $objects[$i];
// Prevent time-out
#set_time_limit ();
if($this->showprogress) {
// echo ". ";
flush(); ob_flush();
}
// Check if an object includes data stream.
if (preg_match("#stream[\n|\r](.*)endstream[\n|\r]#ismU", $currentObject . "endstream\r", $stream )) {
$stream = ltrim($stream[1]);
// Check object parameters and look for text data.
$options = $this->getObjectOptions($currentObject);
if (!(empty($options["Length1"]) && empty($options["Type"]) && empty($options["Subtype"])) )
// if ( $options["Image"] && $options["Subtype"] )
// if (!(empty($options["Length1"]) && empty($options["Subtype"])) )
continue;
// Hack, length doesnt always seem to be correct
unset($options["Length"]);
// So, we have text data. Decode it.
$data = $this->getDecodedStream($stream, $options);
if (strlen($data)) {
if (preg_match_all("#BT[\n|\r](.*)ET[\n|\r]#ismU", $data . "ET\r", $textContainers)) {
$textContainers = #$textContainers[1];
$this->getDirtyTexts($texts, $textContainers);
} else
$this->getCharTransformations($transformations, $data);
}
}
}
// Analyze text blocks taking into account character transformations and return results.
$this->decodedtext = $this->getTextUsingTransformations($texts, $transformations);
}
function decodeAsciiHex($input) {
$output = "";
$isOdd = true;
$isComment = false;
for($i = 0, $codeHigh = -1; $i < strlen($input) && $input[$i] != '>'; $i++) {
$c = $input[$i];
if($isComment) {
if ($c == '\r' || $c == '\n')
$isComment = false;
continue;
}
switch($c) {
case '\0': case '\t': case '\r': case '\f': case '\n': case ' ': break;
case '%':
$isComment = true;
break;
default:
$code = hexdec($c);
if($code === 0 && $c != '0')
return "";
if($isOdd)
$codeHigh = $code;
else
$output .= chr($codeHigh * 16 + $code);
$isOdd = !$isOdd;
break;
}
}
if($input[$i] != '>')
return "";
if($isOdd)
$output .= chr($codeHigh * 16);
return $output;
}
function decodeAscii85($input) {
$output = "";
$isComment = false;
$ords = array();
for($i = 0, $state = 0; $i < strlen($input) && $input[$i] != '~'; $i++) {
$c = $input[$i];
if($isComment) {
if ($c == '\r' || $c == '\n')
$isComment = false;
continue;
}
if ($c == '\0' || $c == '\t' || $c == '\r' || $c == '\f' || $c == '\n' || $c == ' ')
continue;
if ($c == '%') {
$isComment = true;
continue;
}
if ($c == 'z' && $state === 0) {
$output .= str_repeat(chr(0), 4);
continue;
}
if ($c < '!' || $c > 'u')
return "";
$code = ord($input[$i]) & 0xff;
$ords[$state++] = $code - ord('!');
if ($state == 5) {
$state = 0;
for ($sum = 0, $j = 0; $j < 5; $j++)
$sum = $sum * 85 + $ords[$j];
for ($j = 3; $j >= 0; $j--)
$output .= chr($sum >> ($j * 8));
}
}
if ($state === 1)
return "";
elseif ($state > 1) {
for ($i = 0, $sum = 0; $i < $state; $i++)
$sum += ($ords[$i] + ($i == $state - 1)) * pow(85, 4 - $i);
for ($i = 0; $i < $state - 1; $i++) {
try {
if(false == ($o = chr($sum >> ((3 - $i) * 8)))) {
throw new Exception('Error');
}
$output .= $o;
} catch (Exception $e) { /*Dont do anything*/ }
}
}
return $output;
}
function decodeFlate($data) {
return #gzuncompress($data);
}
function getObjectOptions($object) {
$options = array();
if (preg_match("#<<(.*)>>#ismU", $object, $options)) {
$options = explode("/", $options[1]);
#array_shift($options);
$o = array();
for ($j = 0; $j < #count($options); $j++) {
$options[$j] = preg_replace("#\s+#", " ", trim($options[$j]));
if (strpos($options[$j], " ") !== false) {
$parts = explode(" ", $options[$j]);
$o[$parts[0]] = $parts[1];
} else
$o[$options[$j]] = true;
}
$options = $o;
unset($o);
}
return $options;
}
function getDecodedStream($stream, $options) {
$data = "";
if (empty($options["Filter"]))
$data = $stream;
else {
$length = !empty($options["Length"]) ? $options["Length"] : strlen($stream);
$_stream = substr($stream, 0, $length);
foreach ($options as $key => $value) {
if ($key == "ASCIIHexDecode")
$_stream = $this->decodeAsciiHex($_stream);
elseif ($key == "ASCII85Decode")
$_stream = $this->decodeAscii85($_stream);
elseif ($key == "FlateDecode")
$_stream = $this->decodeFlate($_stream);
elseif ($key == "Crypt") { // TO DO
}
}
$data = $_stream;
}
return $data;
}
function getDirtyTexts(&$texts, $textContainers) {
for ($j = 0; $j < count($textContainers); $j++) {
if (preg_match_all("#\[(.*)\]\s*TJ[\n|\r]#ismU", $textContainers[$j], $parts))
$texts = array_merge($texts, array(#implode('', $parts[1])));
elseif (preg_match_all("#T[d|w|m|f]\s*(\(.*\))\s*Tj[\n|\r]#ismU", $textContainers[$j], $parts))
$texts = array_merge($texts, array(#implode('', $parts[1])));
elseif (preg_match_all("#T[d|w|m|f]\s*(\[.*\])\s*Tj[\n|\r]#ismU", $textContainers[$j], $parts))
$texts = array_merge($texts, array(#implode('', $parts[1])));
}
}
function getCharTransformations(&$transformations, $stream) {
preg_match_all("#([0-9]+)\s+beginbfchar(.*)endbfchar#ismU", $stream, $chars, PREG_SET_ORDER);
preg_match_all("#([0-9]+)\s+beginbfrange(.*)endbfrange#ismU", $stream, $ranges, PREG_SET_ORDER);
for ($j = 0; $j < count($chars); $j++) {
$count = $chars[$j][1];
$current = explode("\n", trim($chars[$j][2]));
for ($k = 0; $k < $count && $k < count($current); $k++) {
if (preg_match("#<([0-9a-f]{2,4})>\s+<([0-9a-f]{4,512})>#is", trim($current[$k]), $map))
$transformations[str_pad($map[1], 4, "0")] = $map[2];
}
}
for ($j = 0; $j < count($ranges); $j++) {
$count = $ranges[$j][1];
$current = explode("\n", trim($ranges[$j][2]));
for ($k = 0; $k < $count && $k < count($current); $k++) {
if (preg_match("#<([0-9a-f]{4})>\s+<([0-9a-f]{4})>\s+<([0-9a-f]{4})>#is", trim($current[$k]), $map)) {
$from = hexdec($map[1]);
$to = hexdec($map[2]);
$_from = hexdec($map[3]);
for ($m = $from, $n = 0; $m <= $to; $m++, $n++)
$transformations[sprintf("%04X", $m)] = sprintf("%04X", $_from + $n);
} elseif (preg_match("#<([0-9a-f]{4})>\s+<([0-9a-f]{4})>\s+\[(.*)\]#ismU", trim($current[$k]), $map)) {
$from = hexdec($map[1]);
$to = hexdec($map[2]);
$parts = preg_split("#\s+#", trim($map[3]));
for ($m = $from, $n = 0; $m <= $to && $n < count($parts); $m++, $n++)
$transformations[sprintf("%04X", $m)] = sprintf("%04X", hexdec($parts[$n]));
}
}
}
}
function getTextUsingTransformations($texts, $transformations) {
$document = "";
for ($i = 0; $i < count($texts); $i++) {
$isHex = false;
$isPlain = false;
$hex = "";
$plain = "";
for ($j = 0; $j < strlen($texts[$i]); $j++) {
$c = $texts[$i][$j];
switch($c) {
case "<":
$hex = "";
$isHex = true;
$isPlain = false;
break;
case ">":
$hexs = str_split($hex, $this->multibyte); // 2 or 4 (UTF8 or ISO)
for ($k = 0; $k < count($hexs); $k++) {
$chex = str_pad($hexs[$k], 4, "0"); // Add tailing zero
if (isset($transformations[$chex]))
$chex = $transformations[$chex];
$document .= html_entity_decode("&#x".$chex.";");
}
$isHex = false;
break;
case "(":
$plain = "";
$isPlain = true;
$isHex = false;
break;
case ")":
$document .= $plain;
$isPlain = false;
break;
case "\\":
$c2 = $texts[$i][$j + 1];
if (in_array($c2, array("\\", "(", ")"))) $plain .= $c2;
elseif ($c2 == "n") $plain .= '\n';
elseif ($c2 == "r") $plain .= '\r';
elseif ($c2 == "t") $plain .= '\t';
elseif ($c2 == "b") $plain .= '\b';
elseif ($c2 == "f") $plain .= '\f';
elseif ($c2 >= '0' && $c2 <= '9') {
$oct = preg_replace("#[^0-9]#", "", substr($texts[$i], $j + 1, 3));
$j += strlen($oct) - 1;
$plain .= html_entity_decode("&#".octdec($oct).";", $this->convertquotes);
}
$j++;
break;
default:
if ($isHex)
$hex .= $c;
elseif ($isPlain)
$plain .= $c;
break;
}
}
$document .= "\n";
}
return $document;
}
}

Converting Degree, Minutes, Seconds (DMS) to decimal in PHP

Currently, I'm learning to use Google Maps API. From what I read, the API require the latitude and longitude in Decimal Degree (DD).
In my database, the data is stored as DMS.
Example, 110° 29' 01.1"
I would to ask if you guys have any DMS to DD in php. And, the converter must accept from a single string like the example above.
Regards
You can try if this is working for you.
<?php
function DMStoDD($deg,$min,$sec)
{
// Converting DMS ( Degrees / minutes / seconds ) to decimal format
return $deg+((($min*60)+($sec))/3600);
}
function DDtoDMS($dec)
{
// Converts decimal format to DMS ( Degrees / minutes / seconds )
$vars = explode(".",$dec);
$deg = $vars[0];
$tempma = "0.".$vars[1];
$tempma = $tempma * 3600;
$min = floor($tempma / 60);
$sec = $tempma - ($min*60);
return array("deg"=>$deg,"min"=>$min,"sec"=>$sec);
}
?>
Here's one where you pass in the latitude,longitude in DMS values and returns the converted DMS string. Easy and simnple
function DECtoDMS($latitude, $longitude)
{
$latitudeDirection = $latitude < 0 ? 'S': 'N';
$longitudeDirection = $longitude < 0 ? 'W': 'E';
$latitudeNotation = $latitude < 0 ? '-': '';
$longitudeNotation = $longitude < 0 ? '-': '';
$latitudeInDegrees = floor(abs($latitude));
$longitudeInDegrees = floor(abs($longitude));
$latitudeDecimal = abs($latitude)-$latitudeInDegrees;
$longitudeDecimal = abs($longitude)-$longitudeInDegrees;
$_precision = 3;
$latitudeMinutes = round($latitudeDecimal*60,$_precision);
$longitudeMinutes = round($longitudeDecimal*60,$_precision);
return sprintf('%s%s° %s %s %s%s° %s %s',
$latitudeNotation,
$latitudeInDegrees,
$latitudeMinutes,
$latitudeDirection,
$longitudeNotation,
$longitudeInDegrees,
$longitudeMinutes,
$longitudeDirection
);
}
I wrote a PHP function that does what the question asks: converts a string in degrees/minutes/seconds into decimal degrees. It accepts a number of different formats for the string, and honors direction (NSEW).
Here is the code:
<?php
function convertDMSToDecimal($latlng) {
$valid = false;
$decimal_degrees = 0;
$degrees = 0; $minutes = 0; $seconds = 0; $direction = 1;
// Determine if there are extra periods in the input string
$num_periods = substr_count($latlng, '.');
if ($num_periods > 1) {
$temp = preg_replace('/\./', ' ', $latlng, $num_periods - 1); // replace all but last period with delimiter
$temp = trim(preg_replace('/[a-zA-Z]/','',$temp)); // when counting chunks we only want numbers
$chunk_count = count(explode(" ",$temp));
if ($chunk_count > 2) {
$latlng = $temp; // remove last period
} else {
$latlng = str_replace("."," ",$latlng); // remove all periods, not enough chunks left by keeping last one
}
}
// Remove unneeded characters
$latlng = trim($latlng);
$latlng = str_replace("º","",$latlng);
$latlng = str_replace("'","",$latlng);
$latlng = str_replace("\"","",$latlng);
$latlng = substr($latlng,0,1) . str_replace('-', ' ', substr($latlng,1)); // remove all but first dash
if ($latlng != "") {
// DMS with the direction at the start of the string
if (preg_match("/^([nsewNSEW]?)\s*(\d{1,3})\s+(\d{1,3})\s+(\d+\.?\d*)$/",$latlng,$matches)) {
$valid = true;
$degrees = intval($matches[2]);
$minutes = intval($matches[3]);
$seconds = floatval($matches[4]);
if (strtoupper($matches[1]) == "S" || strtoupper($matches[1]) == "W")
$direction = -1;
}
// DMS with the direction at the end of the string
if (preg_match("/^(-?\d{1,3})\s+(\d{1,3})\s+(\d+(?:\.\d+)?)\s*([nsewNSEW]?)$/",$latlng,$matches)) {
$valid = true;
$degrees = intval($matches[1]);
$minutes = intval($matches[2]);
$seconds = floatval($matches[3]);
if (strtoupper($matches[4]) == "S" || strtoupper($matches[4]) == "W" || $degrees < 0) {
$direction = -1;
$degrees = abs($degrees);
}
}
if ($valid) {
// A match was found, do the calculation
$decimal_degrees = ($degrees + ($minutes / 60) + ($seconds / 3600)) * $direction;
} else {
// Decimal degrees with a direction at the start of the string
if (preg_match("/^(-?\d+(?:\.\d+)?)\s*([nsewNSEW]?)$/",$latlng,$matches)) {
$valid = true;
if (strtoupper($matches[2]) == "S" || strtoupper($matches[2]) == "W" || $degrees < 0) {
$direction = -1;
$degrees = abs($degrees);
}
$decimal_degrees = $matches[1] * $direction;
}
// Decimal degrees with a direction at the end of the string
if (preg_match("/^([nsewNSEW]?)\s*(\d+(?:\.\d+)?)$/",$latlng,$matches)) {
$valid = true;
if (strtoupper($matches[1]) == "S" || strtoupper($matches[1]) == "W")
$direction = -1;
$decimal_degrees = $matches[2] * $direction;
}
}
}
if ($valid) {
return $decimal_degrees;
} else {
return false;
}
}
?>
Here it is on Github with test cases: https://github.com/prairiewest/PHPconvertDMSToDecimal
Solved.
<?php
function DMStoDD($input)
{
$deg = " " ;
$min = " " ;
$sec = " " ;
$inputM = " " ;
print "<br> Input is ".$input." <br>";
for ($i=0; $i < strlen($input); $i++)
{
$tempD = $input[$i];
//print "<br> TempD [$i] is : $tempD";
if ($tempD == iconv("UTF-8", "ISO-8859-1//TRANSLIT", '°') )
{
$newI = $i + 1 ;
//print "<br> newI is : $newI";
$inputM = substr($input, $newI, -1) ;
break;
}//close if degree
$deg .= $tempD ;
}//close for degree
//print "InputM is ".$inputM." <br>";
for ($j=0; $j < strlen($inputM); $j++)
{
$tempM = $inputM[$j];
//print "<br> TempM [$j] is : $tempM";
if ($tempM == "'")
{
$newI = $j + 1 ;
//print "<br> newI is : $newI";
$sec = substr($inputM, $newI, -1) ;
break;
}//close if minute
$min .= $tempM ;
}//close for min
$result = $deg+( (( $min*60)+($sec) ) /3600 );
print "<br> Degree is ". $deg*1 ;
print "<br> Minutes is ". $min ;
print "<br> Seconds is ". $sec ;
print "<br> Result is ". $result ;
return $deg + ($min / 60) + ($sec / 3600);
}
?>
If you also want to include the reference, you might want to use this function:
function DMStoDD($ref, $deg, $min, $sec)
{
$n = $deg + (($min * 60 + $sec) / 3600);
if (($ref == "S") or ($ref == "W")) {
return -$n;
} else {
return $n;
}
}
This works very well:
<?php echo "<td> $deg&#176 $min' $sec&#8243 </td>"; ?>
where deg, min and sec are the angular co-ordinates.

How to generate excerpt with most searched words in PHP?

Here is an excerpt function:
function excerpt($text, $phrase, $radius = 100, $ending = "...") {
270 if (empty($text) or empty($phrase)) {
271 return $this->truncate($text, $radius * 2, $ending);
272 }
273
274 $phraseLen = strlen($phrase);
275 if ($radius < $phraseLen) {
276 $radius = $phraseLen;
277 }
278
279 $pos = strpos(strtolower($text), strtolower($phrase));
280
281 $startPos = 0;
282 if ($pos > $radius) {
283 $startPos = $pos - $radius;
284 }
285
286 $textLen = strlen($text);
287
288 $endPos = $pos + $phraseLen + $radius;
289 if ($endPos >= $textLen) {
290 $endPos = $textLen;
291 }
292
293 $excerpt = substr($text, $startPos, $endPos - $startPos);
294 if ($startPos != 0) {
295 $excerpt = substr_replace($excerpt, $ending, 0, $phraseLen);
296 }
297
298 if ($endPos != $textLen) {
299 $excerpt = substr_replace($excerpt, $ending, -$phraseLen);
300 }
301
302 return $excerpt;
303 }
Its drawback is that it doesn't try to match as many searched words as possible,which only matches once by default.
How to implement the desired one?
The code listed here thus far has not worked for me so I spent some time thinking of an algorithm to implement. What I have now works decently, and it does not appear to be a performance problem - feel free to test. Results are not as snazzy Google's snippets as there is no detection for where sentences start and end. I could add this but it'd be that much more complicated and I'd have to throw in the towel on doing this in a single function. Already its getting crowded and could be better coded if, for example, the object manipulations were abstracted to methods.
Anyhow, this is what I have and it should be a good start. The most dense excerpt is determined and the resulting string will approximately be the span you have specified. I urge some testing of this code as I have not done a thorough job of it. Surely there are problematic cases to be found.
I also encourage anyone to improve on this algorithm, or simply the code to execute it.
Enjoy.
// string excerpt(string $text, string $phrase, int $span = 100, string $delimiter = '...')
// parameters:
// $text - text to be searched
// $phrase - search string
// $span - approximate length of the excerpt
// $delimiter - string to use as a suffix and/or prefix if the excerpt is from the middle of a text
function excerpt($text, $phrase, $span = 100, $delimiter = '...') {
$phrases = preg_split('/\s+/', $phrase);
$regexp = '/\b(?:';
foreach ($phrases as $phrase) {
$regexp .= preg_quote($phrase, '/') . '|';
}
$regexp = substr($regexp, 0, -1) . ')\b/i';
$matches = array();
preg_match_all($regexp, $text, $matches, PREG_OFFSET_CAPTURE);
$matches = $matches[0];
$nodes = array();
foreach ($matches as $match) {
$node = new stdClass;
$node->phraseLength = strlen($match[0]);
$node->position = $match[1];
$nodes[] = $node;
}
if (count($nodes) > 0) {
$clust = new stdClass;
$clust->nodes[] = array_shift($nodes);
$clust->length = $clust->nodes[0]->phraseLength;
$clust->i = 0;
$clusters = new stdClass;
$clusters->data = array($clust);
$clusters->i = 0;
foreach ($nodes as $node) {
$lastClust = $clusters->data[$clusters->i];
$lastNode = $lastClust->nodes[$lastClust->i];
$addedLength = $node->position - $lastNode->position - $lastNode->phraseLength + $node->phraseLength;
if ($lastClust->length + $addedLength <= $span) {
$lastClust->nodes[] = $node;
$lastClust->length += $addedLength;
$lastClust->i += 1;
} else {
if ($addedLength > $span) {
$newClust = new stdClass;
$newClust->nodes = array($node);
$newClust->i = 0;
$newClust->length = $node->phraseLength;
$clusters->data[] = $newClust;
$clusters->i += 1;
} else {
$newClust = clone $lastClust;
while ($newClust->length + $addedLength > $span) {
$shiftedNode = array_shift($newClust->nodes);
if ($shiftedNode === null) {
break;
}
$newClust->i -= 1;
$removedLength = $shiftedNode->phraseLength;
if (isset($newClust->nodes[0])) {
$removedLength += $newClust->nodes[0]->position - $shiftedNode->position;
}
$newClust->length -= $removedLength;
}
if ($newClust->i < 0) {
$newClust->i = 0;
}
$newClust->nodes[] = $node;
$newClust->length += $addedLength;
$clusters->data[] = $newClust;
$clusters->i += 1;
}
}
}
$bestClust = $clusters->data[0];
$bestClustSize = count($bestClust->nodes);
foreach ($clusters->data as $clust) {
$newClustSize = count($clust->nodes);
if ($newClustSize > $bestClustSize) {
$bestClust = $clust;
$bestClustSize = $newClustSize;
}
}
$clustLeft = $bestClust->nodes[0]->position;
$clustLen = $bestClust->length;
$padding = round(($span - $clustLen)/2);
$clustLeft -= $padding;
if ($clustLeft < 0) {
$clustLen += $clustLeft*-1 + $padding;
$clustLeft = 0;
} else {
$clustLen += $padding*2;
}
} else {
$clustLeft = 0;
$clustLen = $span;
}
$textLen = strlen($text);
$prefix = '';
$suffix = '';
if (!ctype_space($text[$clustLeft]) && isset($text[$clustLeft-1]) && !ctype_space($text[$clustLeft-1])) {
while (!ctype_space($text[$clustLeft])) {
$clustLeft += 1;
}
$prefix = $delimiter;
}
$lastChar = $clustLeft + $clustLen;
if (!ctype_space($text[$lastChar]) && isset($text[$lastChar+1]) && !ctype_space($text[$lastChar+1])) {
while (!ctype_space($text[$lastChar])) {
$lastChar -= 1;
}
$suffix = $delimiter;
$clustLen = $lastChar - $clustLeft;
}
if ($clustLeft > 0) {
$prefix = $delimiter;
}
if ($clustLeft + $clustLen < $textLen) {
$suffix = $delimiter;
}
return $prefix . trim(substr($text, $clustLeft, $clustLen+1)) . $suffix;
}
I came up with the below to generate excerpts. You can see the code here https://github.com/boyter/php-excerpt It works by finding all the locations of the matching words, then takes an excerpt based on which words are the closest. In theory this does not sound very good but in practice it works very well.
Its actually very close to how Sphider (for the record it lives in searchfuncs.php from line 529 to 566) generates its snippets. I think the below is much easier to read and is without bugs which exist in Sphider. It also does not use regular expressions which makes it a bit faster then other methods I have used.
I blogged about it here http://www.boyter.org/2013/04/building-a-search-result-extract-generator-in-php/
<?php
// find the locations of each of the words
// Nothing exciting here. The array_unique is required
// unless you decide to make the words unique before passing in
function _extractLocations($words, $fulltext) {
$locations = array();
foreach($words as $word) {
$wordlen = strlen($word);
$loc = stripos($fulltext, $word);
while($loc !== FALSE) {
$locations[] = $loc;
$loc = stripos($fulltext, $word, $loc + $wordlen);
}
}
$locations = array_unique($locations);
sort($locations);
return $locations;
}
// Work out which is the most relevant portion to display
// This is done by looping over each match and finding the smallest distance between two found
// strings. The idea being that the closer the terms are the better match the snippet would be.
// When checking for matches we only change the location if there is a better match.
// The only exception is where we have only two matches in which case we just take the
// first as will be equally distant.
function _determineSnipLocation($locations, $prevcount) {
// If we only have 1 match we dont actually do the for loop so set to the first
$startpos = $locations[0];
$loccount = count($locations);
$smallestdiff = PHP_INT_MAX;
// If we only have 2 skip as its probably equally relevant
if(count($locations) > 2) {
// skip the first as we check 1 behind
for($i=1; $i < $loccount; $i++) {
if($i == $loccount-1) { // at the end
$diff = $locations[$i] - $locations[$i-1];
}
else {
$diff = $locations[$i+1] - $locations[$i];
}
if($smallestdiff > $diff) {
$smallestdiff = $diff;
$startpos = $locations[$i];
}
}
}
$startpos = $startpos > $prevcount ? $startpos - $prevcount : 0;
return $startpos;
}
// 1/6 ratio on prevcount tends to work pretty well and puts the terms
// in the middle of the extract
function extractRelevant($words, $fulltext, $rellength=300, $prevcount=50, $indicator='...') {
$textlength = strlen($fulltext);
if($textlength <= $rellength) {
return $fulltext;
}
$locations = _extractLocations($words, $fulltext);
$startpos = _determineSnipLocation($locations,$prevcount);
// if we are going to snip too much...
if($textlength-$startpos < $rellength) {
$startpos = $startpos - ($textlength-$startpos)/2;
}
$reltext = substr($fulltext, $startpos, $rellength);
// check to ensure we dont snip the last word if thats the match
if( $startpos + $rellength < $textlength) {
$reltext = substr($reltext, 0, strrpos($reltext, " ")).$indicator; // remove last word
}
// If we trimmed from the front add ...
if($startpos != 0) {
$reltext = $indicator.substr($reltext, strpos($reltext, " ") + 1); // remove first word
}
return $reltext;
}
?>
function excerpt($text, $phrase, $radius = 100, $ending = "...") {
$phraseLen = strlen($phrase);
if ($radius < $phraseLen) {
$radius = $phraseLen;
}
$phrases = explode (' ',$phrase);
foreach ($phrases as $phrase) {
$pos = strpos(strtolower($text), strtolower($phrase));
if ($pos > -1) break;
}
$startPos = 0;
if ($pos > $radius) {
$startPos = $pos - $radius;
}
$textLen = strlen($text);
$endPos = $pos + $phraseLen + $radius;
if ($endPos >= $textLen) {
$endPos = $textLen;
}
$excerpt = substr($text, $startPos, $endPos - $startPos);
if ($startPos != 0) {
$excerpt = substr_replace($excerpt, $ending, 0, $phraseLen);
}
if ($endPos != $textLen) {
$excerpt = substr_replace($excerpt, $ending, -$phraseLen);
}
return $excerpt; }
I could not contact erisco, so I am posting his function with multiple fixes (most importantly multibyte support).
/**
* #param string $text text to be searched
* #param string $phrase search string
* #param int $span approximate length of the excerpt
* #param string $delimiter string to use as a suffix and/or prefix if the excerpt is from the middle of a text
*
* #return string
*/
public static function excerpt($text, $phrase, $span = 100, $delimiter = '...')
{
$phrases = preg_split('/\s+/u', $phrase);
$regexp = '/\b(?:';
foreach($phrases as $phrase)
{
$regexp.= preg_quote($phrase, '/') . '|';
}
$regexp = mb_substr($regexp, 0, -1) .')\b/ui';
$matches = [];
preg_match_all($regexp, $text, $matches, PREG_OFFSET_CAPTURE);
$matches = $matches[0];
$nodes = [];
foreach($matches as $match)
{
$node = new stdClass;
$node->phraseLength = mb_strlen($match[0]);
$node->position = mb_strlen(substr($text, 0, $match[1])); // calculate UTF-8 position (#see https://bugs.php.net/bug.php?id=67487)
$nodes[] = $node;
}
if(count($nodes) > 0)
{
$clust = new stdClass;
$clust->nodes[] = array_shift($nodes);
$clust->length = $clust->nodes[0]->phraseLength;
$clust->i = 0;
$clusters = new stdClass;
$clusters->data =
[
$clust
];
$clusters->i = 0;
foreach($nodes as $node)
{
$lastClust = $clusters->data[$clusters->i];
$lastNode = $lastClust->nodes[$lastClust->i];
$addedLength = $node->position - $lastNode->position - $lastNode->phraseLength + $node->phraseLength;
if($lastClust->length + $addedLength <= $span)
{
$lastClust->nodes[] = $node;
$lastClust->length+= $addedLength;
$lastClust->i++;
}
else
{
if($addedLength > $span)
{
$newClust = new stdClass;
$newClust->nodes =
[
$node
];
$newClust->i = 0;
$newClust->length = $node->phraseLength;
$clusters->data[] = $newClust;
$clusters->i++;
}
else
{
$newClust = clone $lastClust;
while($newClust->length + $addedLength > $span)
{
$shiftedNode = array_shift($newClust->nodes);
if($shiftedNode === null)
{
break;
}
$newClust->i--;
$removedLength = $shiftedNode->phraseLength;
if(isset($newClust->nodes[0]))
{
$removedLength+= $newClust->nodes[0]->position - $shiftedNode->position;
}
$newClust->length-= $removedLength;
}
if($newClust->i < 0)
{
$newClust->i = 0;
}
$newClust->nodes[] = $node;
$newClust->length+= $addedLength;
$clusters->data[] = $newClust;
$clusters->i++;
}
}
}
$bestClust = $clusters->data[0];
$bestClustSize = count($bestClust->nodes);
foreach($clusters->data as $clust)
{
$newClustSize = count($clust->nodes);
if($newClustSize > $bestClustSize)
{
$bestClust = $clust;
$bestClustSize = $newClustSize;
}
}
$clustLeft = $bestClust->nodes[0]->position;
$clustLen = $bestClust->length;
$padding = intval(round(($span - $clustLen) / 2));
$clustLeft-= $padding;
if($clustLeft < 0)
{
$clustLen+= $clustLeft * -1 + $padding;
$clustLeft = 0;
}
else
{
$clustLen+= $padding * 2;
}
}
else
{
$clustLeft = 0;
$clustLen = $span;
}
$textLen = mb_strlen($text);
$prefix = '';
$suffix = '';
if($clustLeft > 0 && !ctype_space(mb_substr($text, $clustLeft, 1))
&& !ctype_space(mb_substr($text, $clustLeft - 1, 1)))
{
$clustLeft++;
while(!ctype_space(mb_substr($text, $clustLeft, 1)))
{
$clustLeft++;
}
$prefix = $delimiter;
}
$lastChar = $clustLeft + $clustLen;
if($lastChar < $textLen && !ctype_space(mb_substr($text, $lastChar, 1))
&& !ctype_space(mb_substr($text, $lastChar + 1, 1)))
{
$lastChar--;
while(!ctype_space(mb_substr($text, $lastChar, 1)))
{
$lastChar--;
}
$suffix = $delimiter;
$clustLen = $lastChar - $clustLeft;
}
if($clustLeft > 0)
{
$prefix = $delimiter;
}
if($clustLeft + $clustLen < $textLen)
{
$suffix = $delimiter;
}
return $prefix . trim(mb_substr($text, $clustLeft, $clustLen + 1)) . $suffix;
}

Categories