Archive
Convert HTML to PDF
In this thread you will find a list of “HTML to PDF” converters, e.g.:
- WKhtmlToPDF (blog post)
- DOMPDF
- Htmldoc
- HTML2PDF
- Prince XML (free for non-commercial use)
- etc.
WKhtmlToPDF
“Simple shell utility to convert html to pdf using the webkit rendering engine, and qt.“
You can get its binary executable here. Then, you can convert an html to pdf like this:
wkhtmltopdf-i386 test.html test.pdf
The result will be similar to exporting the page in PDF in a browser. This is not a surprise, wkhtmltopdf contains the WebKit rendering engine.
Command line scripting in PHP
When talking about command line scripting, most people think of Python or Perl. But it’s good to know that you can do something similar with PHP too!
Example (hello.php):
#!/usr/bin/php <?php # /etc/php5/cli/php.ini # The configuration file for the CLI version of PHP. print "Hello, World!\n"; ?>
You can execute it with “./hello.php” or “php hello.php“.
Notice that the command line version of PHP uses a different php.ini file.
Consult this page to learn more.
phpMyAdmin: No activity within 1440 seconds; please log in again
Problem
phpMyAdmin’s “No activity within 1440 seconds; please log in again” message is slowly but definitely driving you crazy. How to remain sane?
Solution
Increase the time limit. Open the file /etc/phpmyadmin/config.inc.php and add the following line to its end:
$cfg['LoginCookieValidity'] = 60 * 60 * 8; // in seconds (8 hours)
Here I set 8 hours, but you can change that.
When you log in again in phpMyAdmin, this new value will be taken into account.
Embed JpGraph in web pages
Problem
In PHP, you use JpGraph to produce graphs. You would like to include (embed) such a graph in a web page but you get the following error: “The image cannot be displayed, because it contains errors.“
Explanation
Let’s see the following basic example (example0.php):
<?php // content="text/plain; charset=utf-8"
require_once ('lib/jpgraph/src/jpgraph.php');
require_once ('lib/jpgraph/src/jpgraph_line.php');
// Some data
$ydata = array(11,3,8,12,5,1,9,13,5,7);
// Create the graph. These two calls are always required
$graph = new Graph(350,250);
$graph->SetScale('textlin');
// Create the linear plot
$lineplot=new LinePlot($ydata);
$lineplot->SetColor('blue');
// Add the plot to the graph
$graph->Add($lineplot);
// Display the graph
$graph->Stroke();
?>
Actually, this code will produce a PNG file, thus it will set the header to ‘Content-type: image/png‘. Once the header is set, it cannot be changed. Now let’s see what happens if you try to mix it with HTML:
<p> Beginning of the HTML page. Normal text. </p> <?php // the previous code of example0.php, I won't repeat that ?>
Since the page starts with normal HTML, the header will be set to ‘Content-type: text/html‘. Then the JpGraph PHP block will try to set ‘Content-type: image/png‘, so there is a conflict.
Solution #1
The easy way is to make a PHP file that produces a graph and include this file as if it were a normal image:
<p> This is normal HTML text. </p> <img src="example0.php">
What happens if you want to pass some data to the JpGraph PHP file, regarding how to produce the graph? If the data are simple, you could pass them via GET parameters:
This is normal HTML text. <img src="example0.php?label1=...&label2=...&data1=...&data2=...">
However, if the data is complicated, it would be better to include JpGraph directly in your PHP. This way, JpGraph has access to the necessary data structures from which it can construct the graph. I will explain it in the next section.
Solution #2
Let’s see how to include JpGraph directly in our PHP script:
<p>
Normal HTML at the beginning of the page.
</p>
<?php
// produce $ydata ...
?>
<?php
define('PREFIX_DIR', 'tmp.jpgraph'); // images will be created here
define('PREFIX', 'jpgraph'); // prefix for the images, can be anything
define('TIME_LIMIT', 3 * 60); // 3 minutes
$tmpfname = tempnam(PREFIX_DIR, PREFIX); // create temp filename
?>
<?php // content="text/plain; charset=utf-8"
require_once ('lib/jpgraph/src/jpgraph.php');
require_once ('lib/jpgraph/src/jpgraph_line.php');
// Some data
$ydata = array(11,3,8,12,5,1,9,13,5,7);
// Create the graph. These two calls are always required
$graph = new Graph(350,250);
$graph->SetScale('textlin');
// Create the linear plot
$lineplot=new LinePlot($ydata);
$lineplot->SetColor('blue');
// Add the plot to the graph
$graph->Add($lineplot);
// Display the graph
$graph->Stroke($tmpfname);
clean_old_tmp_files();
?>
<?php
?><img src="<?php echo get_relative_path($tmpfname); ?>"><?php
#unlink($tmpfname); // wouldn't work correctly
?>
<?php
function get_relative_path($filename) {
return preg_replace("/^.*\/(".PREFIX_DIR."\/.*)/", "$1", $filename);
}
function clean_old_tmp_files()
{
foreach (glob(PREFIX_DIR.'/'.PREFIX."*") as $filename)
{
#printf ( "Name: %s; age: %d<br>\n", $filename, time() - filemtime($filename) );
$age = time() - filemtime($filename);
if ($age > TIME_LIMIT) {
unlink($filename);
}
}
}
?>
As you can see, at the beginning of the page we show some HTML text that is followed by the graph. The data of the graph is produced by our PHP, and JpGraph’s PHP has direct access to it, thus no parameter passing is necessary.
The idea is the following: the graph is written to the file system. Then, this file is shown using the <img src="..."> tag. A time limit is set (here 3 minutes). When the script is called again, it’ll automatically remove images that are older than the limit.
Unfortunately, the image cannot be deleted right after the <img src="..."> tag. When your browser sees this tag, it’ll launch a thread to fetch the image and steps on. That is, the image would be deleted immediately after the creation, and the browser couldn’t show it. So the image file must be left there. My solution is to set a time limit, and when the PHP page is called again, it’ll remove the old images. This way you’ll always have some temporary images in the temp folder, but not many.
Preparation:
I suppose you have your PHP script in your ~/public_html directory. Here create a temporary directory for the images called tmp.jpgraph and set its permission to 777 (chmod 777 tmp.jpgraph).
Multiple inserts with MySQL/PHP
Problem
You want to insert multiple records in a MySQL table (in a loop, for instance). How to improve the performance?
Solution #1
One way is to regroup all the inserts in one SQL command:
INSERT INTO x (a,b)
VALUES
('1', 'one'),
('2', 'two'),
('3', 'three')
Credits go here.
Solution #2
Another way is to regroup the inserts in a transaction:
mysql_query("START TRANSACTION");
mysql_query("INSERT ...");
mysql_query("INSERT ...");
mysql_query("INSERT ...");
mysql_query("COMMIT"); // or "ROLLBACK" if you changed your mind
Credits go here.
Difference in days between two dates [PHP]
Problem
You have two dates and you want to know the difference between them in days.
Solution
$datetime1 = new DateTime('20110107');
# ... = new DateTime('2011-01-07'); is also good format
$datetime2 = new DateTime('20110110');
$interval = $datetime1->diff($datetime2);
print $interval->days; # 3
Check out the DateTime class, DateTime::diff, and the DateInterval class.
Credits
I found this elegant solution in this thread.
Homework
How old are you (in days)?
Today, yesterday, tomorrow in PHP
Here is how to get the date of today, testerday, tomorrow, etc. in PHP:
$today = date("Y-m-d");
# 2011-01-10
$yesterday = date("Y-m-d", mktime(0,0,0, date("m"), date("d")-1, date("Y")));
# 2011-01-09
$tomorrow = date("Y-m-d", mktime(0,0,0, date("m"), date("d")+1, date("Y")));
# 2011-01-11
For more info, check the documentation.
Currencies of Yahoo exchanges
Problem
Using Yahoo! Finance, we can ask info about a given stock, e.g. MSFT. The current price is, for instance, 27.98. But it is given in what currency? USD, EUR, CAD? Unfortunately it’s not indicated…
Solution
As I figured it out, these values are given in local currencies. Thus, we need to know in which country the exchange is located. Using Yahoo! Finance, the exchanges are indicated with a suffix. See http://finance.yahoo.com/exchanges for a list of all suffixes.
Example: let’s take the stock name “UG.PA” with value 30.04. “.PA” stands for “Paris Stock Exchange”, thus 30.04 is given in euro (EUR).
To facilitate life, using the page http://finance.yahoo.com/exchanges, I collected all the necessary information in an array structure. I also added the currencies. So, using this structure, you can easily figure out the currency, once you have the suffix of the exchange. If there is no suffix, we can suppose it’s in USD.
<?php
# id => description, country, currency
# source: http://finance.yahoo.com/exchanges
# collected by Jabba Laci (http://ubuntuincident.wordpress.com/2010/12/17/currencies-of-yahoo-exchanges/)
$financeSymbolMoney = array(
".CBT" => array("Chicago Board of Trade", "United States of America", "USD"),
".CME" => array("Chicago Mercantile Exchange", "United States of America", "USD"),
".NYB" => array("New York Board of Trade", "United States of America", "USD"),
".CMX" => array("New York Commodities Exchange", "United States of America", "USD"),
".NYM" => array("New York Mercantile Exchange", "United States of America", "USD"),
".OB" => array("OTC Bulletin Board Market", "United States of America", "USD"),
".PK" => array("Pink Sheets", "United States of America", "USD"),
".BA" => array("Buenos Aires Stock Exchange", "Argentina", "ARS"),
".VI" => array("Vienna Stock Exchange", "Austria", "EUR"),
".AX" => array("Australian Stock Exchange", "Australia", "AUD"),
".SA" => array("BOVESPA - Sao Paolo Stock Exchange", "Brazil", "BRL"),
".TO" => array("Toronto Stock Exchange", "Canada", "CAD"),
".V" => array("TSX Venture Exchange", "Canada", "CAD"),
".SN" => array("Santiago Stock Exchange", "Chile", "CLP"),
".SS" => array("Shanghai Stock Exchange", "China", "CNY"),
".SZ" => array("Shenzhen Stock Exchange", "China", "CNY"),
".CO" => array("Copenhagen Stock Exchange", "Denmark", "DKK"),
".NX" => array("Euronext", "France", "EUR"),
".PA" => array("Paris Stock Exchange", "France", "EUR"),
".BE" => array("Berlin Stock Exchange", "Germany", "EUR"),
".BM" => array("Bremen Stock Exchange", "Germany", "EUR"),
".DU" => array("Dusseldorf Stock Exchange", "Germany", "EUR"),
".F" => array("Frankfurt Stock Exchange", "Germany", "EUR"),
".HM" => array("Hamburg Stock Exchange", "Germany", "EUR"),
".HA" => array("Hanover Stock Exchange", "Germany", "EUR"),
".MU" => array("Munich Stock Exchange", "Germany", "EUR"),
".SG" => array("Stuttgart Stock Exchange", "Germany", "EUR"),
".DE" => array("XETRA Stock Exchange", "Germany", "EUR"),
".HK" => array("Hong Kong Stock Exchange", "Hong Kong", "HKD"),
".BO" => array("Bombay Stock Exchange", "India", "INR"),
".NS" => array("National Stock Exchange of India", "India", "INR"),
".JK" => array("Jakarta Stock Exchange", "Indonesia", "IDR"),
".TA" => array("Tel Aviv Stock Exchange", "Israel", "ILS"),
".MI" => array("Milan Stock Exchange", "Italy", "EUR"),
".MX" => array("Mexico Stock Exchange", "Mexico", "MXN"),
".AS" => array("Amsterdam Stock Exchange", "Netherlands", "EUR"),
".NZ" => array("New Zealand Stock Exchange", "New Zealand", "NZD"),
".OL" => array("Oslo Stock Exchange", "Norway", "NOK"),
".SI" => array("Singapore Stock Exchange", "Singapore", "SGD"),
".KS" => array("Korea Stock Exchange", "South Korea", "KRW"),
".KQ" => array("KOSDAQ", "South Korea", "KRW"),
".BC" => array("Barcelona Stock Exchange", "Spain", "EUR"),
".BI" => array("Bilbao Stock Exchange", "Spain", "EUR"),
".MF" => array("Madrid Fixed Income Market", "Spain", "EUR"),
".MC" => array("Madrid SE C.A.T.S.", "Spain", "EUR"),
".MA" => array("Madrid Stock Exchange", "Spain", "EUR"),
".ST" => array("Stockholm Stock Exchange", "Sweden", "SEK"),
".SW" => array("Swiss Exchange", "Switzerland", "CHF"),
".TWO" => array("Taiwan OTC Exchange", "Taiwan", "TWD"),
".TW" => array("Taiwan Stock Exchange", "Taiwan", "TWD"),
".L" => array("London Stock Exchange", "United Kingdom", "GBP"),
);
?>
Get file extension [PHP]
Problem
You have a filename and you want to get its file extension, i.e. you want to extract the substring after the last dot.
Solution
/**
* Return the file extension, i.e. take a string and return the
* substring after the last dot.
* If there is no extension, return an empty string.
*
* @return File extension (after the last dot) or empty string (if there is no extension).
*/
static public function get_extension($str)
{
$ext = substr(strrchr($str, '.'), 1);
return $ext;
}
Credits
I found this solution here. I chose this one because it’s simple enough and it returns an empty string if there is no file extension.