Zend Z-Ray: How to run it on PHP’s built-in web server

Posted September 27th, 2015 in Razno, Tehnikalije by Metod

Zend Z-Ray: How to run it on PHP’s built-in web server

In early August I, amongst other ZCEs, got an invitation from Zeev to give their Technology Preview of Zend Z-Ray a try. However, since all systems I could test this on with Apache installed were CentOS and they only support it on Debian / Ubuntu, I had to try it in another way.

So I had a box without Apache installed and for reasons beyond the scope of this post could not install it. So, basically I had an extension that would run just fine, I just needed something to access it’s Web UI.

And so the router script for PHP’s built-in web server came about. You can find it on GitHub.

https://github.com/smottt/zray-builtin-php-server

git clone https://github.com/smottt/zray-builtin-php-server.git

You can grab the Zend Z-Ray Technology Preview here.

Now all you need to do is follow the installation instructions from Zend (ignore the apache part) and run the web server.

php -S localhost:10081 router.php

You can of course bind it to another port and/or host, that works just fine. Then just navigate to the host:port URL and you will see the UI.

Navigate to Z-Ray Live! and you can now monitor any CLI script that is being executed. This way you can get extensive debugging information on any cron script that is running in the background.

Zend Z-Ray Live!

Symfony2: Reload user roles

Posted June 22nd, 2012 in Razno, Symfony2, Tehnikalije by Metod

If you are not using FOSUserBundle for managing your user system, then you might have stumbled onto a problem of reloading user roles when you change them. Here is a possible solution.

Your UserInterface::equals() method might look something like this:

Now all you need to do is change it so it also checks the user roles:

And it should work!

Now whenever you change any user’s roles it will be effective immediately after the next page refresh instead of logout / login.

Quick tip: Joomla white page and rsync

Posted April 15th, 2012 in Razno, Tehnikalije by Metod

I recently worked on a joomla page. And since I love rsync, I made myself a build/sync script to update the page on the test server. The command was similar to the following:

$ rsync --exclude-from=build/rsync.exclude ...

The contents of rsyn.exclude contained:

cache/*
logs/*
tmp/*
...

But when I first ran the script, all I got was a white blank page. No apache errors, no PHP errors. Strange. Then it hit me. Joomla has some cache classes within cache/ directories. So removing the cache/* from rsync.exclude and running the script again made it work.

Of course then there is another matter of clearing the cache, but it is beyond the scope of this quick tip.

Symfony2: How to set the correct host for routing in console command

Posted March 31st, 2012 in Symfony2, Tehnikalije by Metod

Quick tip for setting the correct host in your custom symfony2 command.

$this->getContainer()->get('router')->getContext()->setHost('www.example.com');

This will set your host correctly for routing and it will no longer default to ‘localhost’.

A bit longer version:

Serialization of UploadedFile is not allowed fix

Posted January 31st, 2012 in Razno, Tehnikalije by Metod

If you are doing file uploads in Symfony2 with help from the cookbook tutorial you might have ran into the following error:

Serialization of ‘Symfony\Component\HttpFoundation\File\UploadedFile’ is not allowed.

The solution I came up with involves excluding the public $file field from serialization. That way we bypass the exception.

One catch, though: this will exclude all fields that are not protected.

Add the following function to your entity:

Enjoy!

Symfony2 Error: UsernamePasswordToken::serialize() must return a string or NULL

Posted December 5th, 2011 in Razno, Tehnikalije by Metod

Getting the following error? Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken::serialize() must return a string or NULL

I was getting it while trying to login a user. The thing was, in my Role entity, all properties were private.

class Role implements RoleInterface
{
    private $id;
    
    private $name;
    
    private $created_at;
    
    // ...
}

When doing some googling and checking things out, I found this comment on php.net which gave me an idea. I changed all private properties to protected and thing worked!

class Role implements RoleInterface
{
    protected $id;
    
    protected $name;
    
    protected $created_at;
    
    // ...
}

How to use Pagerfanta with Symfony2 and Doctrine2

Posted November 27th, 2011 in Tehnikalije by Metod

So let’s assume you want to use a pager with your Symfony2 application. If you are like me, you type it in google and get a link to KnpPaginatorBundle. Start using it and everything goes well, until you hit an error telling you something is wrong. That something is something in the lines of:

SELECT SUM(S.STH) AS something FROM ...

Which Zend_Paginator does not support! Here is where Pagerfanta comes into the picture.

Download the PagerfantaBundle or get it through git. Also get Pagerfanta. I decided to break PagerfantaBundle into 2 more folders. So the structure of the bundle is now:

vendor\bundles\WhiteOctober\PagerfantaBundle\...

For Pagerfanta, the structure is:

vendor\pagerfanta\src\...

Now, add both to autoload:

// app/autoload.php
$loader->registerNamespaces(array(
    // ...
    'WhiteOctober'     => __DIR__.'/../vendor/bundles',
    'Pagerfanta'       => __DIR__.'/../vendor/pagerfanta/src',
    // ...
));

Register the bundle with your application kernel:

// app/AppKernel.php
public function registerBundles()
{
    return array(
        // ...
        new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
        // ...
    );
}

Now what the official documentation does not tell you is what namespaces to include to use it.

For Doctrine2 the example Controller looks like this:

In the view (I assume you are using Twig) you just do:

{{ pagerfanta(examples) }}

And you can be done!

However, there is much more to Pagerfanta. You can pass in many configuration options. Here is where so called Global Variables come in handy. You can define them in app/config/config.yml:

twig:
    globals:
        pagerfanta_opts:
            prev_message: '«'
            next_message: '»'
            dots_message: ' ... '

Now you can access the ‘pagerfanta_opts’ in every template:

{{ pagerfanta(examples, 'default', pagerfanta_opts) }}

Where ‘default’ is the name of the Pagerfanta view.

For those who want to learn more about it, read the documentation on GitHub for Pagerfanta.

Login event listener in Symfony2

Posted July 11th, 2011 in Tehnikalije by Metod

So you have a Symfony2 project under construction. Login works. Now you want to execute some code right after the user successfully logs in.

The solution: Make a custom event listener.

An event listener is actually a service with a proper tag associated with it. So first step is to register the listener. The configuration file shown corresponds to the listener in file Acme/UserBundle/Listener/LoginListener.php. You can read more about services here.

In services.yml:

Let’s go through the configuration.

class defines the listener class.

With arguments we inject services that this listener depends on. In this case the security.context service for retrieving the User object and doctrine service for EntityManager.

tags is important. Every listener must be tagged with kernel.event_listener and must specify it’s event. For successful login that event is security.interactive_login. You can also specify the optional method tag.

Ok, our listener is registered. Let’s create it.

The above code should be pretty self-explanatory. The only required method is onSecurityInteractiveLogin(InteractiveLoginEvent $event). You do not need the other stuff, but you probably will if you want to modify the User object, or something else in the DB.

Multiple PHP versions with Apache 2, FastCGI, PHPFarm on Ubuntu

Posted December 2nd, 2010 in Tehnikalije by Metod

This tutorial is a part of the “Setting up your local development environment” series. It is based on this article while keeping in mind that in previous apache tutorial we compiled apache from source. So I’m definitely not taking all the credit for it. But there are some modifications.

Starting with PHPFarm, we need Git installed in order to check it out. If you don’t have it installed:

sudo apt-get install git-core

Now create a directory in which PHP versions will reside. The directory of my liking is /usr/local/php, so I will use that. You can of course change that.

cd /usr/local

Clone the phpfarm repository.

git clone git://git.code.sf.net/p/phpfarm/code php

Now we have to edit the configuration options which phpfarm will use to compile php.

cd php/src

We can use more general configuration options or very strict ones. Default configuration options.sh can be overridden by creating a file called custom-options.sh or a bit more specific like custom-options-5.2.sh or very strict like custom-options-5.3.18.sh. Since the configurations for 5.2 and 5.3 are different and I like to be a strict person, I will create two configurations:

  • custom-options-5.2.17.sh
  • custom-options-5.3.18.sh

custom-options-5.2.17.sh contents (these config values were also mentioned in previous tutorial):

configoptions="
	--enable-cli \
	--with-pear \
	--with-openssl=/usr \
	--with-iconv \
	--with-curl \
	--with-mysqli \
	--enable-mbstring \
	--enable-exif \
	--with-jpeg-dir=/usr \
	--with-zlib \
	--with-zlib-dir \
	--with-png-dir=/usr \
	--with-gd \
	--with-gettext \
	--enable-gd-native-ttf \
	--with-mhash \
	--enable-ftp \
	--with-pspell \
	--with-mcrypt \
	--enable-bcmath \
	--with-mime-magic \
	--with-pdo-mysql \
	--enable-sockets \
	--enable-soap \
        --enable-calendar \
	--enable-fastcgi \
	--enable-force-cgi-redirect \
"

custom-options-5.3.18.sh contents:

configoptions="
	--with-mysqli=mysqlnd \
	--with-pdo-mysql=mysqlnd \
	--enable-cli \
	--with-pear \
	--with-openssl=/usr \
	--with-iconv \
	--with-curl \
	--enable-mbstring \
	--enable-exif \
	--with-zlib \
	--with-zlib-dir \
	--with-gd \
	--with-gettext \
	--enable-gd-native-ttf \
	--with-mhash \
	--enable-ftp \
	--with-pspell \
	--with-mcrypt \
	--enable-bcmath \
	--enable-sockets \
	--enable-soap \
	--enable-calendar \
	--with-png-dir=/usr \
	--with-jpeg-dir=/usr
"

For PHP 5.3 we don’t need the cgi parameters, since these are already enabled by default.

On Ubuntu 11.04, the configuration might fail with error messages about libjpeg and/or libpng. What you can do is the following:

sudo apt-get install libjpeg8-dev

Install the libjpeg8-dev package. This will solve the libjpeg error message.

sudo ln -s /usr/lib/x86_64-linux-gnu/libpng.so /usr/lib/libpng.so

Create a symbolic link to the libpng.so in the /usr/lib directory. This will solve the libpng error message.

Next step – compiling PHP.

sudo ./compile.sh 5.2.17
sudo ./compile.sh 5.3.18

Where the number after the ./compile.sh is the PHP version you wish to compile.

Now that we have compiled PHP, we can move on to set up apache. If you followed the apache tutorial, first of we need to recompile it.

./configure \
	--prefix=/usr/local/apache2.2.22 \
	--with-included-apr \
	--enable-mods-shared=all \
	--enable-so \
	--enable-mod-rewrite \
	--enable-suexec \
	--with-suexec-caller=daemon

These are just my configuration options. The options you have to pay attention to for this topic are:

  • –enable-so
  • –enable-suexec
  • –enable-suexec-caller=daemon – You can change this according to which user your apache runs under.
make
sudo make install

Apache should be up and running. Next stop – FastCGI module.

Download and extract the latest (current) source from http://www.fastcgi.com/dist/.

tar xzf mod_fastcgi-current.tar.gz
cd mod_fastcgi-2.4.6

Next thing to do is rename Makefile.AP2 to Makefile, so we can compile it for apache 2.

cp Makefile.AP2 Makefile

Compile and install the module.

make top_dir=/usr/local/apache2.2.22
sudo make install top_dir=/usr/local/apache2.2.22

The top_dir parameter is optional. If you compiled apache to the more usual location like /usr/local/apache2, you do not need to set this option.

Now that we have mod_fastcgi module compiled, we can load it as a shared object. Add the following line to your httpd.conf:

LoadModule fastcgi_module modules/mod_fastcgi.so

If you had previously ran PHP as an apache module, you must disable it. You can only run PHP either as CGI or an apache module. So in httpd.conf, comment out this line:

# LoadModule php5_module modules/libphp5.so

Create a .conf file (you can call it what you want) – i.e. php-fcgi.conf and put the following content inside:

<IfModule mod_fastcgi>
    FastCgiWrapper /usr/lib/apache2.2.22/bin/suexec
    FastCgiConfig -idle-timeout 110 -killInterval 120 -pass-header
        HTTP_AUTHORIZATION -autoUpdate

    ScriptAlias /php-fcgi/ /var/www/cgi-bin/
</IfModule>

And include it in your main httpd.conf:

# Include FastCGI configuration
Include conf/php-fcgi.conf

Now create a directory for CGI scripts.

sudo mkdir /var/www/cgi-bin

And create scripts.

sudo nano /var/www/cgi-bin/php-cgi-5.2.17
sudo nano /var/www/cgi-bin/php-cgi-5.3.18

And put something like the following in. Just change the version of PHP.

#!/bin/sh
version="5.3.18"

PHPRC=/usr/local/php/phpfarm/inst/php-${version}/lib/php.ini
export PHPRC

PHP_FCGI_CHILDREN=3
export PHP_FCGI_CHILDREN

PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_MAX_REQUESTS

# which php-cgi binary to execute
exec /usr/local/php/phpfarm/inst/php-${version}/bin/php-cgi

These scripts should be executable. So we set permissions to 0755.

cd /var/www/cgi-bin
sudo chmod +x *

Now we configure apache virtualhosts. Each virtualhost will have it’s own subdomain and PHP version.

NameVirtualHost localhost.53:80
<VirtualHost localhost.53:80>
  ServerName localhost.53
  DocumentRoot /var/www
  <Directory "/var/www">
    AddHandler php-cgi .php
    Action php-cgi /php-fcgi/php-cgi-5.3.18
  </Directory>
</VirtualHost>

Do the same for all versions of PHP.

We are almost there. Since these subdomains (asumingly) do not exist yet, we must point them to your localhost IP.

sudo nano /etc/hosts

Just add your subdomains after the localhost definition. It should look something like this:

127.0.0.1 localhost localhost.52 localhost.53

Everything is set, so just restart the apache.

sudo /usr/local/apache2.2.22/bin/apachectl -k restart

Put a file phpinfo.php in /var/www directory with the following line:

And test it. If everything went well, you should see different PHP versions on different subdomains.

  • http://localhost.52/phpinfo.php – PHP 5.2.17
  • http://localhost.53/phpinfo.php – PHP 5.3.18

Enjoy!

Post updated on November 12th, 2012th to reflect latest updates.

Doctrine connection error – symfony 1.4 – php 5.3

Posted November 20th, 2010 in Tehnikalije by Metod

I just got in the sandbox with symfony 1.4 & php 5.3.3. In the beginning everything went well, untill I tried to pull some data from a database. I got this error:

PDO Connection Error: SQLSTATE[HY000] [2002] No such file or directory

Error log said:

PHP Warning:  PDO::__construct() [<a href='pdo.--construct'>pdo.--construct</a>]: [2002] No such file or directory (trying to connect via unix:///tmp/mysql.sock)

It made it clear that mysql.sock was missing or I had some configuration problems. Turns out my php.ini file had to be changed a bit.

pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock

Solution?
Find out where mysqld.sock or mysql.sock is residing and change the default value in your php.ini. That should solve the problem.