Claudiu Persoiu

Blog-ul lui Claudiu Persoiu


Archive for the ‘PHP’ tag

Closures, from Scheme to Javascript to PHP

without comments

The notion of closure in PHP, even though it appeared in PHP 5.3, as I’ve said before on my blog, it was properly done only in 5.4.

Wikipedia tells us:

In computer science, a closure (also lexical closure or function closure) is a function or reference to a function together with a referencing environment—a table storing a reference to each of the non-local variables (also called free variables) of that function.

In PHP this isn’t a very popular concept or very well-known. It is often mistaken for Anonymous Functions. But in functional programming languages it is very popular, because they really need it!

Scheme

When Brendan Eich designed JavaScript, relied on the Scheme language and ended up doing an implementation of this language with a C syntax. The C syntax was and is a lot more popular, and back then (1995) the Java programming language was very “fashionable”.

The Scheme syntax is similar to Lisp, in the sens that is using parenthesis abound expressions in order to execute them. The operators are defined as functions and just like them, there must be placed left of the parenthesis.

Let’s take an Scheme closure example:

(define (make-counter)
  (let ((count (begin 
                 (display "run parent function and return 0") 
                 0)))
    (lambda ()
      (set! count (+ count 1))
      (begin 
        (display "inside child function ") 
        count))))

The function is setting a “count” variable, with the value 0 and displays “run parent function and return 0”, then returns another lambda function, that is incrementing the variable defined in the main function and then displays “inside child function”.

I’m storing the resulting function in a variable in order to later run it multiple times:

> (define counter (make-counter))
run parent function and return 0
> (counter)
inside child function 1
> (counter)
inside child function 2

In other words, each time I’m calling (make-counter), it will return a new function that has access to the environment at the time at which it was created. If it looks strange because of the syntax, I promise that it will fell a lot more natural in JavaScript.

This concept is very interesting for encapsulation. The environment from the time when the parent function was been executed can be encapsulated, and later it can be used without worrying that it was changed by external causes.

For the functional programming languages this is a very interesting concept. Yet when it comes to object orientated languages, the concept seems almost useless, because objects also have the purpose of encapsulation.

JavaScript

From the beginning JavaScript was a hybrid, a functional programming language, object orientated, with prototype based inheritance. And if this wasn’t enough, the syntax was taken from Java (C).

JavaScript didn’t inherited a lot from Scheme, but it did inherit the closure concept.

A reason why there was a need for closures in Scheme is that that if a function is not finding a variable in its environment, it will search for it in its container’s environment. Let’s take an example:

(define x 1)
(define (add-in-env y) (+ x y))

If we call add-in-env with 2:

(add-in-env 2) -> 3

It looks just as ambiguous as in JavaScript, but is not exactly like that. In Scheme to do mutation is not that easy, simple and transparent, so an subsequent operation of:

(define x 2)

will result in an error.

In JavaScript resulted a hybrid. Mutation is permitted, but the notion of searching a variable in the current environment remained:

var x = 1;
var add_in_env = function (y) {
   return x + y;
}

add_in_env(2); // returns 3

Up to this point is ok, but for:

x = 2;
add_in_env(2); // returns 4

For this case, things can get out of hand very easy:

But, in order to solve the issue, we can just define a variable in the environment that will finish execution (will close):

var make_counter = function () {
   console.log("run parent function and set counter to 0")
   var count = 0;

   return function () {
       count = count + 1;
       console.log("inside child function");
       return count;
   }
}

var counter = make_counter();
console.log(counter());
console.log(counter());

var counter2 = make_counter();
console.log(counter2());
console.log(counter());
console.log(counter2());

The output will be:

run parent function and set counter to 0
inside child function
1
inside child function
2
run parent function and set counter to 0
inside child function
1
inside child function
3
inside child function
2

Even though the main function finished executing, the environment inside it is kept as a closure for the function that was returned. Only when there aren’t any more references to the sub-function the memory allocated for the closure will also be deallocated.

Even though JavaScript has objects, it doesn’t have private methods. An approach is to add a “_” (underscore) in front of the function name and consider it private. From my point is like asking the developers that will later use the code to consider this function private. Of course this is not very consistent.

Let’s take an example:

var obj = {
   _secretFunction : function (key) { console.log(‘do secret ’ + key) },
   doStuff : function (key) { this._secretFunction(key) }
}

obj.doStuff(‘stuff’); // do secret stuff

It seems that there is a public method “doStuff” and a private one “_secretFunction”. Nevertheless you can not prevent a user from calling “_secretFunction” or even worse, to modify it:

obj._secretFunction = function (key) { console.log('new secret ' + key); }

obj.doStuff('stuff'); // new secret stuff

If we want to hide the function, and make this obvious for everybody, again, we can use closures:

var obj = (function () {
   var secretFunction =  function (key) { console.log(‘do secret ’ + key) }

   return {
      doStuff : function (key) { 
         secretFunction(key) 
      }
   }
})();

obj.doStuff(‘stuff’); // do secret stuff

Because the parent function was not stored but rather immediately executed, basically the space in which secretFunction was defined has already finished its execution, encapsulating the logic. The object returned can call the function because it was defined in the same environment as the object.

Looks complicated at first, but is really very easy when you understand the concept.

And then it was… PHP

PHP includes a lot of different options. It was originally developed as a Perl framework, later the engine was rewritten in C.

PHP is a dynamic language that includes a lot of concepts, from objects, interfaces and anonymous functions, up to goto labels. The development direction for the language is not very clear, it rather offers the possibility for different approaches.

In the weird PHP history, somewhere in version 4, syntax for Anonymous Functions was added, but only in PHP 5.3 a more “normal” version appeared.

Also in version 5.3 the first closure version was introduced:

$scalar = 5;

$closure = function () use ($scalar) {
     return 'Scalar: ' . $scalar . PHP_EOL;
};

echo $closure(); // Scalar: 5

$scalar = 7;

echo $closure(); // Scalar: 5

This version mostly worked, but you had to specify what you want to send to the closure.

And there were other inconveniences:

<?php 
class Foo {         
   private function privateMethod() {                 
      return 'Inside private method';         
   }

   public function bar() {                 
      $obj = $this;                 
      return function () use ($obj) {                         
         return $obj->privateMethod();
      };
   }
}

$obj = new Foo();
$closure = $obj->bar();
echo $closure();

Fatal error:  Call to private method Foo::privateMethod() from context '' in [...][...] on line 10

Is not working because you can not send $this as a parameter to a closure, and if you try the above trick you still can’t access the private methods. Remember, this was happening in PHP 5.3.

The idea to introduce a closure of this kind seems strange to me. But this is not the first time something “strange” is introduced in PHP, as I was saying before about the Anonymous Functions. Sometimes is looking like work in progress.

I think everybody was expecting a more JavaScript like closures. I think that JavaScript had a big influence in making this concept so popular.

In version PHP 5.4 things changed, we finally have a closure as we would expect:

class Foo {
   private function privateMethod() {
      return 'Inside private method';
   }

   public function bar() {
      return function () {
         return $this->privateMethod();
      };
   }
}

$obj = new Foo();
$closure = $obj->bar();
echo $closure(); // Inside private method

And it works!

You can even do:

unset($obj);
echo $closure();

and it will work, because the object in which the closure was defined remains in memory until either the script finishes execution, or a call like this is made:

unset($closure);

For more details on how closures work in PHP 5.4, check out this post.

Written by Claudiu Persoiu

10 April 2013 at 10:02 AM

Passing Magento Developer Plus certification

with 3 comments

Over an year ago, I started working on the Magento platform. In last year’s spring, a colleague from Optaros took the Magento Developer Plus certification exam. Since then, I began to like the idea of taking the certification exam, more as a motivation to learn the ins and outs of Magento.

Few months ago I was enrolled into a company study group for the certification. This was the first time I was sponsored for a certification (yes, until now everything was with my money). Preparing in a study group was a whole different experience.

Those who have more experience in a field balance the situation for the others and can give better examples from their own experience. It’s easier to understand from concrete examples then to try to imagine the scenarios yourself.

The certification is available through Prometric. So when you decide that you’re ready you can go to the website to purchase the voucher and schedule the exam.

The price for a voucher is 260$, not exactly cheap, but if you get to convince your boss to pay, it probably won’t be so bad. 🙂

But let’s get to the more interesting subject, the preparation.

Materials
Magento is not doing very good on this subject, there are very few materials and they are not centralized.

My sources were:
Magento® Certified Developer Plus Exam Study Guide – it is compulsive to read the guide and try to find answers to all the questions in it;
Magento training – especially Fundamentals of Magento Development
– blogs – I don’t want to give any names, there are a lot of people that write about the problems that they encounter and blog about the exam.

Unfortunately there isn’t a way like for PHP, ZF and Symfony where you can find all you need in one place, basically it depends on your luck and searching skills, there isn’t an “official version”. Things become weird when you find different approaches that are version specific.

How did I prepare
I began with the video training. It’s not perfect by it’s very helpful. I think the problem with most certifications is that you don’t get to work with all the available modules, just like in PHP you don’t get to work that much with sockets and streams.

Even though you don’t get the code and sometimes it is hard to follow and transcribe the examples, I think that the video tutorials are one of the most important sources at the moment.

Secondly, with the Study Guide in my hand, I began to try to answer the questions from it. When I joined the Study Group, the work divided between all the members in the group. My advantage was that it was the second generation of the group and we could profit from the documentation already developed by the first group.

If you’re preparing by yourself, I think the most important thing is to start, that’s the hardest part. And if you don’t know where to start, Google search the Magento questions, there are already a lot of people that are posting the explanations.

Answers for the questions from the first chapters are the easiest to find. As the number of the chapter is getting bigger, the number of Google results decreases.

But after the first questions, you should understand what is all about and in theory you will no longer need the documentation.

Use Mage::log(Varien_Debug::backtrace(true, false)); for stack trace and xdebug (http://xdebug.org/) to see what’s going on behind the scene. With patience, all the questions find their answers.

Because it was a group, the study was easier for me, but even so, to be sure of the explanation I has to dive deep in the code.

The exam
Some of the questions are difficult, but there are also accessible ones. The questions in the exam are off all levels of difficulty.

For Plus, the exam takes 2h not 2.5h as it is specified in the guide.

If you opted for Plus, there are 11 questions from Enterprise and advanced difficulty questions, of which 7 correct ones are required to pass. Basically this is the difficulty difference. For this questions it matters how much Enterprise experience you have.

In the guide for each exam, the questions are broken in percentages for each chapter.

Because in the non Plus certification there are no Enterprise questions, you only have to answer the necessary percentage from the full exam in order to pass and it’s not required to have a certain percentage from a certain chapter.

Things that are done regularly are analyzed in detail, it is important to understand how each function that is approached in each chapter works and what is the purpose of all those tags in the xml files.

Usually there are things you work with, or at least with which there is a good probability you have been working from the modules listed in the guide.

Post exam
Before you leave the room you’ll know if you’ve passed or not. When you exit the room you’ll receive a printed paper with the correct number of questions from each section from the total number .

In case you haven’t been successful you’ll receive by mail from Magento a voucher with a discount for a future attempt. They state that you should study at least 3 more weeks before you try again. Anyway, after you’ve taken the exam you’ll have a better view over your overall knowledge for a future attempt.

After few days (3 in my case) you will be able to see your profile on the Magento website as a reference.

The diploma got to Romania in about a month, the delivery address is the one from the Magento website account.

Best of luck!

Written by Claudiu Persoiu

16 February 2013 at 8:23 PM

Posted in Magento,PHP

Tagged with , , ,

There is life without PHP 6 – 2012 retrospective

with 3 comments

Another year has passed without native unicode support for PHP. Yes, PHP6 is not here yet, in case anybody was still asking…

But, the version that is now here is PHP 5.4. With this version only refinements were added, there weren’t changes as big as there were on PHP 5.3. In PHP 5.4, the big addition are “traits” and, my favorite, the new version for closure.

As the keywords for last year were Drupal and Magento, this year the keyword was only Magento.

A couple of months ago, more or less forced by the circumstances, I’ve taken the Magento Plus certification exam. For this certification, Optaros, my employer, had a major influence. We had been more or less made to take the exam and we also had to be part of a company level study group.

I haven’t been part of a study group since faculty, and I must admit that I’ve forgotten how useful it is. Colleagues with more Magento experience (unlike me who I’ve been working with Magento for a little more than an year), had helped a lot to clarify issues and to document them.

But more about this in another blog, that will follow shortly (I hope)…

Anyway, after studying Magento in so much detail, I must admit that I have a lot more respect for the platform. After you analyze the backend architecture, a different picture is emerging. The architecture is very interesting and quite flexible, which makes you overlook some of it’s shortcomings.

Now that a new year has begun, I wish I’m going to publish more, I think in the last period I haven’t been very “productive” when it comes to publishing, either text or code.

Also this year I want to take at least another certification exam. As the Magento certification was set only for this year, I still have a lot of options on my plate.

That’s about all for 2012 and plans for 2013.

I wish you an excellent 2013!

Written by Claudiu Persoiu

14 January 2013 at 9:54 AM

Posted in Diverse,PHP

Tagged with , ,

PHP 5.4 was released!

without comments

PHP 5.4 was released!

Even though is already yesterday news… literally, yesterday 1 March was released.

The complete list of changes is available on php.net.

I’m sorry that we still don’t have scalar type hinting in this version. The only change to type hinting was the “callable” word was added, about which I’ve talked in the closure in PHP 5.4  blog.

Another interesting thing is that this time register_globals and magic_quotes_gpc were really removed, so the old PHP 4 apps don’t get to be compatible anymore with the help of a couple of flags in php.ini.

Also the hex2bin() function was added, of course is not that important, but is interesting that the  bin2hex() function existed since PHP 4. 🙂

Written by Claudiu Persoiu

2 March 2012 at 9:43 PM

Posted in PHP

Tagged with , ,

Magento native stack trace

with 5 comments

There are moments when you need to see the stack trace, to know how a certain point was reached. There are two native functions for that in PHP: debug_backtrace() si debug_print_backtrace. The first one returns an array and the second will print the stack trace to the screen.

The problem is that this functions must be customized for Magento, because it is very possible that when you’re running debug_backtrace()  you can run out of memory before you can send the output to a log file.

Magento has a native function for that purpose: Varien_Debug::backtrace([bool $return = false], [bool $html = true], [bool $withArgs = true]). In order to send the resulting stacktrace to a log file you simply all it with:

Mage::log(Varien_Debug::backtrace(true, false));

This technique is very useful when you need to see where an certain object is initialized, and what methods were executed up to that point.

Written by Claudiu Persoiu

25 February 2012 at 11:48 AM

Posted in Magento,PHP

Tagged with , , ,

PHP 5.4 – Closures the right way!

with 5 comments

The concept of closure was introduced in PHP 5.3, with the new “more traditional” syntax for anonymous functions.

PHP 5.3

In PHP 5.3, a closure will rely on the term “use”, which was passing the variables to the anonymous function, making it a closure.

The problem is that the anonymous function will only be able to access the variables that have been passed with “use”. When it comes to objects, there are passed by reference by default, but scalar variables (int, string, etc.) are passed by value, as this is the default behavior in PHP 5+:

$scalar = 5;

$closure = function () use ($scalar) {
     return 'Scalar: ' . $scalar . PHP_EOL;
};

echo $closure(); // Scalar: 5

$scalar = 7;

echo $closure(); // Scalar: 5

Another problem is that you cannot pass $this when the anonymous function is declared inside an object, so only the public method and properties can be accessed inside the closure.

PHP 5.4

In PHP 5.4 the keyword “use” is optional, and the entire environment where the function was created is available inside the function.

The advantage is that when the anonymous function is created inside another function or method, the anonymous function has access to the environment where it was created, even after the execution of the environment is over. The objects from this environment will be unset, only after the last reference to the closure will be unset:

class testClass {

        private $changeableVar = 1;
        private $bigVar;

        public function __construct() {
                // Allocate a big variable so we can see the changes in memory
                $this->bigVar = str_repeat("BigWord", 5000);
        }

        /**
         * A method that returns the closure
         */
        public function closure() {

                return function () {
                        // Display the value of a private property of the object
                        echo 'Private property: ' . $this->changeableVar.PHP_EOL;

                        // Change the value of a private property of the object
                        $this->changeableVar = 2;
                };
        }

        /**
         * Method that displays a private property
         */
        public function showChangeableVar() {
                echo 'Private property in method: ' . $this->changeableVar.PHP_EOL;
        }

}

// Memory befor the objects is created
echo "Memory: " . memory_get_usage() . PHP_EOL; // Memory: 229896

// Create object
$testObj = new testClass();

// Create closure
$closure = $testObj->closure();

// Execute closure
$closure(); // Private property: 1

// Displaying the current value of the private property
$testObj->showChangeableVar(); // Private property in method: 2

// Memory befor object will be unset
echo "Memory: ". memory_get_usage() . PHP_EOL; // Memory: 266240

// Unset the object
unset($testObj);

// Memory after the object was distroyed, there is no big difference in memory
echo "Memory: ". memory_get_usage() . PHP_EOL; // Memory: 266152

// Run closure after the object in which it was created was unset
echo $closure(); // Private property: 2

// Unset closure and with it the object environment
unset($closure);

// Memotry after the las reference to the object (closure) is unset
echo "Memory: " . memory_get_usage() . PHP_EOL; // Memory: 230416

Callable type hinting

Another new feature introduced in PHP 5.4 regarding closures is the new “type hint”: “callable”. Actually callable is referring to any anonymous function, and even to a new way of calling a method of an object:

<?php

// A function that uses type hinting
function typeHinting(callable $a) {
     echo $a() . PHP_EOL;
}

// A closure
$closure = function () {
     return __FUNCTION__;
};

// Call the type hinting function with the closure
typeHinting($closure); // {closure}

class testClass {
     public function testMethod() {
          return __METHOD__;
     }
}

// A mock object
$testObj = new testClass();

// The new way of calling object methods
$objCallable = array($testObj, 'testMethod');

// Call type hinting function with the new method calling way
typeHinting($objCallable); // testClass::testMethod

I believe that only now we can really say that PHP supports closures, the right way!

Written by Claudiu Persoiu

11 February 2012 at 5:10 PM

Posted in PHP

Tagged with , , , ,

Magento dead end – Breadcrumbs

without comments

In one of my adventures in the Magento code. I’ve encountered the following problem: I had to add a link to the breadcrumb.

As the documentation is not so great, after a little debugging (not a lot), I’ve got in to the core Mage_Page_Block_Html_Breadcrumbs.

The method is quite self-explanatory: addCrumb($crumbName, $crumbInfo, $after = false). Since I was there, I took a look inside:

function addCrumb($crumbName, $crumbInfo, $after = false)
{
  $this->_prepareArray($crumbInfo, array('label', 'title', 'link', 'first', 'last', 'readonly'));
  if ((!isset($this->_crumbs[$crumbName])) || (!$this->_crumbs[$crumbName]['readonly'])) {
    $this->_crumbs[$crumbName] = $crumbInfo;
  }
  return $this;
}

What’s interesting is the $after parameter, as you can see, even though it has a default value, is not used anywhere. The rest work’s as expected, probably this is why people don’t complain so much about it.

Written by Claudiu Persoiu

3 February 2012 at 10:03 PM

Posted in Magento,PHP

Tagged with ,

Closures and lambda functions in PHP vs. JavaScript

with 2 comments

JavaScript and PHP support both lambda functions and closures. But the terms are poorly understood in both programming languages ​​and are often confused with each other.

Lambda functions

Also called anonymous functions. They refer to functions that can be called without being bound to an identifier. One of their purposes is to be passed as arguments. The Lambda name was introduced by Alonzo Church, inventor of lambda calculus in 1936. In lambda calculus all functions are anonymous.

JavaScript

In JavaScript lambdas are part of the standard set and there are the preferred method of defining functions.

For instance:

var add = function (a, b) {
     return a + b;
}
alert(add(1, 2)); // 3

Lambda functions are used almost in any context when it comes to JavaScript, like:

window.onload = function (e) {
     alert('The page has loaded!');
}

PHP

In PHP, lambda functions were introduced in version 4.0.1 using create_function. In version 5.3+ a similar syntax to JavaScript was added, a much more readable and elegant way of defining a function.

This means that in PHP there are two ways of creating a lambda function:

// PHP 4.0.1+
$add = create_function('$a, $b', 'return $a + $b;');

// vs.

// PHP 5.3+
$add = function ($a, $b) {
     return $a + $b;
};

echo $a(1,2); // 3

Lambda functions can be used as parameter for other functions, such as usort:

$array = array(4, 3, 5, 1, 2);
usort($array, function ($a, $b) {
     if ($a == $b) {
          return 0;
     }
     return ($a < $b) ? -1 : 1;
});

Even more, PHP 5.3+ allows calling an object as a anonymous function:

class test {
     function __invoke($a) {
          echo $a;
     }
}
$a = new test();
$a('test'); // 'test'

Closures

The closure is really the misunderstood concept of the two. In general confusion appears because closures may involve lambda functions. A closure refers to the ability of a function/object to access the scope in which it was created even if the parent function has ended it’s execution and returned. In other words, the function/object returned by a closure is running in the scope in which it was defined.

In JavaScript the notion of closure is part of the standard arsenal, because the language is not based on the traditional object model, but rather on prototypes and functions. But JavaScript has some traditional object model parts, like the fact that you can use “new” to construct an object based on a function that plays the role of a class. In PHP closures are more of an new way to approach problems, because PHP is part of the traditional object model family.

JavaScript

In JavaScript the notion of closure is widely used, it’s so popular because JavaScript is not a traditional object orientated language, but rather a functional one, based on prototype inheritance.

JavaScript doesn’t have Public, Private and Protected, but rather only Public and Private and objects an inherit from each other, without using classes.

Another issue is the scope, because the global scope is used by default. This issues can be fixed in an elegant fashion using closures:

var closure = function () {
     var sum = 0;
     return {
          add: function (nr) {
               sum += nr;
          },
          getSum: function () {
               return sum;
          }
     }
}();

closure.add(1);
closure.add(2);
console.log(closure.getSum());

In the example above, sum is a private property and in theory can only be accessed and modified by the closure function. The interesting part is that the parentheses from the end of the function definition, signify that this function will be immediately  executed and therefore will return the result which is an object. At this point the original function will only exist for serving the return object, encapsulating therefor the private variable.

Although the function has finished execution, through this closure the returned object can still access the variables defined in the function scope, because that was the environment in which it was created.

This becomes even more interesting when a function returns another function:

var counter = function () {
    var counter = 0;
    console.log('in closure');
    return function () {
        console.log('in the anonymous function');
        return ++counter;
    };
};
var counter1 = counter();

console.log(counter1()); // 1

var counter2 = counter();
console.log(counter2()); // 1
console.log(counter1()); // 2

The output will be:

in closure
in the anonymous function
1
in closure
in the anonymous function
1
in the anonymous function
2

What actually happens is that the first function is executed and returns an anonymous function that can still access the environment in which it was created. In my opinion this is where the confusion between closures and lambda functions comes from, because a function returns another function.

The difference between examples is that in the first one the closure function executes immediately, and in the second example when counter is executed it’s returning a result that is actually a function definition, which in turn can be executed. Of course the second example can be modified to act just like in the first example using parenthesis.

PHP

As I said above, the notion of closure in PHP is not as important as in JavaScript.

Considering that lambda functions are available in the language since version 4, closures only appeared with PHP 5.3+.

Because of the block scope nature of PHP, there is a better encapsulation but there is a lot less flexibility compared to JavaScript. Basically in PHP you must specify using the use instruction what will the anonymous function be able to access from the closure scope.

function closure () {
     $c = 0;
     return function ($a) use (&$c) {
          $c += $a;
          echo $a . ', ' . $c . PHP_EOL;
     };
}

$closure = closure();

$closure(1);
$closure(2);

Unlike JavaScript, in PHP closures can not return objects, or rather the object can not be bound to the scope in which it was created, unless you send the variables as a reference to the constructor, in which case is not very elegant and I can’t imagine a scenario that would absolutely need closure for this.

Like in the JavaScript examples, instead of parentheses “()” at the end of the function, in PHP to run a function immediately after defining it call_user_func() or call_user_func_array() can be used:

$closure = call_user_func(function () {
    $c = 0;
    return function ($a) use (&$c) {
        $c += $a;
        echo $a . ', ' . $c . PHP_EOL;

    };
});

$closure(1);
$closure(2);

Written by Claudiu Persoiu

16 April 2011 at 6:02 PM

Parse ini files in PHP

without comments

Why “ini” files? Because there are more convenient! Most servers in the *nix world have “ini” or “conf” configuration files. In the PHP world there are preferred PHP configuration files, which are usually arrays. Wouldn’t be more elegant to have an ini file without PHP code in it?

Fortunately PHP has a couple of native functions just for that: parse_ini_file and parse_ini_string.

The principle is very simple, you give an configuration ini file as a parameter and it will return an array.

A little example:

;config.ini

[simple]
number = 1
another = 2
fraction = 0.2

[escape]
path = /usr/bin/php
url = http://blog.claudiupersoiu.ro
error = '<a href="%path%">%error%</a>'

[array]
1 = a
2 = b
3 = c

To parse the previous file:

$config = parse_ini_file('config.ini', true);
var_dump($config);

The second parameter specifies if the sections will become keys in the resulting array. Honestly I don’t think of a case when that wouldn’t be useful.

Seems slow? In fact for the file above is faster to parse then to include an array already parsed. The difference on my computer is ~0.00002s.

But the above file is not exactly big, so let’s get to a more serious ini file, like php.ini. Here the difference was bigger in favor of array, which won whit an advantage of ~0.0003, which means about half of parsing time that was ~0.0006s.

Taking into consideration that my computer is pretty fast and concurrent request can add an overhead for big files, sometimes it is useful to use a cache of the ini file.

Fortunately this is easy to do in PHP.

$cache = var_export($config, true);

file_put_contents('cache/config.php', "<?php\n\$config = " . $cache . ';');

Now you just need to include cache/config.php file and of course regenerate it when something changes in the ini file.

PHP should have write permissions for the cache directory.

Written by Claudiu Persoiu

12 March 2011 at 11:38 AM

Posted in PHP

Tagged with , ,

PHP CLI Input/Output from keyboard, pipe or arguments

without comments

Somewhere in the certification guide there is a chapter dedicated to “streams”.

A small part of it represents the input, output and error streams from PHP.  C/C++ has famous stdio.h library, but few people knows that input from keyboard is possible in PHP too.

In short, this can be achieved with PHP://STDIN, PHP://STDOUT and PHP://STDERR.

As this subject is panicking a lot of developers that are studding for ZCE, let’s get the confusion out. A stream represents a flow of information, just like when your reading and internal or external file using fopen.

But as a programmer best understands from cod, let’s get to more practical stuff.

Input

For input there is PHP://STDIN.

The next script is reading input from the keyboard:

#!/usr/bin/php
<?php
// initializing the input stream
$input = fopen('php://stdin', 'r');

// welcome message
echo 'Type "exit" and then enter to exit' . PHP_EOL;

// reading the stream input
while($line = fgets($input, 1024)) {
 // exit condition with line terminator
 if($line == 'exit' . PHP_EOL) {
    echo 'bye bye' . PHP_EOL;
    break;
 }
 // displaying the input from the keyboard
 echo 'You say: ' . $line . PHP_EOL;
}

// close stream
fclose($input);

The first line of code is specially for Linux/Unix, and Windows users can remove it.

The cod above must be placed in to a file, like for instance testStream.php.

You must have execution rights for that file, witch can be achieved with:

chmod +x testStream.php

Then the file can be executed in Linux directly with:

$./testStream.php

In Windows you must give the absolute path to PHP, if the path is not already in the system include path:

>c:\php\php.exe testStream.php

Notice that the input is with “\n” or “\r\n” at the end of the line, that’s why I’m testing “exit” with the line terminator (PHP_EOL). I’m using PHP_EOL so it can work with both Linux/Unix and Windows.

Output

For output there is PHP://STDOUT.

Unlike input, the output is a lot less relevant. Basically the output is the standard one which can be achieved with echo and print.

But for educational purpose let’s modify the previous file to use PHP://STDOUT:

#!/usr/bin/php
<?php
// initializing the input stream
$input = fopen('php://stdin', 'r');

// initializing the output stream
$output = fopen('php://stdout', 'w');

// welcome message
fwrite($output, 'Type "exit" and then enter to exit' . PHP_EOL);
// reading the steam input
while($line = fgets($input, 1024)) {
 // exit condition with line terminator
 if($line == 'exit' . PHP_EOL) {
    fwrite($output, 'bye bye' . PHP_EOL);
    break;
 }
 // displaying the input from the keyboard
 fwrite($output, 'You say: ' . $line . PHP_EOL);
}

// close input stream
fclose($input);

// close output stream
fclose($output);

Basically there isn’t any change in the script, is just that the output was displayed using PHP://STDOUT explicitly.

Error

A more interesting subject then the output is the error stream.

Basically is more relevant in the Unix/Linux environment, probably is relevant in Windows too but I don’t know how to capture it. If your reading this blog and you know how to do this please leave a comment below.

And again let’s change the script so that error messages will use the proper stream. I’ll output an error each time the user enters more then 5 characters (I’m sorry but I don’t have a lot of ideas right now):

#!/usr/bin/php
<?php
// initializing the input stream
$input = fopen('php://stdin', 'r');

// initializing the output stream
$output = fopen('php://stdout', 'w');

// initializing the error stream
$err = fopen('php://stderr', 'w');

// welcome message
fwrite($output, 'Type "exit" and then enter to exit' . PHP_EOL);

// reading the steam input
while($line = fgets($input, 1024)) {
 // exit condition with line terminator
 if($line == 'exit' . PHP_EOL) {
    fwrite($output, 'bye bye' . PHP_EOL);
    break;
 }

 if(strlen($line) > 5) {
    fwrite($err, 'WARNING! Input greater then 5 characters: ' . $line);
    continue;
 }

 // displaying the input from the keyboard
 fwrite($output, 'Ai scris: ' . $line . PHP_EOL);
}

// close input stream
fclose($input);

// close output stream
fclose($output);

// close error stream
fclose($err);

By default in Linux error messages are displayed to the screen, but there are scenarios when the errors are redirected for instance to a log file .

To redirect the error messages to a log file 2>> is used like in the following example:

$./testStream 2>>testStream.log

Input from PIPE (|)

Let’s take the fallowing scenario: the output of a previous operation contains a serious of email addresses that are both valid and invalid. There should be two files: valid.txt with valid addresses and invalid.txt with invalid ones. The email addresses will be send to the script using pipe.

The list of email addresses will be simulated using a file called email.txt:

valid_addres@yahoo.com
another_valid@yahoo.co.uk
invalid@y.c
good@gmail.com
invalid addres@hotmail.com
foo

The name of the script will be emailTest.php:

#!/usr/bin/php
<?php
// initializing the input stream
$input = fopen('php://stdin', 'r');

// initializing error stream
$err = fopen('php://stderr', 'w');

// unlike the previous cases, here is tested for the end of the file
// because the input is not coming from keyboard
while(!feof($input)) {
 // the value is trimmed to remove line terminators
 $line = trim(fgets($input, 1024));

 // test email address
 if(filter_var($line, FILTER_VALIDATE_EMAIL)) {
    // direct output, equivalent to php://stdout stream
    echo $line . PHP_EOL;
 } else {
    // invalid addresses are redirected to the php://stderr stream
    // to be intercepted later
    fputs($err, $line . PHP_EOL);
 }
}

// close input stream
fclose($input);

// close error stream
fclose($err);

For testing I’ll simulate the output of email addresses with the cat command:

cat email.txt |./emailTest.php >valid.txt 2>invalid.txt

Now the files valid.txt and invalid.txt from the current directory contain the proper values.

Processing like this is very useful for complex operations. Basically is an alternative to Shell Scripting (linux) or Batch Scripting (windows), which are not as flexible.

Script arguments

Often is useful to send direct arguments to a script to have, for instance, a different functionality.

Let’s change the previous scenario to receive the name of the file that contains the email address, as a script argument.

The script arguments are automatically stored in the $argv variable. Notice the first element of the array ($argv[0]) is the name of the script!

The modified example is as follows:

#!/usr/bin/php
<?php

// the count stars at 1 to eliminate the name of the script
for ($i = 1; $i < count($argv); $i++) {
  // initializing the input stream
  $input = fopen($argv[$i], 'r');

  // initializing error stream
  $err = fopen('php://stderr', 'w');

  if(!$input) {
   continue;
  }

  // unlike the previous cases, here is tested for the end of the file
  // because the input is not coming from keyboard
  while(!feof($input)) {
   // the value is trimmed to remove line terminators
   $line = trim(fgets($input, 1024));

   // test email address
   if(filter_var($line, FILTER_VALIDATE_EMAIL)) {
     // direct output, equivalent to php://stdout stream
     echo $line . PHP_EOL;
   } else {
     // invalid addresses are redirected to the php://stderr stream
     // to be intercepted later
     fputs($err, $line . PHP_EOL);
   }
  }

  // close input stream
  fclose($input);

  // close error stream
  fclose($err);
}

Now just run the script with arguments:

$./argTest.php email.txt >valid.txt 2>invalid.txt

Written by Claudiu Persoiu

26 February 2011 at 2:35 PM

Posted in PHP

Tagged with , , , ,