(PHP) Code snippet #6

Posted May 26th, 2016 in Snippets by Metod

A while ago I encountered thle following one-liner snippet in a legacy codebase.

Yes, it was a one-liner! Alarming. So, what does it do? Let’s tear it apart and see.

Hint: it displays the name of the first element in the array. But it still iterates through the rest of the array. Which might be ok if the array is of length 1. But still there are some issues left:

  • The complexity.
  • The unreadability.
  • Wrong structure (array instead of string) for the job.

All of the above can be solved by moving the logic somewhere else:

Keep it simple, stupid!

A case for PHP session handlers

Posted September 28th, 2015 in Razno by Metod

tl;dr: Don’t blindly write @session_start(); and hope for the best. Use a session handler!

A case for PHP session handlers

Not long ago, we were in transition from using Memcache to using Redis. Up until that point we were saving sessions to Memcache, but due to reasons beyond the scope of this blog post, we decided to migrate to Redis. As for any smooth transition, we kept Memcache up and ran Redis beside it so there would be no downtime in between deployments. After the deploy all went well. All apps were up and running. We decided to keep Memcache up for a few more days, just in case. And we forgot about that.

After some time, a system admin notices we still have Memcache up. Obviously the transition to Redis was made and we don’t need Memcache anymore, so he shuts it down. Suddenly some parts of the system start failing. Red alert, this cannot be good, why is it trying to connect to Memcache, when we removed all code related to it? So what was going on?

Lesson learned

We deploy our own configuration of session storage and caching etc. We do not rely on the server configuration, as it is not flexible enough. There was nothing wrong with our configuration. But, one of the developers wrote the following snippet of code in one of the component dealing with Facebook SDK (which requires an active session to connect a new user):

  1. <?php
  2.  
  3.  

Yes, he even suppressed errors, so we received no error messages related to that particular line of code.

There was no session handler in place. Coincidentally, the servers had session.save_handler and session.save_path set to Memcache servers and everything worked just fine. Up until the point when the system admin decided to shut down those Memcache servers.

Lesson learned. We managed to quickly resolve the issue by putting our existing session handling system in place. So, please, please, always make sure you know where and how your sessions will be stored. Especially if you are writing an app that is running in high-availability infrastructure.

How to write a session handler

Writing a session handler could not be easier. If you are running PHP >= 5.4 – and you should! – this is as easy as implementing the \SessionHandlerInterface. There is a nice example in the PHP documentation. For Memcache and Redis there are probably a lot of already written session handlers out there as well.

Finally

This was a short post on how something so simple can go pretty much very wrong. So I hope this will at least make someone not repeat the same mistake when dealing with sessions. Happy coding!

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

  1. 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.

  1. 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!

Eclipse / Zend Studio crashing on New project on Ubuntu KDE

Posted August 30th, 2015 in Razno by Metod

If you are using the latest stable versions of either Eclipse or Zend Studio on Ubuntu with KDE installed you might have run into some trouble along the way. If you have oxygen theme installed the IDE will crash whenever you want to create a new project. Or maybe the close buttons won’t work. Plenty of problems.

However there is a simple solution which I found digging around the comments in bug reports.

For oxygen, edit the normally already existing file “/usr/share/themes/oxygen-gtk/gtk-2.0/gtkrc” and change
GtkComboBox::appears-as-list = 1
into
GtkComboBox::appears-as-list = 0

Works like a charm!

All credit goes to Axel Müller for pointing to the original comment made by Hugo Pereira Da Costa.

P.S.: The workaround for this is quite old. However since google search does not provide the straight up answer and the problem persists in latest Ubuntu 14.04 LTS I have decided this is worth a post.

Detect if a synthetic service has been set in Symfony2 Dependency Injection container

Posted October 17th, 2014 in Symfony2 by Metod

If you are using the Symfony2 DependencyInjection component, you might have run into synthetic services.

If I quote from the docs:

Synthetic services are services that are injected into the container instead of being created by the container.

So, what do we do if we want to detect if a service has already been injected or not? Turns out that the definition of the synthetic service gets removed when it is injected into the container. So we can just check if the definition for the service exists. Below is a quick gist to get the general idea.

Get Doctrine2 DBAL connection for different databases in Symfony2

Posted October 26th, 2013 in Razno by Metod

Let’s say you have multiple databases you want to connect to and your config looks similar to the following:

So we have a default DBAL connection to db1 and we have 2 other databases db2 and db3 we want to connect to and perform some queries on.

How do we get the DBAL connections to them?

The Cookbook only tells us how to get the default (db1) connection:

  1. $conDb1 = $this->get(‘database_connection’);

If we want the connection to other 2, it goes like this:

  1. $conDb2 = $this->get(‘doctrine.dbal.db2_connection’);
  2. $conDb3 = $this->get(‘doctrine.dbal.db3_connection’);

The key part is of course: doctrine.dbal.%s_connection, where %s is replaced by the connection name you want to get.

Passing configuration options to Hadoop

Posted March 7th, 2013 in Razno by Metod

If you want to override Hadoop job configuration options, you can do so via command line -D key=value.

When I wanted to pass multiple configuration options including some special characters:

  1. hadoop jar MyJob.jar MyJob -D key=something,else -D key2=jdbc:mysql://host?user=u&password=p

I got some errors like:

  1. -bash: -D: command not found

The solution is to put values in quotes like this:

  1. hadoop jar MyJob.jar MyJob -D key="something,else" -D key2="jdbc:mysql://host?user=u&password=p"

Enjoy! :)

Fix for: There is no `_sonata_admin` defined for the controller …

Posted December 25th, 2012 in Razno by Metod

If you stumbled upon the following error while trying to make SonataAdminBundle work:

There is no `_sonata_admin` defined for the controller `Acme\DemoBundle\Controller\PostController` and the current route `admin_acme_demo_post_list`

Here is what is wrong with your configuration.

The official documentation (in my case for ORM) says to define the *Admin service as follows:

  1. # app/config/config.yml
  2. services:
  3.    acme.demo.admin.post:
  4.       class: Acme\DemoBundle\Admin\PostAdmin
  5.       tags:
  6.         – { name: sonata.admin, manager_type: orm, group: acme_demo, label: post }
  7.       arguments: [null, Acme\DemoBundle\Entity\Post, AcmeDemoBundle:PostAdmin]

Notice that null in the arguments? That is what is wrong.

That means that as the code for the admin it passes null. Whereas the correct thing to do would be to pass in the name of the service itself. Like this:

  1. # app/config/config.yml
  2. services:
  3.    acme.demo.admin.post:
  4.       class: Acme\DemoBundle\Admin\PostAdmin
  5.       tags:
  6.         – { name: sonata.admin, manager_type: orm, group: acme_demo, label: post }
  7.       arguments: [acme.demo.admin.post, Acme\DemoBundle\Entity\Post, AcmeDemoBundle:PostAdmin]

Happy coding!

Symfony2: Upgrading 2.0 to 2.1 – CallbackValidator

Posted November 12th, 2012 in Razno by Metod

The CallbackValidator class was deprecated in 2.1.

If you implemented custom validators using this interface, you can substitute them by event listeners listening to the FormEvents::POST_BIND (or any other of the *BIND events). In case you used the CallbackValidator class, you should now pass the callback directly to addEventListener.

Here is how you do it.

Before:

After:

Enjoy! 😉

Doctrine2: CHAR with annotations

Posted November 7th, 2012 in Razno by Metod

Ever wondered if there is a better way of defining a CHAR (mysql) with doctrine2 annotations?

From doctrine2 docs:

  1. <?php
  2. /**
  3.  * @Column(type="string", columnDefinition="CHAR(2) NOT NULL")
  4.  */
  5. protected $country;

Not a very nice approach imo. I dug around the code and found a somewhat neater solution:

  1. <?php
  2. /**
  3.  * @Column(type="string", length=2, options={"fixed" = true})
  4.  */
  5. protected $country;

Now you don’t need to manually type in column definitions. Enjoy!