8/25/2016

Getting Started with PHP Archives: PHAR

You can think of PHAR Archive as tar Archive or JAVA Archive (jar), but PHAR Archive serve specific purpose and more flexible.
  1. You can convert your PHP App into single Phar archive, So it saves space and easy to distribute
  2. If you want, you can compress it either using gz, bzip2 or zip compression Algorithms
  3. You can create executable Phar Archive which can have multiple endpoints, Endpoints server very different purpose, because, When you execute this Phar Archive from Command line, it will call, shell endpoint, But when you try to run that same archive using Browser, After putting it into web document Directory, it will look for (if Exists), web endpoint. That way you can create a single Phar archive which can we used as either command line utility, or when serve through web, it behaves like web app.
If You are facing any Error about, phar.readonly setting in php.ini file Then You need to Edit Your PHP Configuration File (In My case, php.ini) search for string phar.readonly and remove any Semi-colon before that line And set it to Off Example:- phar.readonly = Off

Example - Just create a simple Phar Archive for Given Directory

cd /tmp
mkdir first
cd first
# Create 10,000 Files for Testing purpose
php -r 'foreach(range(0,10000) as $i){ echo "$i\n"; $d=sprintf("%07d.txt", $i); file_put_contents($d, "Hello from $d\n"); }'


cd ..
# Now create a Phar Archive for all those generated Files
php -r "(new Phar('archive.phar', 0, 'archive.phar'))->buildFromDirectory('first');"
ls
# archive.phar


# Check Time taken by PHP Script to access individual File inside Phar Archive
time php -r 'echo file_get_contents("phar://archive.phar/0000693.txt");'
# Hello from 0000693.txt
#
# real  0m0.056s
# user  0m0.048s
# sys   0m0.000s


# Lets create a ZIP Archive for same Directory
zip -r first.zip first/

# Check out, How much size each archive is taking
du -h archive.phar first.zip first/
# 616K  archive.phar
# 1.8M  first.zip
# 40M   first/


# Lets read the same file inside ZIP File
time php -r 'echo file_get_contents("phar://first.zip/first/0000693.txt");'
# Hello from 0000693.txt
#
# real  0m0.198s
# user  0m0.120s
# sys   0m0.068s


Although phar:// wrapper supports reading zip, tar.gz, tar.bz2, phar Archives, i have checked all supported formats, and phar is taking less time to read individual file from archive.

Example - Lets me tell you structure of my app

/app
    /web
        assets/
            jquery
            bootstrap
        index.php
    /cli
        functions.php
        index.php
    /libs
    /vendors
    index.php

Example - Lets create Executable Phar Archive

<?php

# Case 1: When You want to include all Files from GIVEN Directory
// create with alias "project.phar"
$phar = new Phar('project.phar', 0, 'project.phar');
// add all files in the project
$phar->buildFromDirectory(dirname(__FILE__) . '/project');

# You can execute it from Command line or Just run it Using Your web Browser
# final public static string Phar::createDefaultStub ([ string $indexfile [, string $webindexfile ]] )
$phar->setStub($phar->createDefaultStub('cli/index.php', 'www/index.php'));

Example - Using Regex Filter to add matched files into Phar Archive

<?php
# Case 2: When You want to include all PHP (*.php) Files from GIVEN Directory
$phar2 = new Phar('project2.phar', 0, 'project2.phar');
// add all files in the project, only include php files
$phar2->buildFromDirectory(dirname(__FILE__) . '/project', '/\.php$/');
$phar2->setStub($phar->createDefaultStub('cli/index.php', 'www/index.php'));

Example - Create NEW Phar Archive for Given Directory

# Using Phar::buildFromDirectory API
php -r '(new Phar("users_arc.phar", 0, "users_arc.phar"))->buildFromDirectory("/home/ssp/www/app/users");'
# Using Phar::buildFromIterator API
php -r '(new Phar("app_arc.phar", 0, "app_arc.phar"))->buildFromIterator( new RecursiveIteratorIterator( new RecursiveDirectoryIterator("/home/ssp/www/app")), "/home/ssp/www/app");'

Example - How to convert TAR to Phar Archive

We will use PharData class to convert tar to phar Archive
<?php
try {
    $tarphar = new PharData('myphar.tar');
    // convert it to the phar file format
    $phar = $tarphar->convertToExecutable(Phar::PHAR); // creates myphar.phar
    $phar->setStub($phar->createDefaultStub('cli/index.php', 'web/index.php'));
    // Lets Create compressed Phar Archive
    $compressed = $tarphar->convertToExecutable(Phar::TAR, Phar::GZ, '.phar.tgz');
} catch (Exception $e) {
    // handle the error here
}

Example - Convert Phar to ZIP/Tar/TAR.GZ/TAR.BZ2 Archive

php -r '(new Phar("archive.phar"))->convertToData(Phar::ZIP);'
ls
// archive.phar  archive.zip
# To create tar.bz2 Archive
php -r '(new Phar("archive.phar"))->convertToData(Phar::TAR, Phar::BZ2, ".tbz");'

12/31/2015

New* FormGenLib - My JavaScript Library to dynamically Generate HTML Forms (Built-in Support for Bootstrap_v3)

Automatically Generate awesome looking HTML form using minimal JSON options (theme Bootstrap v3)

DEMO
https://shishtpal.github.io/formgenlib/
Released Development Version
contribute to project
Or Request some feature on github

Project is under Development, API may change

Input Types

general
checkbox
file
hidden
radio
select
textarea
text
password

Special Types

List (Allow You to send a list of values)
Set (Choose just one values for a given set of values)
Photo (Upload Photo Widget)
Clearfix
Date
Heading

Form Layouts

Because we are using Underscore Templating Engine, So, We can use Global Functions inside Templates. And some properties are not defined than you can check for them with the help of this special object reference Object.

Memorize Form State

Except Input Type file , Input Fileds can Memorize its State, And to Memorize form State, we are using data-value custom attribute with each input type. And when we render or load saved form from LocalStorage, formgenlib trigger load events, that we used to load value form data-value attribute and inject into that Input Fields.
There is one toolbar to save, clean and load form states.
  • clean - clear LocalStorage
  • save - Save Current Form State to LocalStorage
  • load - Load previously saved form State
    • You can save one state for one form
    • Because we are Using form_key attribute to save Form state into LocalStorage
    • If You want to load saved state from Server (Backend)
    • Then Each Component schema should have either value or values attribute according to their schema.

Example

  • This is sample Javascript code that Generate HTML form for First Time
    • And save to localStorage
  • Next, time Form will loaded from LocalStorage
  • If You want it to re-render HTML Form
    • Then set the value LocalStorage.isClean = "false"
## Example Code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
var i = new GenerateForm("#form_container");
var form = {
 form_key: "thisForm",
    action: "/apis/testing",
    method: "POST",
    caption: "Testing Simple Html Form",
    id: "mygenform",
    style: "border:2px solid red;",
    schema: [
  {
      type: "heading",
      cont_grid: [12],
      label: "Simple Hello world",
      label_class: " text-center btn-warning btn-sm",
      style: "",
      control_id: "demoworld"
  },
  {
   cont_grid: [12, 6, 4, 3],
   type: "text",
   label: "Name",
   title: "Your Name?",
   name: "name",
   placeholder: "Your Name ?"
  },
  {
   cont_grid: [12, 6, 4, 3],
   type: "text",
   label: "Email",
   title: "Your Email?",
   name: "email",
   placeholder: "Your Email ?",
   autocomplete: true
  },
  {
   cont_grid: [12, 6, 4, 3],
   type: "text",
   label: "Mobile No.",
   title: "Your Mobile No?",
   name: "mobileno",
   placeholder: "Your Mobile no. ?"

  },
  {
            type: "date",
            cont_grid: [12, 6, 4, 3],
            cont_style: "",
            label: "Admission Date",
            title: "Admission Date?",
            name: "admdate",
            control_id: "admdateID",
            style: "",
            placeholder: "01/05/2014",
            value: "05/08/1992"
        },
     {
      type: "clearfix"
     },
     {
      cont_grid: [12, 6, 4],
      type: "select",
      label: "Gender",
      title: "Gender?",
      name: "gender",
      control_id: "genderID",
      items: ["00|Other", "01|Male", "02|Female"]
     },
  {
      cont_grid: [12, 6, 4],
      cont_class: "",
      cont_style: "",
      type: "photo",
      label: "Select Photo",
      title: "Your Photo",
      name: "mypic",
      control_id: "myPhoto",
      img_default: "/_assets/img/elect001.png",
      img_alt: "My Photo",
      img_style: "",
      img_id: "myphotoid",
  },
  {
      cont_grid: [12,6, 4],
      cont_class: "",
      cont_style: "",
      type: "list",
      label: "Likes ?",
      title: "What You likes?",
      name: "likes[]",
      control_id: "mylikes",
      items: ["01|Play", "02|Reading", "03|Game"],
  },
  {
   type: "clearfix"
  },
  {
   cont_grid: [12],
   type: "textarea",
   label: "About me?",
   name: "aboutme",
   control_id: "aboutmeID",
   style: "background:cyan;",
   title: "About me",
   value: "Hello World"
  },
     {
      name: "Click",
      value: "Submit",
      control_id: "formsubmit",
      control_class: "btn-primary btn-block",
      style: "",
      type: "submit"
     }
    ]
};
i.config(form);
i.injectFormCompAsNew();
i.listen();


Checkout Project on Github
Thank You.