May 212013
 

In order to deploy application easier, we package java application in to a jar.

Now, in PHP we have phar.

In order to enable packaging in PHP, change the config from php.ini to phar.readonly = 0

Let’s write some code. create a new project with following directory:

sample1
    |
    |---build.php
    |---src
         |----index.php
         |----lib.php
    |---build/
    |---test/

It’s a very simple application, access the index.php, then index.php require lib.php, execute some function in lib.php, echo something in console.

in commons, it’s like

$php src/index.php
//echo it works.

we just write the index.php and lib.php as usual:

//index.php
<?php

include dirname(__FILE__)."/lib.php";

Foo::run();
</code><pre>

<code><pre>
//lib.php
<?php
class Foo
{
    public static function run()
    {
        echo PHP_EOL;
        echo 'it works!';
        echo PHP_EOL;
    }
}

</code>

This is very simple, but we want to package index.php and lib.php with phar, if they are packaged into one phar file, PHP can not load file via absolute path, just change one line: include

After some refactor, our index.php looks like:

<?php

include "phar://sample1.phar/lib.php";

Foo::run();

OK, out application should work with phar, we need a build script to create phar file.

let's add something into build.php

<?php
$srcRoot = dirname(__FILE__)."/src";
$buildRoot = dirname(__FILE__)."/build";
$phar = new Phar($buildRoot . "/sample1.phar",
    FilesystemIterator::CURRENT_AS_FILEINFO |
    FilesystemIterator::KEY_AS_FILENAME, "sample1.phar");
$phar["index.php"] = file_get_contents($srcRoot . "/index.php");
$phar["lib.php"] = file_get_contents($srcRoot . "/lib.php");
$phar->setStub($phar->createDefaultStub("index.php"));

Then, try to run:

$php build.php
$php build/sample1.phar

Now you have your first phar package. Do not worry about new features in PHP 5.4+, phar support namespace, let's see the second sample here:

sample2
  |
  |--build/
  |--build.xml/
  |--src/
  |   |--autoload.php
  |   |--saharabear/
  |   |            --phar/
  |   |                 --index.php
  |   |                 --Foo.php

//index.php
<?php

require_once "phar://sample2.phar/autoload.php";
use saharabear\phar\Foo;
Foo::run();

//Foo.php
<?php
namespace saharabear\phar;

class Foo
{
    public static function run()
    {
        echo PHP_EOL;
        echo 'it works!';
        echo PHP_EOL;
    }
}

//autoload.php
<?php

class PharSampleAutoload {
  static public function loader($className) {
      $filename = "phar://sample2.phar/".str_replace('\\', '/', $className) . ".php";
        if (file_exists($filename)) {
            include($filename);
            if (class_exists($className)) {
                return TRUE;
            }
        }
        return FALSE;
    }
}

spl_autoload_register('PharSampleAutoload::loader');

//build.php
<?php
$srcRoot = dirname(__FILE__)."/src";
$buildRoot = dirname(__FILE__)."/build";
$phar = new Phar($buildRoot . "/sample2.phar",
    FilesystemIterator::CURRENT_AS_FILEINFO |
    FilesystemIterator::KEY_AS_FILENAME, "sample2.phar");
$phar->buildFromDirectory($srcRoot,'/\.php$/');
$phar["index.php"] = file_get_contents($srcRoot . "/saharabear/phar/index.php");
$phar->setStub($phar->createDefaultStub("index.php"));

Now, you get all sample. Source code is on github, you are free to clone.

May 202013
 

There are many configuration file format, pure php, yaml, ini, json or xml. json and xml are easy to parse in PHP, for json, just use json_decode($file);.

I think json is not good readable for human, ini and yaml is better. The different of ini and yaml is nest ability. yaml is easier to nested.

parse ini file

The sample code to parse ini file in PHP:

###### config.ini ######
db_driver=mysql
db_user=root
db_password=root

[dsn]
host=localhost
port=3306
dbname=localhost

<?php
//parse config.ini
$ini = dirname(__FILE__) . "config.ini" ;
$parse = parse_ini_file ( $ini , true ) ;
$driver = $parse [ "db_driver" ] ;

$dsn = "${driver}:" ;

foreach ( $parse [ "dsn" ] as $k => $v ) {
    $dsn .= "${k}=${v};" ;
}

parse yaml

what is yaml

YAML is a human friendly data serialization
standard for all programming languages.

parse yaml via php

sitename: saharabear.com
date: "2012-05-01"
contact:
    number: 1585410
    address: |-
        RM 807 No 1000 
            Shunhua RD
    city: Shanghai
business:
    development:
        price: something
    testing:
        price: something

<?php
//parse config.yaml
$parsed = yaml_parse_file(dirname(__FILE__).'/config.yml');
var_dump($parsed);
//that's all

At last, do not use Windows as PHP development platform, do not use Windows as Python development platform, do not use Windows as Lua development platform, wasted too much time on working environment.

Slackware or FreeBSD is better.

Apr 152012
 

In symfony2, if you want to get value from request, you have many ways:

forst, bind request to form, then you can use the entity, official document has details.

If you are using formtype, there is another two ways to get value,

first:

$postData = $request->request->get('slackiss_bundle_qingbundle_registertype');
$name_value = $postData['email'];

second:

$email = = $form["email"]->getData();

or

$defaultData = array('message' => 'Type your message here');
$form = $this->createFormBuilder($defaultData)
->add('name', 'text')
->add('email', 'email')
->add('message', 'textarea')
->getForm();

if ($request->getMethod() == 'POST') {
$form->bindRequest($request);

// data is an array with "name", "email", and "message" keys
$data = $form->getData();
}

If you do not use formtype, I mean, you are not using {{form_widget}}, you can get values:


echo $request->request->get('email');

About $request, the code is like:

public function doAction(Request $request)
{
}

or

$request = $this->getRequest();

Jan 122012
 

Here is a trick to compare two dates in Twig. Convert them as string with the date filter, with first the year, then the month and finally the day:

myDate|date('Y-m-d')

Then, you can compare strings because the chronological order is the same than the lexicographical order:

{% if date1|date('Y-m-d') > date2|date('Y-m-d') %}
    {# ... #}
{% endif %}

Tip. If you want to get the current date, you can give the string now to the date filter:

{% if "now"|date('Y-m-d') > date2|date('Y-m-d') %}
    {# ... #}
{% endif %}
Jan 122012
 

Remember that the main advantage of standards is that every piece of code looks and feels familiar, it’s not about this or that being more readable.

Since a picture – or some code – is worth a thousand words, here’s a short example containing most features described below:

<!--?php 

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com-->
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Acme;

class Foo
{
    const SOME_CONST = 42;

    private $foo;

    /**
     * @param string $dummy Some argument description
     */
    public function __construct($dummy)
    {
        $this-&gt;foo = $this-&gt;transform($dummy);
    }

    /**
     * @param string $dummy Some argument description
     * @return string|null Transformed input
     */
    private function transform($dummy)
    {
        if (true === $dummy) {
            return;
        }
        if ('string' === $dummy) {
            $dummy = substr($dummy, 0, 5);
        }

        return $dummy;
    }
}

Structure

  • Never use short tags ( closing tag;
  • Indentation is done by steps of four spaces (tabs are never allowed);
  • Use the linefeed character (0x0A) to end lines;
  • Add a single space after each comma delimiter;
  • Don’t put spaces after an opening parenthesis and before a closing one;
  • Add a single space around operators (==, &&, …);
  • Add a single space before the opening parenthesis of a control keyword (if, else, for, while, …);
  • Add a blank line before return statements, unless the return is alone inside a statement-group (like an if statement);
  • Don’t add trailing spaces at the end of lines;
  • Use braces to indicate control structure body regardless of the number of statements it contains;
  • Put braces on their own line for classes, methods, and functions declaration;
  • Separate the conditional statements (if, else, …) and the opening brace with a single space and no blank line;
  • Declare visibility explicitly for class, methods, and properties (usage of var is prohibited);
  • Use lowercase PHP native typed constants: false, true, and null. The same goes for array();
  • Use uppercase strings for constants with words separated with underscores;
  • Define one class per file;
  • Declare class properties before methods;
  • Declare public methods first, then protected ones and finally private ones.

Naming Conventions

        • Use camelCase, not underscores, for variable, function and method names;
        • Use underscores for option, argument, parameter names;
        • Use namespaces for all classes;
        • Suffix interfaces with Interface;
        • Use alphanumeric characters and underscores for file names;
        • Don’t forget to look at the more verbose Conventions document for more subjective naming considerations.

Documentation

      • Add PHPDoc blocks for all classes, methods, and functions;
      • Omit the @return tag if the method does not return anything;
      • The @package and @subpackage annotations are not used.

Put braces on their own line for classes, methods, and functions declaration;