Tuesday, 24 January 2012

A simple Debian based dev environment.

After walking a user through this entire process last night on irc I figure I’m probably better off documenting it somewhere so I don’t have to repeat myself.

This is just a quick walkthrough describing how to setup a decent development environment allowing the easy setup of multiple sites. It already assumes you have a working Debian or Ubuntu OS installed and configured with PHP, MySql &
Apache already running. You will also need to have a working sudo.

While some of this stuff is Debian / Ubuntu specific it wouldn’t be difficult at all to apply this to any other distro.

The very first thing we need to do is create a ‘www’ group. Anyone within this group will be able to create new websites.

sudo groupadd www

Put yourself in this group.

sudo gpasswd –a username www && newgrp www

Now, we need to make sure that the location all our sites are going to be stored within are owned and writable by www.

sudo chown :www /var/wwwsudo chmod g+ws /var/www

The s switch for chmod sets the sticky bit and ensures that all directories created within /var/www will also belong to the www group.

We need to make sure www can write to the directories where our vhost configs are kept as well.

sudo chown :www /etc/apache2/sites-*

Next, we are going to create a template vhost configuration. We will use this to generate configurations for each of our sites.

ServerName {SITE}.local DocumentRoot /var/www/sites/{SITE}.local/htdocs DirectoryIndex index.php Options FollowSymLinksAllowOverride All Options Indexes FollowSymLinks MultiViewsAllowOverride AllOrder allow,denyallow from all ErrorLog /var/www/sites/{SITE}.local/logs/error.log LogLevel warn CustomLog /var/www/sites/{SITE}.local/logs/access.log combined

Save that as /etc/apache2/sites-available/example.conf

Now, lets create a simple test site.

mkdir -p /var/www/sites/foo.local/{htdocs,logs}echo '' > /var/www/sites/foo.local/htdocs/index.phpcd /etc/apache2/sites-availablesed -e 's/{SITE}/foo/g' example.conf > foo.confsudo a2ensite foo.confsudo /etc/init.d/apache2 restartecho '127.0.0.1 foo.local' | sudo tee -a /etc/hosts

Theres a few commands here, but its all pretty straight forward:

The first line creates the minimal required directory structure for a new web site.
We then create an index.php file which has a call to phpinfo() in it.
Next we move into the directory where our vhost configs are stored.
We then create a new vhosy config called foo.conf which is a copy of the example.conf from above, we use sed to replace all instances of '{SITE}' with 'foo'
Next, enable this vhost. This adds a symlink within /etc/apache2/sites-enabled
Restart Apache.
Add foo.local to our hosts file. This enables the url http://foo.local to resolve to our local machine and hence, be served by Apache.

That's about it really. You can build quite a bit on this basic idea though. One thing I have implemented in a multi-user system is to make new commands available to the members of the 'www' group. These commands are mostly just wrappers
around the stuff that requires sudo, but it does make the process allot cleaner from an end user point of view. I might go into further details about that in another tutorial given the chance and the interest.

One thing to note. If you need directories within your web site to be writable by Apache you will have to make them belong to the www-data group, and this group will need write permissions. eg;

mkdir -p /var/www/sites/foo.local/uploadssudo chown :www-data /var/www/sites/foo.local/uploadssudo chmod g+w /var/www/sites/foo.local/uploads

View the original article here

An introduction to PHP and Mongodb

Most of us grew up on the concept of LAMP(Linux apache mysql and php) but there are times when that basic setup can become a real pain to maintain and scale. Generally the hardest part to scale out of a LAMP setup is MySQL. When running a large site with lots of data and traffic optimizing/scaling MySQL can be a really complicated undertaking.

That is where NoSQL comes into play. NoSQL is a very board term and some options are better than others. At the moment my choice for a NoSQL database is set firmly with MongoDB. Despite being a relatively new comer to the NoSQL scene MongoDB is quite mature and has awesome documentation.

If you are on a *nix platform you can simply use pecl

pecl install mongo

For windows you will need to download the MongoDB binaries and the php extensions

Also don't forget to add the mongo extension to your php.ini

extension=mongo.so

Now that was easy wasn't it? That is almost always a good sign when the installation is a breeze

For those of us who only have experience with relational databases such as MySQL, Postgresql, etc understanding a Document Oriented database may be a bit difficult at first. Lets start by defining some of the key differences between relational sql databases and non-relational documented oriented databases

Documents do not have a predefined schema like tablesJoins are not natively supported but can be manually coded

Establishing a connection with mongo db is really easy

$mongo = new Mongo();

or you can define an address

$mongo = new Mongo('127.0.0.1:1234');

Now we must select a database to work with.

$db = $mongo->ebooks;//or we can also use$db = $mongo->selectDB('ebooks');

It is important to note that if the database does not already exist one will be created auto-magically.

Instead of using 'tables' like with a relational sql database we use 'Collections'. Simply put these are collections of documents. From a traditional sql developer standpoint these would be comparable to a database table(collection) and an entry within that table(document). However, this is much for flexible than that. Each document can have sub documents etc.

Creating or retrieving a collection:

$collection = $db->ebooks;//or like above$collection = $db->selectCollection('ebooks');

Just as above, if the collection does not exist one will be created. The max length of the collection name is 128 chars. Although, that includes the db name and indexes. So, it is generally better to stick with a name that is 80 or less chars in length.

Inserting a document is really easy

$authors = $db->authors;$author = array( 'first_name'=>'Thomas', 'last_name' =>'Johnson', 'website'=>'http://www.tomfmason.net');$author_id = $authors->insert($author);

The return value of the insert is the object id. Also, you can pass an additional argument 'safe' which tells mongo to return immediately. This is much faster but you wont know immediately if the insert succeeded or not. That option would be really useful if you were inserting a large number of documents.

Lets say we have the following ebook documents in our ebooks collection.

$ebook = array( 'title'=>'An introduction to PHP and Mongodb', 'description'=>"Mongodb is an up and coming document oriented database that supports many awesome features including native PHP extension, an easy to use query interface and it is blazing fast. ", 'author_id'=>$author_id, 'reviews'=>array());$ebooks->insert($ebook);

and

$ebook = array( 'title'=>'php and mongo: A simple scalable CMS tutorial', 'description'=>"Some nice description here. ", 'author_id'=>$author_id, 'reviews'=>array());$ebooks->insert($ebook);

We can retrieve the author's ebooks like so

$filter = array( 'author_id'=>$author_id);$my_ebooks = $ebooks->find($filter);foreach($my_ebooks as $book) { echo $book['title'] . "
"; echo $book['description'] . "
";}

Something that caused me a bit of trouble was querying using an id. Lets say our author_id is a string like 4cffb213726e24640d000000. If you tried the following you would get back an empty result

$author_id = "4cffb213726e24640d000000"$filter = array('_id'=>$author_id);$author = $authors->findone($filter);

This is because in MongoDB the id's are not simply a string but an MongId object instead. You must do the following:

$author_id = new MongoId("4cffb213726e24640d000000");$filter = array('_id'=>$author_id);$author = $authors->findone($filter);

Now, lets say our author is wanting to update their website address. With MongoDB this is extremely simple.

$filter = array('_id'=>$author_id));$update = array( '$set'=>array('website'=>'http://www.phpfreaks.com'));$authors->update($filter,$update);

Lets say we are wanting to add a review for one of our ebooks. Would could do something like the following:

$filter = array('_id'=>$ebook_id);$review = array( 'name'=>'Thomas Johnson', 'email'=>'tomfmason@phpfreaks.com', 'website'=>'http://www.tomfmason.net', 'review'=>'MongoDB is awesomesauce');$update = array( '$push'=>array('reviews'=>$review));$ebooks->update($filter,$update);

Now our ebook should look something like:

Array( [_id] => MongoId Object ( [$id] => 4cffb69f726e24d404000000 ) [author_id] => 4cffb213726e24640d000000 [description] => Mongodb is an up and coming document oriented database that supports many awesome features including native PHP extension, an easy to use query interface and it is blazing fast. [reviews] => Array ( [0] => Array ( [name] => Thomas Johnson [email] => tomfmason@phpfreaks.com [website] => http://www.tomfmason.net [review] => MongoDB is awesomesauce ) ) [title] => An introduction to php and mongo)

See the MongoDB Modifier Operations documentation for more information on the modifiers such as $set, $unset,$push etc.

Deleting documents follows the same process as with querying and updating a document.

$filter = array('_id'=>$ebook_id);$ebooks->remove($filter,true);

"The GridFS spec provides a mechanism for transparently dividing a large file among multiple documents. This allows us to efficiently store large objects, and in the case of especially large files, such as videos, permits range operations (e.g., fetching only the first N bytes of a file)."

In my opinion MongoDB's GridFS is one of the most exciting parts of MongoDB. The GridFS acts very much like a standard collection except it stores files. Here is a simple example:

$meta_data = array( 'name'=>"ebook.pdf", 'type'=>'ebook', 'description'=>'An awesome example ebook', 'ebook_id'=>'4cffb69f726e24d404000000', 'downloads'=>0);$grid = $db->getGridFS();$file_id = $grid->storeFile(dirname ( __FILE__ ) . DIRECTORY_SEPARATOR . 'ebook.pdf',$meta_data);

If we were using php to upload this ebook we would use storeUpload instead. This makes storing php file uploads in MongoDB an absolute breeze.

We can now search the files just as we would with any other collection

$filter = array('_id'=>$file_id);$file_data = $grid->findone($filter);echo $file_data->file['description'];

Which should look something like this:

MongoGridFSFile Object( [file] => Array ( [_id] => MongoId Object ( [$id] => 4cffd892726e24640d070000 ) [name] => ebook.pdf [type] => ebook [description] => An awesome example ebook [ebook_id] => 4cffb69f726e24d404000000 [downloads] => 0 [filename] =>/path/to/my/ebook.pdf [uploadDate] => MongoDate Object ( [sec] => 1291835538 [usec] => 0 ) [length] => 2622 [chunkSize] => 262144 [md5] => 64ab0b4bfe362d4c90647a03532e137a ) [gridfs:protected] => MongoGridFS Object ( [w] => 1 [wtimeout] => 10000 [chunks] => MongoCollection Object ( [w] => 1 [wtimeout] => 10000 ) [filesName:protected] => fs.files [chunksName:protected] => fs.chunks ))

After getting a few private comments I thought I should come back and add a better conclusion. In short, I am very impressed with MongoDB and will use it when ever/where ever I can. However, we all need to keep in mind that not every tool is right for every job. If you require a highly reliable db, extremely fast reads/writes or are going to have very high update rates MongoDB is the perfect tool to solve those types of problems.


View the original article here

Working with dates in PHP

There are many topics on the forums that go again, topics many people often are having trouble with. One of these problem areas are how to handle dates, convert them to a different format, timezone issues, etc. This tutorial will attempt to address many of the commonest problems related to date and time issues.

Before covering how you handle dates in PHP, I want to talk a little about how you should store dates in a database. Specifically I'm going to talk about MySQL because that is what I've got the most experience with. The other DBMS have also got facilities for working with date and time information, so you can check out the manual for these.

Many people "invent" their own way of storing dates in the database, and this inevitably gives them some trouble later on. They may for instance have a VARCHAR field type and store dates in a DD/MM/YYYY format. This is the wrong way to do it.

There are a number of different ways you can store dates properly in a database. One way is to have an integer field and store a Unix timestamp. I don't like this approach. It makes you unable to use MySQL's date and time functions, and there are the potential issues with the Y2K38 problem.

MySQL has a datatype called TIMESTAMP. This displays the date and time in an ISO 8601 format, i.e. from the most significant part (year) to the least significant part (second). An example could be 2009-08-18 9:17:21. The extra formatting isn't actually necessary when typing it in, so 2009081891721 would be the same thing.

There is also a datatype called DATETIME. First looking at it, it seems identical to the TIMESTAMP, but that is not the case. First of all, TIMESTAMP still have issues with the Y2K38 thing, so it can only store dates that can be represented with a 32-bit unsigned integer starting from the Unix epoch (1970-01-01 00:00:00). This gives an upper limit 2038-01-19 03:14:07. DATETIME does not have this problem; it can store dates from 1000-01-01 to 9999-12-31. Finally, there are some datatypes called DATE and TIME. These are for if you just need either the date or time part only.

My recommendation is to use either DATETIME, DATE or TIME depending on your needs. Actually, there is a YEAR type as well. Using MySQL's built-in datatypes for date and time storage allows you to use its date and time functions.

I'll not be using databases for the remainder of this tutorial. The examples will assume you already have some string containing some date.

This is a very frequent problem. When using the date() function in PHP it is always using the server time for generating date and time stamps. Unless you're in a different timezone than your server, this is not a problem. I have got a VPS (Virtual Private Server) in England, but I live in Denmark. That is a time difference of one hour. How do I get PHP to display the right time for me?

Because I am the server admin, I can just change the server's clock (and that is actually what I've done). Most people cannot just do that, so we'll have to work out some alternative solutions to this problem.

If you've got access to php.ini (or can change its directives using an Apache .htaccess file) you can change the date.timezone directive (actually, this needs to be set to something if you don't want errors from PHP). Otherwise you can use the date_default_timezone_set() function. The manual has a list of valid timezones you can use for these two things. Because I am in Denmark, I would choose Europe/Copenhagen.

Let's try it out:

echo date('H:i:s');

My computer's local time is 09:34:08, so that is also the output. Now we'll try to change the timezone:

date_default_timezone_set('America/New_York');echo date('H:i:s');

And we'll get 03:34:08. So it seems to be working (how fortunate!). This is a very good way of doing it.

What if we need multiple dates in different timezones, but on the same page? Well, that is quite simple. Consider the following example:

date_default_timezone_set('Europe/Copenhagen');echo 'The time in Copenhagen is: ' . date('H:i:s') . PHP_EOL;date_default_timezone_set('America/New_York');echo 'The time in New York is: ' . date('H:i:s') . PHP_EOL;date_default_timezone_set('Europe/Moscow');echo 'The time in Moscow is: ' . date('H:i:s') . PHP_EOL;

The output of that would currently be:

The time in Copenhagen is: 09:45:56The time in New York is: 03:45:56The time in Moscow is: 11:45:56

What if you have users from multiple timezones? Still simple! Ask them what their timezone is and set it accordingly. The function timezone_identifiers_list() gives you an array of all the timezone identifiers, so you can use that to generate a drop down list they can choose from. You can also try out geolocating, but that is beyond the scope of this tutorial.

Finally, PHP has a function called gmdate(), which always formats the date in GMT. If you know the offset in seconds you can do like:

gmdate('H:i:s', time() + $offset);

, so you might do

gmdate('H:i:s', time() + 3600);

for an offset of one hour. However, this requires you to take DST into consideration. Not all countries observe DST, and some do it differently than others. My recommendation would be to use PHP's built-in support for timezones.

"I have got a date in DD/MM/YYYY but I need it in MM-DD-YYYY. Help!"

How do we help this person? Well, let's analyze the problem a bit. Each date consists of three components: the day, the month and the year. So, essentially what we need to do is reorder it and use hyphens instead of slashes. There are a few ways we can accomplish this. Let's first try splitting it up. We've got a function called explode() for that.

$oldDate = '18/08/2009'; // DD/MM/YYYY$parts = explode('/', $oldDate);/** * Now we have: * $parts[0]: the day * $parts[1]: the month * $parts[2]: the year * We could also have done: * list($day, $month, $year) = explode('/', $oldDate); */$newDate = "{$parts[1]}-{$parts[0]}-{$parts[2]}"; // MM-DD-YYYYecho $newDate; // 08-18-2009

This seems to work pretty nice. We can also use something called regular expressions. This will essentially be a one-liner:

$oldDate = '18/08/2009';$newDate = preg_replace('#^(\d{2})/(\d{2})/(\d{4})$#', '$2-$1-$3', $oldDate);

I am not going to explain regular expressions in this tutorial. You may check out this regex tutorial for that.

Any other ways? Yes, there is! As it usually happens to be with programming, there are many ways to do just one thing. Assuming we have already split up our date in three variables $day, $month and $year we can use a function called mktime() for generating a Unix timestamp and then use date() to format it in this way:

$timestamp = mktime(0, 0, 0, $month, $day, $year);echo date('m-d-Y', $timestamp);

Yet another way is using strtotime() to convert a formatted string into a Unix timestamp. EXCEPT, strtotime() does not recognize DD/MM/YYYY as a valid date format, so it returns false. There are also problems with ambiguity. Consider the string 07-08-2009. Is that the 7th of August, or is it the 8th of July? It will be the former.

If you take a date as input (for instance a birthday), it would be quite useful knowing if it's actually a valid date. There are two conditions that must be met before a date can be considered valid:

It must conform to a particular format (we might only want YYYY-MM-DD for instance).The date must actually exist (2009-02-29 doesn't exist, but 2008-02-29 does).

The first condition is rather simple, and we can do that using regular expressions. The second one is a bit more involved. We will have to take the length of a month into consideration. Maybe it's a leap year, maybe it's not? Fortunately, we needn't worry about that; PHP has a function called checkdate() that, uhm... checks a date. So, regex and checkdate() is what we need. A little example:

The date is valid!

';}else {echo '

The date is invalid!

';}echo '
';}?>
value="">

This example should be fairly straightforward. First we check the format of the string using preg_match() where we also extract the month, day and year in backreferences. preg_match() returns true if the string matches the pattern. Because logical and is left to right associative, the preg_match() is evaluated first, and the checkdate() is only evaluated if the first operand is true (if the left operand was false, the AND expression couldn't possibly return true, so evaluating the right operand would be redundant, hence the reason why it isn't).

If you have made separate fields for day, month and year it's even simpler and we can skip checking the format.

You might setup additional conditions that must be met before you consider a date valid. You might ask for a date interval meaning that the first must be earlier than the last. You might only want dates in the past or in the future, or they might have to be within a particular preset interval. The easiest way of doing this would be to convert the dates to Unix timestamps. From hereon it's rudimentary integer comparison. I'll leave that as an exercise to you. A safer bet might (recall Y2K38) be to use DateTime::diff(). For that, see this comment in the manual.

As you have hopefully seen. Dates aren't really that difficult to work with. PHP's built-in functions makes it very easy to validate and format all kinds of dates. It really does all the heavy lifting for us. Therefore, it shouldn't come as a surprise that the recommended further reading for this topic is the date reference section in the manual. PHP also has native support for other calendar types such as the Jewish calendar. I even think someone wrote a book solely about PHP and dates. You can go Google it (or Bing it).


View the original article here

Help! Fatal error: Cannot redeclare function - PHP Tutorial

Hey Everyone, phpfreak here!

This is for the PHP beginners out there, and possibly a refresher for those of you who are writing functions. I've ran across issues such as "Fatal error: Cannot redeclare function" in my coding history. Mostly because I was lazy and wrote the function in a template file that was called by a loop to theme content. Sometimes though, code is written on major projects where the file defining the function has to have the function in that file. Therefore, simply defining a function in your code such as:

Could get you into some trouble if that file is being looped through. You'd get that "Fatal error: Cannot redeclare function" error and your code will break. So, to get around this, we simply use the built in PHP Function: function_exists() to determine if we should define this function or not.

In a nutshell, you could think of the above statement like a caveman and say "IF NOT FUNCTION EXISTS foo THEN function foo..."

This should help you throughout your coding troubles. I'm a bit rusty, haven't written tutorials in a few years, so let me know if you have any thoughts or if you have any recommendations on other tutorials, feel free to post something!

//phpfreak
http://www.phpfreaks.com


View the original article here

Template based document generation using LiveDocx and Zend Framework

Generating print-ready well-formatted PDF documents with PHP is not an easy task. Traditionally, there are two main approaches to PDF generation with PHP. Given sufficient time and patience, both partially get the job done, but still leave a lot to be desired:

HTML-to-PDF: This approach is widely used in mainstream applications. Here an HTML document is programmatically created and converted to a PDF, using one of the many open source libraries. Since HTML, however, is not a page-oriented format (as is PDF), it is impossible to perform a 1-to-1 mapping between HTML and PDF. Typical word processing file format features, such as header and footers, orphans and widows or even page numbers can simply not be represented in HTML.

Programmatic: This approach offers total control of the resulting PDF. However, it requires that the x and y coordinates of every line of text, every geometrical shape and graphic be set from program code. Not only is this an extremely time-consuming solution, but is also very brittle: Every time a graphical designer changes the layout of a document, a programmer must re-work his or her program code.

In this article, the author presents an entirely new, third approach. It relies on templates being created in a WYSIWYG environment, such as Microsoft® Word or Open Office, and then being populated with data in PHP. The resulting document can be saved not only to PDF, but also DOCX, DOC and RTF.

Before we delve into a technical discussion on the inner workings of this new approach, let us first take a look at a practical example. The following PHP 5 code illustrates PDF generation, in which the merge fields software, licensee and company in the template template.docx [46.7 KB] are populated with scalar data in PHP. The resulting document document.pdf [104.7 KB] is created and written to disk.

$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge( array ( 'username' => 'yourUsername', 'password' => 'yourPassword' ) ); $phpLiveDocx->setLocalTemplate('template.docx'); $phpLiveDocx->assign('software', 'Magic Graphical Compression Suite v1.9'); $phpLiveDocx->assign('licensee', 'Henry Smith'); $phpLiveDocx->assign('company', 'Megasoft Co-operation'); $phpLiveDocx->createDocument(); $document = $phpLiveDocx->retrieveDocument('pdf'); file_put_contents('document.pdf', $document); unset($phpLiveDocx);

The code demonstrated in this article will be shipped with the Zend Framework 1.10 when it becomes available. Although at the time of writing, there is no official release date, 1.10 is expected to release in Q4 2009. In the meantime, you can check the components out of the Standard Incubator SVN repository.

LiveDocx is a SOAP-based document generation service, based on the market-leading, word processing component TX Text Control .NET. LiveDocx allows word processing templates to be populated in any programming language that supports SOAP. The resulting document can be saved to any supported format. This article, however, concentrates on using LiveDocx in PHP 5.

The components of the Zend Framework implementation of LiveDocx are located at /Zend/Service/LiveDocx/ in the standard Zend Framework distribution file. It is possible to use LiveDocx directly with the PHP 5 SoapClient, without the Zend Framework, and with the third party library NuSOAP. The NuSOAP approach even allows LiveDocx to be used in PHP 4. This article, however, concentrates on the official Zend Framework components in PHP 5.

The key point with LiveDocx is to reduce the effort required to generate well-formatted, print-ready word processing documents to an absolute minimum. For the end-user, the logic involved in creating any of the supported file formats is identical. For example, regardless of whether you want a PDF or RTF file, the code, with the exception of one parameter, is the same.

The core developers of LiveDocx also wanted to ensure that the generation of templates should be as simple as possible, in an environment, with which the end-user is already very familiar. Hence, you make the templates in Word or Open Office.

Throughout this article, we refer to the terms templates and documents. It is important to understand the difference between the two.

Templates: The term template is used to refer to the input file, containing formatting and text fields. Templates can be in any one of the following file formats:

DOCX - Office Open XML FormatDOC - Microsoft® Word DOC FormatRTF - Rich Text FormatTXD - TX Text Control® Format

Templates can be stored either locally on the client machine (the one from which the SOAP request is initiated) or remotely on the backend server. The decision on which one you should use depends upon the kind of application you are developing.

If you store the templates locally, you have to transfer the template together with the data that should be populated on every request. In the case that the template remains the same on every request, this approach is very inefficient. It would be better to upload the template to the backend server once and then reference it on all subsequent requests. This way, only the data that should be populated is transfered from the client to the backend server. Most applications, using LiveDocx fall into this category.

On the other hand, if you have a template that is constantly changing, or an application in which you enable end-users to upload templates, you may consider storing templates locally and transfer them every request. This approach, is obviously slower, as every request contains the template itself, in addition to the data to populate it.

Documents: The term document is used to refer to the generated output file that contains the template file, populated with data - i.e. the finished document. Documents can be saved in any one of the following file formats:

DOCX - Office Open XML FormatDOC - Microsoft® Word DOC FormatHTML - XHTML 1.0 Transitional FormatRTF - Rich Text FormatPDF - Acrobat® Portable Document FormatTXD - TX Text Control FormatTXT - ANSI Plain Text

In addition to the above word processing file formats, documents can also be saved to the following image file formats:

BMP - Bitmap Image FormatGIF - Graphics Interchange FormatJPG - Joint Photographic Experts Group FormatPNG - Portable Network Graphics FormatTIFF - Tagged Image File FormatWMF - Windows Meta File Format

In this section, we are going to look at the entire process of creating a document using LiveDocx from scratch.

The first step in any LiveDocx project is the creation of a template. To do this, you can use either Open Office or Microsoft® Word. For the purpose of this article, we are going to use Microsoft® Word 2007. For instructions on using Open Office, please take a look at the LiveDocx Blog.

Insert merge field in Microsoft® Word 2007 Start off by creating a new file in Microsoft® Word 2007 and save the template file as template.docx.

You can then start to compose the template, inserting text, graphics and merge fields with the Field dialog box, shown to the right.

After a while, you will have a template, which contains images, text and a number of merge fields. The merge fields are represented by { MERGEFIELD name } and will be populated with scalar data in the next step. The follow screenshot of the template in Microsoft® Word 2007 illustrates how your template may look:

Save the template template.docx[/img] [46 KB] when you are done.

Now that we have the template file, the next step is to populate it with data. In the following example, we are going to assign scalar data types - in this case strings - to the template.

$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge( array ( 'username' => 'yourUsername', 'password' => 'yourPassword' ) ); $phpLiveDocx->setLocalTemplate('template.docx'); $phpLiveDocx->assign('software', 'Magic Graphical Compression Suite v1.9'); $phpLiveDocx->assign('licensee', 'Henry Smith'); $phpLiveDocx->assign('company', 'Megasoft Co-operation'); $phpLiveDocx->assign('date', 'October 10, 2009'); $phpLiveDocx->assign('time', '14:12:01'); $phpLiveDocx->assign('city', 'Frankfurt'); $phpLiveDocx->assign('country', 'Germany'); $phpLiveDocx->createDocument(); $document = $phpLiveDocx->retrieveDocument('pdf'); file_put_contents('document.pdf', $document); unset($phpLiveDocx);

For many applications, in particular those in which PDF files are used of archiving purposes, you may wish to set the meta data of the PDF file. You can do this, by specifying an associative array with the meta data that should be embedded into the PDF file. The setDocumentProperties() method must be called before createDocument():

$documentProperties = array( 'title' => 'Magic Graphical Compression Suite v1.9', 'author' => 'Megasoft Co-operation', 'subject' => 'Magic Graphical Compression Suite v1.9', 'keywords' => 'Graphics, Magical, Compress, Suite, License' ); $phpLiveDocx->setDocumentProperties($documentProperties);

The resulting document document.pdf [104 KB] is written to disk and can now be opened in your favorite PDF reader, such as the shipped Document Viewer in Ubuntu:

In addition to the scalar data types, which were assigned to the template in the previous example, you can also assign compound data types, such as an associative array. Consider the template template.doc [20.5 KB] and the resulting document document.pdf [77.6 KB]. In particular, take a look at the following section of the template (click to enlarge):

The section of the template between the bookmarks in Microsoft® Word and in Microsoft® Word is repeated in the final document to produce rows of a table. One sub-array of the following associate array is used for each row.

Using the following PHP 5 code, we are going to populate the template with an associative array of telephone connection data. For clarity, this example shows only the part in which an associative array is assigned. The instantiation of LiveDocx and the document creation and retrievable processes are identical to the previous examples and have been omitted:

// instantiate LiveDocx $billConnections = array( array( 'connection_number' => '+11 (0)222 333 441', 'connection_duration' => '00:01:01', 'fee' => '1.15' ), array( 'connection_number' => '+11 (0)222 333 442', 'connection_duration' => '00:01:02', 'fee' => '1.15' ), array( 'connection_number' => '+11 (0)222 333 443', 'connection_duration' => '00:01:03', 'fee' => '1.15' ), array( 'connection_number' => '+11 (0)222 333 444', 'connection_duration' => '00:01:04', 'fee' => '1.15' ) ); $phpLiveDocx->assign('connection', $billConnections); // create and retrieve document

The resulting document contains the following table with the data from the assigned associate array (click to zoom):

In addition to the word processing file formats listed above that are supported by LiveDocx, you can also save the resulting documents as one or more image files. For this purpose, Zend_Service_LiveDocx_MailMerge offers the methods getAllBitmaps() and getBitmaps():

// instantiate LiveDocx // get all bitmaps // (zoomFactor, format) $bitmaps = $phpLiveDocx->getAllBitmaps(100, 'png');

Similarly, it is possible to retrieve images for pages in a specific range:

// get just bitmaps in specified range // (fromPage, toPage, zoomFactor, format) $bitmaps = $phpLiveDocx->getBitmaps(2, 2, 100, 'png');

Note that zoomFactor parameter. This is a per cent value, in the range of 10% to 400%. These methods are ideally suited to generating thumbnail images of the created document, for example, to display in the browser as a preview.

The actual image files can be written to disk by iterating through the $bitmaps array. There is one page of binary data per record in the array:

// write to disk // (one page per record) foreach ($bitmaps as $pageNumber => $bitmapData) { $filename = sprintf('documentPage%d.png', $pageNumber); file_put_contents($filename, $bitmapData); printf('Written %d bytes to disk as %s.%s', filesize($filename), $filename, PHP_EOL); }

The code, which constitutes the PHP 5 implementation of LiveDocx, shipped in the Zend Framework, is released under the New BSD license and thus may be deployed, modified and redistributed in most projects, according to that terms of the license. The actual LiveDocx SOAP server, however, is proprietary software. There are three ways in which the SOAP service can be deployed in your own applications.

Free public server
For the vast majority of applications, developers choose this approach. The default LiveDocx server that is referenced in the Zend Framework components is the free public server. It may be used in your own applications completely free of charge. Sign up for a LiveDocx account.Premium hosted server
In the case that your application generates several thousand documents per hour, you may consider paying a small monthly fee to have access to your own personal LiveDocx server. In association with leading hosting providers, you can rent such a premium hosted server.Local licensed server
In the case that your application generates more than about ten thousand documents her hour, you may consider installing a LiveDocx server in your local network. Having direct access in a local gigabit network is by far the fastest way of deploying LiveDocx.

This article has scratched the surface of what you can do with LiveDocx. If you would like to learn more about this new powerful document generation platform, please take a look at the following resources:

phpLiveDocx blogphpLiveDocx technical articlesLiveDocx blogLiveDocx API reference

Please do not hesitate to contact the author or request technical support in the support forum (free of charge) at any time.


View the original article here

Wednesday, 6 July 2011

Basics of PHP

Practical Uses of PHP

It almost goes without saying that you will want your business website to be compelling, interactive, and secure.  All of these characteristics will make your website more effective at bringing in and keeping customers.  But how to go about it in a way that is stable, cost-effective, and easy to manage?  One popular solution is to use the server-side scripting language PHP to help you solve those problems.

What is PHP?

Created in 1995, PHP originally stood for "Personal Home Page", however it is now generally understood to mean "PHP: Hypertext Preprocessor".  It was originally designed to create dynamic or more interactive web pages.  It is a widely-used, open-source, general-purpose scripting language.  PHP is a "high-level" language, meaning that it's generally more human-friendly (and easier to learn) than other programming languages such as C, ASP or ASP.net.

PHP was originally designed for use in Web site development, but rapidly grew to become a much more robust language.  PHP's primary use is as an "embedded" scripting language, which means that the actual PHP code is embedded in HTML code.  When used in this way, PHP enables your web server to process web pages before they're displayed in the user's web browser.

Monday, 13 June 2011

Welcome!

Hello and welcome to PHP-101!

This blog will aim to be a clear and concise collection of PHP related articles, tutorials, code snippets and reviews.

If you have an articles that you think is relevant, please send the URL and a quick description to pcanning@gmail.com

Please be sure to follow this blog and stay tuned for updates!