Views : 2286  |
This document explains how to build a PHK package. If you just want to use an
existing PHK package, refer to the PHK user's
guide.
As this document is a reference guide, you may want to read this basic tutorial
first.
Here is a global view of the build process :
1 - What you need
1.1 - PHP interpreter
In order to create a PHK package, you first need a PHP CLI interpreter,
version 5.1.0 or more.
The PHP CLI interpreter is generally found in the bin subdirectory, under the
PHP installation directory, or in /usr/bin. Its name is php on Unix/Linux, and php.exe
on Windows.
In order to determine if your installation is suitable to build a PHK
package, run the 'php -v' command in a shell. In the output, the first line must
display version 5.1.0 or more, followed with the '(cli)' string.
1.2 - PHK_Creator
Then, you need the package creation software. It is provided as one file,
named 'PHK_Creator.phk', which can be downloaded
here (choose 'PHK Creator', then 'PHK Creator package').
There is no installation procedure for this file, as it is itself a PHK
package. It can be saved anywhere in your file system, and does not have to be in your include
path, nor in the shell's path. When building your package, you will just specify its absolute path
on the command line.
2 - The Package Specification File
Now that your platform is ready, you will create a Package Specification
File. This file is interpreted by the PHK_Creator software and contains
every information PHK_Creator needs to build the package.
In the whole PHK documentation, PSF stands for Package Specification
File.
2.1 - Structure
The PSF is a text file, created using any
text editor (both Windows/CR-LF and Unix/LF line terminations are supported).
It is made up of two parts :
- the command section, mandatory,
- and the options section, optional.
2.2 - Subfile paths
Basically, a package contains a tree of virtual or pseudo files, called subfiles.
The subfile tree is made up of directories and
files, as a usual file system. In this tree, each node can be accessed through a unique
canonical path (no symbolic link). This
path is expressed using a Unix-like syntax :
- the root path is known as '/'
- The subdirectories are separated by '/' characters. In order to keep the
compatibility with software using the DIRECTORY_SEPARATOR constant, the '\'
character is also accepted as separator in subfile paths, but the PHP API will
always return paths separated with '/' chars.
You will use this syntax when adding files to the archive and when specifying
paths in options like '{cli/web/lib}_run_script' and others.
This 'Unix-like' syntax is used in every environment, even on Windows
and other non-Unix
ones.
2.3 - The command section
The first part in a PSF is the 'command section'. This section defines which
files to include in the package.
2.3.1 - Syntax
Here is the syntax for the command section :
- Commands are composed of words, separated by spaces or tabs.
- The first word on a line is the command to run. The other words are
modifiers and arguments.
- Commands, modifiers, and arguments cannot contain any space or tab character.
- Anything following a '#' char is considered as a comment and ignored.
- A line can be continued by setting a '\' as its last character.
2.3.2 - Variables
Variables can be set, and then used in any subsequent command. Values are
strings.
A variable is set through the 'set' command described below. Environment
variables from the calling environment are also available in the PSF (the order
is to search first in the internal table, then in the environment).
A variable's value can be used and substituted anywhere, using a
Makefile-like syntax :
Example of using an environment variable : As you can see in its building
kit, the PHPUnit API is built in 2 steps : first, we build the tree with phpdoc,
and we build a PHK package from this tree. The location of this source tree is
provided by the Makefile variables. So, the PSF receives this location through
an environment variable. The Makefile runs this command :
TMP_DIR=$(TMP_DIR) php PHK_Creator.phk build PHPUnit_api.phk
PHPUnit_api.psf |
and the PSF contains this line :
merge -strip=true -compress=gzip / $(TMP_DIR) |
2.3.2.1 - Pre-defined variables
The following predefined variables can be used in the
command section :
2.3.2.1.1 - PSF_DIR
The PSF_DIR variable contains the name of the directory where the PSF lies.
You can use it to compose paths relative to the PSF location, avoiding to use
an absolute path in your PSF. This way, you can move your source file tree
without needing to modify your PSF, if the relative path remains the same.
2.3.2.1.2 - Command arguments
The command arguments are the arguments present on the command line after the
PSF file name. If present, these arguments can be retrieved using a $(<number>)
syntax, where <number> starts at 1.
Example, when running this command :
# php PHK_Creator.php build example.phk example.psf foo bar |
every occurences of $(1) in the example.psf file will be replaced with
'foo' and $(2) will be replaced with 'bar'.
2.3.3 - Modifiers
Some commands support modifiers. Modifiers are strings of the form :
They must be located between the command and its arguments. Modifiers
are always optional (although a 'modify' command without modifiers is useless).
Here are the supported modifiers, their possible values, and their meanings :
| Modifier |
Value |
Default |
|
| -autoload |
true |
true |
When true, PHP source file(s) are scanned for
symbols to populate the automap. |
| false |
| -strip |
true |
false |
When true, PHP source file(s) are stripped
(filtered through php_strip_whitespace()) before being stored into the
archive. Makes the package slightly faster and much smaller. |
| false |
| -compress |
none |
none |
The compression type to apply to the file(s). |
| gzip |
| bzip2 |
The 'autoload' and 'strip' modifiers have an effect
only for files which are identified as PHP source files at package creation
time. For more information about this detection mechanism, see the
'Identifying PHP source files' chapter below.
The 'compress' modifier sets only the way the file will be stored in
the package. When this file is read at runtime, it is transparently
uncompressed. So, the 'compress' modifier's only effect is to reduce the package
size, at the expense of a slower access to the file at runtime. You may also
note that, at runtime, if a supported PHP cache system is present, the compression
flag does not reduce the performance anymore, as the data is uncompressed only
once to populate the cache. The only (minor) remaining drawback, in this case, is
that it requires the corresponding extension (zlib and/or bzip2) in the runtime PHP interpreter.
Example:
# Under /foo/bar, every file will be gzip-compressed and PHP
sources will be stripped
modify -compress=gzip -strip=true /foo/bar |
2.3.4 - Target syntax
In the add and merge commands, the first argument is the
virtual path where files will be added/merged. It can contain some (generally
one) '&' character(s). Every occurence of a '&' in the target path will be replaced by the 'basename' of the corresponding
source path (for unix admins, think of an automount table).
Example :
# This line defines these files in the virtual tree :
# - /tests/test1.php
# - /tests/parameters
# - /tests/run.php
add /tests/& /sources/test1.php /etc/parameters /other/dir/run.php |
The PSF supports file globbing. So, you can use specifications containing
'*' and '?' characters as source paths.
There is no 'mkdir' command, as virtual directories are automatically
created when needed by the add or merge commands.
2.3.5 - Commands
2.3.5.1 - add
add [modifiers] <virtual-path> <source-path1> [<source-path2> ... ] |
Adds files or directories to the virtual tree, as <virtual-path>. If the
source path is a directory, this directory and its content are recursively
included.
Examples :
#-- Creates /info/help.txt and /info/help.htm
add /info/& $(SOURCE)/etc/help.txt $(SOURCE)/etc/help.htm
#-- Adds a whole source tree as /src
add /src $(SOURCE_DIR) |
Adding a directory as virtual root (/) is not supported. Use the
merge command instead.
2.3.5.2 - merge
merge [modifiers] <virtual-dir> <source-dir1> [<source-dir2> ... ] |
Similar syntax to the add command but, here, we deal with directories,
as source and target to merge together. Merging a source directory to an
existing virtual one, consists of adding its content to the existing content,
eventually replacing nodes when they already exists in the virtual tree.
Examples :
# Merges 2 source dirs together
merge / $(SOURCE1) $(SOURCE2) |
When some parts of the source paths overlap, the order of
source path specifications determines what the virtual tree will contain at last.
2.3.5.3 - modify
modify <modifiers> <virtual-path1> [<virtual-path2> ... ] |
This command is used to change the modifiers associated with a part of the
virtual tree. When <virtual-path> is a virtual directory, the modifiers are
recursively applied.
Modifiers are used only after the whole PSF is processed. So, adding
files with a given modifier is exactly the same as adding them without the
modifier and then using modify to set it.
Example :
#-- Insert a source tree
merge / $(SOURCE)
#-- The params subdir is excluded from the automap and its files are compressed.
modify -autoload=false -compress=gzip /params |
2.3.5.4 - mount
mount <mount-variable> <path of phk-archive> |
This command is used when you want to copy some data from an existing package
to a new one.
The <mount-variable> is the name of a variable which will receive the
package's mount point. This mount point is computed by the mount process and
will be used to access its subfiles. You can mount an unlimited number of
existing packages at the same time, providing a different mount-variable for
each.
After mounting a PHK package, its subfiles will be referred as 'phk:://$(mount-variable)/<path> in the subsequent add and merge commands.
An example will make it clearer :
#-- I want to extract the /etc virtual tree from an existing
package,
#-- and insert this subtree as /params in a new one :
mount first_package /path/to/existing/package.phk
add /params phk://$(first_package)/etc |
2.3.5.5 - remove
remove <virtual-path1> [ <virtual-path2> ... ] |
Removes a part of the virtual tree we are currently building.
Why would we need to destroy something we are building ? Generally to
implement an exclusion, when we want to include 'everything except...'.
Example:
#-- I want to include everything except the doc which is in
$(SOURCE)/documentation.
# If the $(SOURCE) directory contains a lot of entries, it is easier to include everything,
# and then
remove what we don't want.
merge / $(SOURCE)
remove /documentation |
Removing a non-existent directory is useless, but accepted.
Trying to remove the virtual root ('remove /') is forbidden and
triggers a fatal error.
2.3.5.6 - set
Sets a variable to be used in the rest of the command section.
Example :
set doc_dir $(PSF_DIR)/doc
add /documentation $(doc_dir) |
2.4 - The 'options' section
This section, as its name implies, contains the packages's options. PSF
generally contain an options section, even if not mandatory.
2.4.1 - Syntax
The section's start is identified by a line starting with '%options'. The
section
contains some PHP code, without the leading '<?php' and trailing '?>. This
code can contain anything, but, at the end, it
must return an array, with option names as keys, and option values as array
values.
Example of an options section (excerpt from PHPUnit's PSF) :
#-- The command section
merge $(FLAGS) / $(PSF_DIR)/source
%options #-- The package's options
return array(
'name' => 'PHPUnit',
'version' => '3.0.0',
'release' => '6',
'license' => 'BSD License
<http://www.opensource.org/licenses/bsd-license.php>',
'copyright' => 'Sebastian Bergman
<http://sebastian-bergmann.de/>',
'url' => 'http://www.phpunit.de',
'packager' => 'F. Laupretre <mailto:francois@tekwire.net>',
'icon' => '/phpunit-logo.gif',
'license_prefix' => '/license',
'test_script' => '/tests/test.phk'
);
#-------- EOF -------- |
2.4.2 - Embedding an URL in a string
As you may see in the previous example, in option values, the strings displayed in webinfo mode only, like the
license, author, packager, etc, can embed an URL, using the following syntax :
# Specify the URL between '<' and '>' characters
string <url> |
When the string is displayed in HTML mode, the URL is extracted and displayed as an
hypertext link.
Example :
'packager' => 'F. Laupretre <mailto:francois@tekwire.net>' |
'license' => 'New BSD License <http://framework.zend.com/license>' |
will give the following webinfo output :
2.4.3 - PSF options
- The options which can contain an URL are
flagged as 'string with optional URL'.
- The options which don't have any impact on the package's behavior, except
when displayed in webinfo mode, are flagged as '(Information only)'.
2.4.3.1 - author
Type: string with optional URL
The package's author (Information only)
2.4.3.2 - auto_umount
Type: Boolean - Default=false.
This parameter is used with the script referenced in the 'lib_run_script' option. When it is
true, the
PHK archive is automatically unmounted after the 'lib_run_script' is run, and the
include/require returns null.
Using this parameter allows to define some kind of 'volatile' packages: they
are available just the time to do what they have to, and then, they disappear.
Example : this parameter is used in the unit tests in the demonstration
packages. We use the following architecture :
- the test code is put in a PHK package, and this package is itself embedded
in a higher level PHK package (with an 'autoload=false' modifier),
- the test package is defined as the 'test_script' in the 1st level package,
- in the tests package, AllTests.php is defined as 'lib_run_script' and auto_umount is
set to true.
The result is that, when we request a '@test' on the main package :
- the main package includes the test package because it is defined as its 'test_script',
- once the tests package is mounted, it runs its 'lib_run_script'
(AllTests.php) and executes the unit tests,
- When the tests are complete, because of the auto_umount option, the tests
package is unmounted.
2.4.3.3 - crc_check
Type: Boolean (default = false)
If set, a CRC check will be forced every time the package is mounted. By
default, as it is too expensive, the CRC is checked only when accessing the
webinfo mode, or before executing a built-in CLI command.
The file size is checked each time a package is run, as it allows to detect typical erroneous FTP ascii/binary conversions.
Please
note that PHK packages, even if they can be considered as PHP scripts and run as
such, must never be modified by an external tool, such as a transfer conversion.
So, when transferring a PHK file through FTP, you must use the binary
mode.
As
there is only one global CRC for the whole package, checking the package's CRC implies temporarily reading the whole
package file in memory.
2.4.3.4 - compress_min_size
Type: numeric. Default = 0.
This parameter is used when building the package, and for every subfile with
a compression flag. If the file size (before compression) is lower than this value, the file is not compressed.
2.4.3.5 - compress_max_size
Type: numeric. Default = no limit.
This parameter is used when building the package, and for every subfile with
a compression flag. If the size of the file (uncompressed) is greater than this
parameter's value, the file is not compressed. This parameter allows to avoid
compressing files whose size makes them too heavy for on-the-fly decompression.
Remember that, when the PHK runtime environment contains a supported
PHP cache, on-the-fly
decompression does not reduce the performance anymore.
2.4.3.6 - compress_ratio_limit
Type: numeric (0-100), default=90
This parameter is used when building the package, and for every subfile with
a compression flag. If the file's compression ratio is
greater than this
value, the file is left uncompressed.
Compression ratio = 100 * <compressed size> / <uncompressed size>
The primary purpose, here, is to avoid compressing already compressed files,
compressed pictures, or very small files.
The default value is not 100% because :
- 1. we consider that, when compressing a
file, if the resulting compressed size is more than 90% of the original size,
the gain in space is not worth the CPU power that will be consumed at decompression
time.
- 2. it allows to filter out some 'basic-RLE' compressed files (pictures
generally), whose gzip-compressed size is still slightly smaller than their
original size. There, again, we consider that a double compression scheme is
not worth the CPU it will use.
2.4.3.7 - cli_run_script
Type: Subfile path
The script to run when the package is run in CLI mode.
2.4.3.8 - copyright
Type: string with optional URL
Copyright notice (Information only)
2.4.3.9 - distribution
Type: string with optional URL
Self-explanatory. Information only
2.4.3.10 - help_prefix
Type : Subfile path without suffix.
The 'help_prefix' option is used when searching for the help file to display (webinfo 'Help' page or
CLI '@help' built-in command). In HTML, PHK looks for a subfile with a suffix of
'.htm' or '.html'. If not found, it tries to find a file with a '.txt' suffix or
with no suffix.
Example: if you give '/etc/help' as 'help_prefix', PHK will look in turn for these
filenames:
In HTML :
- 1. /etc/help.htm
- 2. /etc/help.html
- 3. /etc/help.txt
- 4. /etc/help
In CLI mode :
- 1. /etc/help.txt
- 2. /etc/help
As a text file can be used in both mode, and an HTML file can be used
only in HTML mode, provide a text file first and, optionally, an HTML file.
2.4.3.11 - include_path
This feature is inhibited
until a solution is found to the 'include path' issue.
2.4.3.12 - icon
Type: Subfile path
Defines the path of the subfile to take as the package's icon. In
webinfo mode, this image is displayed on every page. When the user clicks on
this image, he goes to the address specified with the
url option.
If your image subfile's suffix is not defined in the PHK
default mime table, you must provide its mime type using the
mime_types option.
2.4.3.13 - icon_bgcolor
Type: String / HTML color spec
The background color to set around the icon in webinfo mode (see figure
above).
This parameter can contain any value suitable for a '<td bgcolor=...'
element.
2.4.3.14 - icon_width
Type: HTML cell width specification. Default = 150 pixels.
The width of the cell containing the icon in webinfo mode (see figure above).
This parameter can contain any value suitable for a '<td width=...'
element (absolute, percentage, etc).
2.4.3.15 - info_script
Type: Subfile path
The script to run when the webinfo Home
page is displayed, instead of the default information.
As any PHP script, this subfile can contain PHP code or just some
static HTML content.
2.4.3.16 - lib_run_script
Type: Subfile path
The script to run when the PHK archive is included from another PHP script.
2.4.3.17 - license
Type: string with optional URL
Information only. This parameter contains the license's name and, by
convention, should contain an URL to the license home page.
Example:
'license' => 'New BSD License
<http://framework.zend.com/license>' |
2.4.3.18 - license_prefix
Type : Subfile path without suffix.
The same as 'help_prefix', but for the license.
2.4.3.19 - max_php_version
Type: String
The maximum PHP version this package supports.
2.4.3.20 - mime_types
Type: Array
This array contains additonal mime types to associate with file
suffixes. These mime types are used in webinfo mode when
displaying a subfiles's content, and in execution mode when accessing subfiles directly through
the web (direct web access).
By default, PHK knows the following suffixes :
| Suffix |
Mime type |
| gif |
image/gif |
| jpeg |
image/jpeg |
| jpg |
image/jpeg |
| png |
image/png |
| psd |
image/psd |
| bmp |
image/bmp |
| tif |
image/tiff |
| tiff |
image/tiff |
| iff |
image/iff |
| wbmp |
image/vnd.wap.wbmp |
| ico |
image/x-icon |
| xbm |
image/xbm |
| txt |
text/plain |
| htm |
text/html |
| html |
text/html |
| css |
text/css |
| php |
application/x-httpd-php |
| phk |
application/x-httpd-php |
| pdf |
application/pdf |
| js |
application/x-javascript |
| swf |
application/x-shockwave-flash |
| xml |
application/xml |
| xsl |
application/xml |
| xslt |
application/xslt+xml |
| mp3 |
audio/mpeg |
| ram |
audio/x-pn-realaudio |
| svg |
image/svg+xml |
Through this option, you can redefine suffixes from the default mime
table.
Example: if you want to access some MS Word™ and MS Excel™ documents via
direct web access, you will need to set the following option :
...
'mime_types' => array('doc' => 'application/msword',
'xls' => 'application/vnd.ms-excel'),
... |
2.4.3.21 - min_php_version
Type: String
The minimum PHP version this package supports.
2.4.3.22 - mount_script
Type: Subfile path
This script is called at the end of the mount process.
If the 'mount_script' decides that the package cannot run in this
environment, for any reason, it can 'refuse' the mount by throwing an exception.
When the 'mount_script' is run, the plugin object, if any, is not
created yet, so it cannot be called.
2.4.3.23 - name
Type : String
The package's name (Information only)
2.4.3.24 - packager
Type: string with optional URL
The package's builder (Information only)
2.4.3.25 - phpunit_package
Type: Subfile path
This option is used, along with phpunit_test_package, when the PHPUnit test
package does not contain the PHPUnit package. In this case, the container
package must contain the PHPUnit package, generally flagged as 'autoload=false',
not to uselessly export the PHPUnit symbols to the container's automap. In this
case, you must explicitely define where the PHPUnit package lies through this
option.
You can build the PHPUnit package yourself or download it from the
download area.
2.4.3.26 - phpunit_test_package
Type: Subfile path
This option, introduced with PHK 1.4, should be used when your unit tests use
PHPUnit, instead of the older test_script option.
This option contains the path of a subpackage containing your test file tree.
When using this option, you should not set the test_script option.
2.4.3.27 - plain_prolog
Type: Boolean - Default=false
When creating a package, this parameter defines if we strip the PHP prolog
(e.g. run it through php_strip_whitespace()), which is the default, or if we
keep it as-is.
This flag is used when encountering a bug in the PHK runtime code because
code
stripped through php_strip_whitespace() does not return valid line numbers in
error messages. If you get an error located in the PHK runtime layer (by opposition
to virtual files whose paths start with 'phk://'), regenerate your package with
this flag on and reproduce your error. Now, your error message should display a
valid line number. Without this number, it will be very hard for us to investigate the
problem.
Except in this case, this parameter should not be set as it makes the
generated PHK archive larger and slower.
2.4.3.28 - plugin_class
Type : class name.
For more information on this parameter, please read this
document.
2.4.3.29 - release
Type : String
Self-explanatory. Information only.
2.4.3.30 - required_extensions
Type: Array
A list of PHP extensions required by the package. Each time the
package is run, PHK checks that all these required extensions are
present or can be loaded by dl(). If
it is not the case, it triggers a fatal error.
This behavior was chosen because we consider it cleaner than getting a
cryptic error message when a missing function or class is called. The philosophy
here is : if your package is not compatible with your runtime environment, you
must know it as early as possible (without having to test every features).
If some of the package's subfiles are compressed, the corresponding extensions ('zlib' and/or 'bz2') are automatically
appended to the list of required
extensions.
As of PHK 1.4.0, subpackage's required extensions are automatically
recursively added to the list of required extensions in the container
package(s).
The extensions listed here are 'universal' extensions names, without file
suffixes (ex: 'iconv', 'gd', etc.). PHK automatically determines the filename to
dl().
2.4.3.31 - requires
Type: String
What the package requires to run (Information only).
2.4.3.32 - summary
Type: String
Self-explanatory. Information only
2.4.3.33 - tabs
Type Array.
Additional tabs to display in webinfo mode.
Each array element corresponds to one additional tab. The key is the string
to display in the tab, and the value gives the action to associate with this
tab.
To be completed... For a list of the supported actions, see the PHK_Webinfo.php
file in the PHK_Creator
building kit, and view an example in the Smarty demonstration
package and
Smarty PHK building kit.
2.4.3.34 - test_script
Type: Subfile path
A script to call when the user displays the webinfo 'test' page, or when
it runs the '@test' built-in command.
This is the low-level interface to the unit tests feature. As of PHK
1.4, you can use a new mechanism, specifically intended for PHPUnit tests, via
the phpunit_test_package and phpunit_package options.
2.4.3.35 - umount_script
Type: Subfile path
This script is called just before a PHK archive is unmounted.
When it is run, the plugin object, if any, is already unset, but the automap is still active.
This script is called only when explicitely calling PHK_Mgr::umount(). When the program ends, no umount script is executed.
2.4.3.36 - url
The URL to call when the user clicks on the package's icon in webinfo mode.
2.4.3.37 - version
Type: String
Self-explanatory. Information only.
2.4.3.38 - web_access
Type: Array of subfile paths
A list of subfile paths authorized for web direct access.
If an authorized path is a directory, everything under this node is
authorized. So, putting '/' in the list gives an open access to
the whole file tree.
2.4.3.39 - web_main_redirect
Type: Boolean - Default=false.
In web direct access mode, when the URL we receive does not contain any subfile
path, or if the requested subfile path is not authorized, PHK tries to execute
the script defined by the 'web_run_script' option. Then :
- If the 'web_main_redirect' option is set, PHK returns an HTTP 301/Redirect
with the URL of the web_run_script, so that the browser does a redirection.
- If the 'web_main_redirect' option is not set, the web_run_script is
transparently executed. In this case, the browser has no way to know which
'real' URL was executed.
The choice of the value to give to this parameter depends on the software you
package. If the web_run_script uses relative links, it may be better to set the
web_main_redirect option,
as relative links are resolved by the browser, but there is no simple rule for
this.
2.4.3.40 - web_run_script
Type: Subfile path
The script to run, in web direct access mode, when :
- the URL we receive does not contain any subfile path,
- or when the requested subfile path is not authorized (by the 'web_access'
option).
2.4.4 - Options reference table
| Option name |
Type |
Default |
Info only |
Expert
only |
Comments |
| author | String (URL) |
Empty |
 |
| |
| auto_umount | Boolean |
False | |
| |
| crc_check | Boolean |
False | |
| |
| test_script | Subfile path |
<none> | |
| |
| cli_run_script | Path |
<none> | |
| |
| compress_max_size | Integer |
No limit | |
| Unit = bytes |
| compress_min_size | Integer |
0 | |
| Unit = bytes |
| compress_ratio_limit | Percentage | 90 | |
| |
| copyright | String (URL) |
Empty |
 |
| |
| distribution | String (URL) |
Empty |
 |
| |
| help_prefix | Subfile path |
<none> |
 |
| |
| icon | Subfile path |
<none> |
 |
| |
| icon_bgcolor | HTML color spec |
<auto> |
 |
| |
| icon_width | HTML width spec |
<auto> |
 |
| |
| info_script | Path |
<none> |
 |
| |
| lib_run_script | Subfile path |
<none> | |
| |
| license | String (URL) |
Empty |
 |
| |
| license_prefix | Subfile path |
<none> |
 |
| |
| max_php_version | String |
<none> | |
| |
| mime_types | Array |
Empty | |
| Keys=suffix ;
values=mime types |
| min_php_version | String |
<none> | |
| |
| mount_script | Subfile path |
<none> |
 |
| |
| name | String |
<auto> |
 |
| Default = PHK file
name |
| packager | String (URL) |
Empty |
 |
| |
| phpunit_package | Subfile path |
<none> | |
|
|
| phpunit_test_package | Subfile path |
<none> | |
|
|
| plain_prolog | Boolean |
False | |
 |
|
| plugin_class | Class name |
<none> | |
| |
| prolog_code_creator | Boolean |
False | |
 |
|
| release | String |
Empty |
 |
| |
| required_extensions | Array |
Empty | |
| Extension names
without file suffix |
| requires | String + URL |
Empty |
 |
| |
| summary | String + URL |
Empty |
 |
| |
| tabs | Array |
Empty |
 |
| Key=String to display
in tab;
Value = Subfile path |
| umount_script | Subfile path |
<none> | |
| |
| url | URL | <none> |
 |
| |
| version | String |
Empty |
 |
| |
| web_access | Array |
Empty | |
| Array of subfile
paths |
| web_main_redirect | Boolean |
False | |
| |
| web_run_script | Subfile path |
<none> | |
| |
3 - Building the package
PHK packages are built in command-line mode. On Unix, you use a shell
command. On windows, you start a command window.
The syntax to build a package is :
php <path to PHK_Creator.phk> build <dest-file> <PSF>
[args] |
where :
- <path to PHK_Creator.phk> is the absolute path to the PHK_Creator.phk
file,
- <PSF> is the path to the PSF you just created,
- <dest-file> is the path where the new PHK package will be created (if a
previous file exists with the same name, it will be overwritten),
- [args] are optional arguments the PSF can retrieve using the $(<number>)
syntax.
if the PHP interpreter is not in your path, you must replace 'php' with its
absolute path.
During the build process, PHK_Creator displays some information. Here is some
typical output :
Processing /license.txt
Compressing (zlib)
Processing /smarty-logo-orange.gif
Compressing (zlib)
No compression: Compression ratio exceeded (100%)
Processing /libs/Config_File.class.php
Registering Automap symbols
Stripping source
Processing /libs/Smarty.class.php
Registering Automap symbols
Stripping source
Processing /libs/Smarty_Compiler.class.php
Registering Automap symbols
Stripping source
Processing /libs/debug.tpl
...
Processing /tabs/TODO
Compressing (zlib)
--- Sections
Processing /FTREE
Processing /AUTOMAP
Processing /STATIC/tabs/left.gif
Processing /STATIC/tabs/right.gif
Processing /STATIC/tabs/bottom.gif
Processing /STATIC/tabs/tabs.css.php
Processing /STATIC/phk_logo.png
Processing /OPTIONS
Processing /BUILD_INFO
Writing PHK file to Smarty.phk |
For more examples, see the
'hello, world' tutorial and the demo packages'
building kits.
4 - Registering Automap symbols
In most cases, symbol registration is a transparent process and you don't
have to care about it. The following information can be used for
troubleshooting or for advanced cases.
4.1 - PHP source files detection
When creating the package, PHK_Creator needs to determine which files must be
considered as PHP source files. Only these files will be scanned for symbols,
except if they were flagged as '-autoload=false' in the PSF.
The default rule is to consider as PHP source files :
- the files whose suffix contains the 'php' string,
- and the files whose mime type is explicitely set to
'application/x-httpd-php'.
So, if you want to force registration on PHP source files with unusual suffixes,
add these suffixes to the mime-types option in the PSF, and give them an
'application/x-httpd-php' mime type. Then, PHK will consider them as PHP
sources.
When embedding a PHK package (see 'Meta-packages' below), this is
detected and PHK packages are handled in a specific way (direct transfer between
symbol maps).
4.2 - Advanced directives
These directives are considered as 'advanced' as, in most cases, the
registration process is transparent and does not need any explicit
configuration. But, for special cases, it is possible to force or inhibit the
declaration of a symbol in a script file.
These directives can be added to PHP source files as specially formatted
comments. The syntax is :
// *<Automap>: command arguments |
Note that :
- there must be exactly one space between '//' and '*'.
- The directive can appear anywhere on any line in the file, as they are all
read before the scan starts.
4.2.1 - declare
Explicitely declares a symbol as defined by this source file.
Syntax :
// *<Automap>: declare <type> <symbol> |
where <type> is a letter from this list :
- 'F' : function
- 'C' : Constant
- 'L' : Class or interface
Examples :
#-- Declares a class named 'MyClass'
// *<Automap>: declare L MyClass
#-- Declares a constant
// *<Automap>: declare C A_NEW_CONSTANT |
4.2.2 - ignore
This directive will instruct the registration process to explicitely ignore a
symbol that it would normally register. Use this when you don't want a specific symbol to go to the
automap.
The syntax is similar to 'declare' :
// *<Automap>: ignore <type> <symbol> |
4.2.3 - no-auto-index
This directive does not take any argument. When present in a file, the file
is not scanned for symbols.
Usage :
// *<Automap>: no-auto-index |
4.2.4 - skip-blocks
The default behavior of the registration process is to extract the symbols from
the code, even if they are inside a conditional block.
When the 'skip-blocks' directive is present in a file, the conditional blocks
are not searched for symbols any more.
Example :
# Here the MyClass class won't be registered.
// *<Autoload>: skip-blocks
if (!class_exists('MyClass',false))
{
class MyClass {}
} |
Symbols defined inside a function or class are always ignored by the
registration process, as including the file does not always declare the symbol.
If you want these embedded symbols to be in the map, declare them explicitely
using '<Automap>:declare' statements.
Example :
// In the following code, the 'define_foo_gateway' function will
// be registered, but not the 'foo_gateway' class.
function define_foo_gateway()
{
if (!class_exists('foo_gateway',0)) {
class foo_gateway
{
... |
5 - Meta-packages
Meta-packages are PHK packages including another package as a subfile.
There are several cases where meta-packages are interesting :
- When embedding unit tests with a package, it allows to keep the code and
automaps separate. With such an approach, embedding the unit tests does
not imply any speed penalty when running the package as, until the tests are
executed, the test package is totally ignored. Separating automaps is most
important point here, too.
- You may group several PHK packages, with or without dependencies. This way,
as they are merged in a single package file, it is easier to maintain, distribute, install,
etc. It is also faster because they won't be mounted until one of their
symbols is required, and only the needed packages will be loaded.
- In a similar way, it can allow to package an application with its
dependencies.
- And probably a lot of other cases, as it is a very powerful feature.
5.1 - Autoloading sub-packages
You can specify whether an embedded package exports its symbols to
the higher-level map or not, using the 'autoload' modifier on the embedded
package's entry. By default, the symbols are exported to the upper-level
package.
When symbols are exported, the including package will
automatically mount an embedded package when one of its symbols is referenced.
So, as this feature is recursive, by default, every symbol of every embedded
package is present in the upper-layer map and can be autoloaded, even if the
corresponding package is not currently mounted.
Sometimes (for instance when embedding a package containing unit tests), you
don't want the embedded package's symbols to be merged into the main map (see
the Zend framework library and PHPUnit demonstration packages for examples). In
such cases, you will include the embedded packages with a '-autoload=false' modifier.
6 - Examples
The building kits for these packages
are available here.
6.1 - PHPUnit
PHPUnit was the first candidate, as it is used by other demonstration
packages to run their unit tests.
PHPUnit is a well programmed, clean OO software. So, it is easy to package. Here are the main steps :
- PHPUnit is totally OO except a single function, named
PHPUnit_Util_ErrorHandler. So, we had to explicitely require it through
Automap::require_function() before it is referenced in
Framework/TestResult.php.
- We don't include the '/Samples' subdirectory'.
- We exclude files in /Util/Skeleton to be scanned for symbols as they are
just templates.
- We filter every file through a very basic filter to :
- remove most 'require' directives,
- transform 'class_exists(...,false)' calls to 'class_exists(...,true)'.
- Transform 'realpath(__FILE__)' to '__FILE__' (realpath() does not
support stream wrappers).
6.2 - The Zend Framework library
The process is essentially the same as for PHPUnit, except a pair of code
changes to make it compatible with PHK.
We also had to modify the Loader method to call Automap
before trying a filename-based search.
The unit tests are included as an embedded package. It allows to keep them
separate from the main code, and to load the unit tests package only when we
want to run them. In such a case, it is essential to keep symbols in separate
maps, and the unit tests package must not export its symbols to the main map.
This example is especially interesting as the test package itself includes the
PHPUnit package, providing a three-level meta-package.
Please note that some unit test fail, when run under PHK, mostly because the
PHK virtual tree is read-only, and some tests try to create temporary files in
this tree.
The test package is built with uncompressed subfiles. Then we compress it as
a whole when we insert it in the main package. This way, the resulting package
is smaller and faster.
6.3 - The Zend Framework documentation
The documentation was split in API and reference, and then by language. As a
result, we get 6 independant packages.
These packages are quite basic and support web direct access mode
only.
6.4 - Smarty
Quite the same as ZF and PHPUnit, except :
- Smarty.class.php needs a small change because we want PHK URIs to be
considered as absolute paths.
- the package can be used as an example of webinfo tab addition.
Last update : Saturday, 19 January 2008
|