Quickly create phar files using Box



    PharIs an analogue jarfrom the Java world, but only in relation to PHP. Pharpacks project files into a special archive and makes it easy to transfer and install the application without manipulating the project itself as an executable program.

    Description of phar from official documentation
    Phar archives are best characterized as a convenient way to group several files into a single file. As such, a phar archive provides a way to distribute a complete PHP application in a single file and run it from that file without the need to extract it to disk. Additionally, phar archives can be executed by PHP as easily as any other file, both on the commandline and from a web server. Phar is kind of like a thumb drive for PHP applications.


    For creating phar files in PHP, there is a rather branchy API , but there is a simpler and more convenient way - to use the Box project .

    JSON file format


    The Box project allows you to describe the process of creating a phar file in a convenient JSON format.

    The simplest file looks like this:

    {
        "files": ["src/Put.php"],
        "main": "bin/main",
        "output": "example.phar",
        "stub": true
    }


    where

    filesare the files that should be included in the phar

    main- the file that will be executed when the phar file

    outputis called - the name of the final pharfile

    stub- for console applications is set to true

    Here you can see the process of creating a phar file using an example of a simple project.

    It contains a list of all possible parameters box.jsonwith comments.

    Let's try to build a phar file using an example of a real project. Take the Nasgrate database migration system as an example .. “Traditionally,” this system is installed either through cloning the repository from GitHub, or through Composer. We will try to make a separate utility that you can simply download and start using without knowing anything about PHP at all.

    Create box.jsonat the root of the project

    {
      "chmod": "0755",
      "directories": ["src","app"],
      "files": ["README.md"],
      "main": "bin/nasgrate",
      "output": "nasgrate.phar",
      "stub": true
    }

    directories- this parameter contains a list of directories that will be entirely included in the project (in this case, the directory srcand app).

    files- if you need to include any specific files, list them here.

    We could for example rewrite box.json as follows

    {
      "chmod": "0755",
      "directories": ["src"],
      "files": ["app/console.php", "app/index.php", "README.md"],
      "main": "bin/nasgrate",
      "output": "nasgrate.phar",
      "stub": true
    }

    In addition to these two recording options, it is also possible to selectively include files in the project based on filters. For example, if external libraries were actively used in the project and they were located in a folder vendors, we would like to include the files of these libraries in the project, but exclude, for example, all tests. Then the file would look like this

    {
      "chmod": "0755",
      "directories": ["src"],
      "files": ["app/console.php", "app/index.php", "README.md"],
      "finder": [
        {
          "name": "*.php",
          "exclude": [
            "tests",
            "test"
          ],
          "in": "vendor"
        }
      ],  
      "main": "bin/nasgrate",
      "output": "nasgrate.phar",
      "stub": true
    }

    the section finderin this case says: “include all files with the extension *.phpfrom the directory vendorexcept the folders testsand test“.

    chmod- allows you to set pharfile permissions . In this case, we set 0755to make the file executable.

    The remaining parameters were described above.

    Box Installation


    The easiest (and recommended) installation method

    $ curl -LSs https://box-project.github.io/box2/installer.php | php

    then appears in the current directory box.phar.

    You can run it as php box.phar, or assign execution rights chmod 755 box.phar, rename it to box mv box.phar boxand transfer it to /usr/local/bin. Then it can be launched from anywhere just like that box.

    Alternative installation via Composer

    $ composer global require kherge/box --prefer-source

    or add it to an existing project

    {
        "require-dev": {
            "kherge/box": "~2.5"
        }
    }

    Check the installation

    $ box -v

    should display a description of the program and a list of possible options.

    Next, you need to check that in your php.inifile the parameter is phar.readonlyin 0, Offor false.

    We find out where our file is located, which is relevant for the console (if you run phpinfo (); through Apache, it will show you another php.ini):

    $ php -i | grep php.ini
    >> Configuration File (php.ini) Path => /usr/local/php5/lib
    >> Loaded Configuration File => /usr/local/php5/lib/php.ini

    Next, find the parameter phar.readonlyand put it in Off.

    [Phar]
    ; http://php.net/phar.readonly
    phar.readonly = Off

    Project compilation


    We go into the folder with the project (to the level where ours lies box.json) and start compilation

    $ box build -v

    The flag -vallows us to see what happens during the compilation

     Removing previously built Phar...
    * Building...
    ? Output path: /Users/dlevsha/Sites/nasgrate/nasgrate.phar
    ? Adding directories...
      + /Users/dlevsha/Sites/nasgrate/src/config.php
      + /Users/dlevsha/Sites/nasgrate/src/Driver/Base/Dump.php
      + /Users/dlevsha/Sites/nasgrate/src/Driver/Base/Generator.php
      + /Users/dlevsha/Sites/nasgrate/src/Driver/Base/Helper.php
      + /Users/dlevsha/Sites/nasgrate/src/Driver/Base/Migration.php
      + /Users/dlevsha/Sites/nasgrate/src/Driver/Mysql/Dump.php
      + /Users/dlevsha/Sites/nasgrate/src/Driver/Mysql/Generator.php
      + /Users/dlevsha/Sites/nasgrate/src/Driver/Mysql/Helper.php
      + /Users/dlevsha/Sites/nasgrate/src/Process/Base.php
      + /Users/dlevsha/Sites/nasgrate/src/Process/Console.php
      + /Users/dlevsha/Sites/nasgrate/src/Process/Server.php
      + /Users/dlevsha/Sites/nasgrate/src/template.sql
      + /Users/dlevsha/Sites/nasgrate/src/Util/Console.php
      + /Users/dlevsha/Sites/nasgrate/src/Util/Db.php
      + /Users/dlevsha/Sites/nasgrate/app/console.php
      + /Users/dlevsha/Sites/nasgrate/app/index.php
    ? Adding files...
      + /Users/dlevsha/Sites/nasgrate/README.md
    ? Adding main file: /Users/dlevsha/Sites/nasgrate/bin/nasgrate
    ? Generating new stub...
    ? Setting file permissions...
    * Done.

    After that, a file will appear in the project directory nasgrate.phar.

    Check that everything compiled fine.

    $ ./nasgrate.phar

    will display a description of the utility

    Nasgrate is a console utility that let you organise database schema migration process at a consistent and easy way.
    It supports mysql, mssql, postgresql, oracle and other databases
    Usage:
      php nasgrate [command] [options]
    Command:
      status     - displays migration status
      generate   - creates new migration (migration file)
      up:show    - displays (but not executes) SQL-query, executed by migration update
    ...

    Work with external resources


    A feature of the work pharis that he is looking for all the resources inside his archive. In most cases, this is not a problem, because it was for this that we phardid it so that it was independent of the environment. But there are a number of cases when resources inside the phararchive need to work with external files.

    For example, Nasgrate - you need to read the configuration from a file .environment, write migration files and status files to an external directory.

    If we try to specify a relative path inside the project, for example, how ../.environment, an error is generated, since there is pharno such file inside .

    There are two options for solving this problem:

    The first option is to map the external file to the internal space of the pharfile.

    Phar::mount('phar://.environment', '/etc/nasgrate/.environment');

    The problem is that you need to know exactly the absolute path to the file.

    The second option is to specify the path from the current location of the pharfile. Like that:

    define(DIR_RUN, dirname(Phar::running(false)));

    Next, you either use Phar :: mount to map it into the internal space pharor simply specify the absolute path to the configuration file. Assume the configuration file is in the same folder asphar

    define(DIR_RUN, dirname(Phar::running(false)));
    Phar::mount('phar://.environment', DIR_RUN.'/.environment');

    and then refer to it as a local file, or always refer to the absolute path.

    There is one remark, I do not know whether this is a bug or a feature, but all directories connected through Phar::mountare in readonly mode and how to change this is not very clear. When addressing the absolute path, such problems do not arise.

    Another one seems like an obvious point, but which is worth paying attention to. The phar file contains the resources of your project and does not regulate the presence of connected libraries to php itself, its version, etc. That is, if you use some kind of php extension, for example PDO, or even install something from PECL, or use some features of a specific version of php, your phar will not contain information about the runtime. If you use for example traits from PHP 5.4, and the user has 5.3, then an error will be generated. You must check all required dependencies inside your application.

    Related links:


    Also popular now: