Category Archives: PHP

Composer 2.3.0 breaks Symfony 3.4 app

If you experience the following error while installing the required packages for Symfony 3.4 packages, it is highly possible to have Composer 2.3.0 or newer installed:

symfony-scripts: Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::buildBootstrap

In Process.php line 143:

[TypeError]
Argument 1 passed to Symfony\Component\Process\Process::__construct() must
be of the type array, string given, called in /var/www/example.com/releases/20220330124916/vendor/sensio/distribution-bundle/Composer/Scrip
tHandler.php on line 310

The root cause of the issue is that Composer 2.3.x requires symfony/process^5 itself, but your project also has a dependency on symfony/process^4 somewhere, composer loads it first and when your project tries to use it, expecting v4 but using v5 instead it triggers the error

The quick and dirty solution is to downgrade Composer to 2.2.x so you are able to update your dependencies normally. To do that just run the following command

sudo composer self-update 2.2.9

Enjoy!

 

PHP Warning: PHP Startup: mcrypt: Unable to initialize module

If you have installed multiple PHP versions using PPA maintained by Ondrej Surý you may end up with the following error message:

PHP Warning: PHP Startup: mcrypt: Unable to initialize module
Module compiled with module API=20190902
PHP compiled with module API=20170718

This is caused by a misconfiguration: the php.ini file is pointing to the latest version of mcrypt instead of the one compiled for PHP 7.2. To fix that you have to correct the path to the extension. Open the file for editing:


sudo vi /etc/php/7.2/cli/conf.d/mcrypt.ini

and replace extension=/usr/lib/php/20190902/mcrypt.so with extension=/usr/lib/php/20170718/mcrypt.so. Do the same for /etc/php/7.2/fpm/conf.d/mcrypt.ini file.

If you have the module mcrypt.so listed in /etc/php/7.2/cli/php.ini or /etc/php/7.2/fpm/php.ini – delete it to avoid “PHP Warning: Module ‘mcrypt’ already loaded in Unknown on line 0” error

10 things to to after installing WordPress blog

This guide provides a list of 7 things that you should do after installing a new WordPress site. Some of the steps are optional, but many others are essential if you want to comply with GDPR and Google AdSense policy, to have at least basic on-site SEO and manage the updates easier.

This guide provides links to other articles that will aid in your learning of WordPress content management system. Many of the steps refer to 3rd party sites where you can find more information on a particular topic.

After you have finished this guide, you will have easy to maintain SEO optimized website that complies to GDPR and Google AdSense policy. Continue reading

How to install PHP Data Structures (DS) extension on Ubuntu 16.04

First, you will need to install PEAR via apt-get to get the necessary package and distribution system that both PEAR and PECL use. From a shell prompt enter:

sudo apt-get install php-pear

You will be prompted to confirm the install. Just press “y” and enter. If all goes well you should see it download and install the php-pear package.

Now you will need to install the php-dev package to get the necessary PHP7 source files to compile additional modules. Enter the following from a shell prompt:

sudo apt-get install php-dev

If you do not install the php-dev package and try to install a PECL extension using “pear install”, you will get the following error:

sh: phpize: not found
ERROR: `phpize’ failed

The PECL_HTTP extension requires an additional dependency package to be installed. You can probably skip this for other extensions:

sudo apt-get install libcurl4-openssl-dev

Now we are finally ready to actually install the extension. From a shell prompt enter following:

sudo pecl install ds

The installer may ask you about some specific options for the extension you are installing.  Just accept the defaults and go ahead.

Once the install is complete, it’s time to enable the extension.
First, edit the following file (create it if it does not exist already):

sudo vi /etc/php/7.0/mods-available/ds.ini

and change it’s contents to:


; configuration for php ds module
; priority=30
extension=ds.so


Than check and remove any symbolic links to 20-ds.ini file, such as:

sudo rm /etc/php/7.0/fpm/conf.d/20-ds.ini
sudo rm /etc/php7.0/apache2/conf.d/20-ds.ini
sudo rm /etc/php7.0/cli/conf.d/20-ds.ini

You need to remove above listed symlinks because of bug: there is hard dependency on the json extension. DS extension shouldn’t try to implement JsonSerializable if the json extension is not loaded, but actually do it and it will complain with exception if it is not found:


PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib/php/20151012/ds.so'
 - /usr/lib/php/20151012/ds.so: undefined symbol: php_json_serializable_ce in Unknown on line 0

That’s why we removed 20-ds.ini symlinks and specified ds.so to load after json is already enabled.

Now, disable and then re-enable the extension:

sudo phpdismod ds
sudo phpenmod ds

You may need to restart your HTTP server:

# If you are on apache
sudo service apache2 restart
# if you are on nginx
sudo service nginx restart

How to parse a csv file in php when the delimiter is unknown

There are plenty of MS Excel alternatives out there – OpenOffice, LibreOffice, Kingsoft, Google Spreadsheets and many more. The problem is that CSV files created by different softwares may vary (, or ; to name a few options). If you need to process CSV files exported from different systems and software and handle the delimiter automatically, you can benefit from using SplFileObject::getCsvControl method.

Example usage:

<?php $csvFileObject = new SplFileObject($_FILES["csv"]["tmp_name"]); list($delimiter, $enclosure) = $csvFileObject->getCsvControl();

$lines = fopen($_FILES["csv"]["tmp_name"], 'r');
if($lines) {
while (($line = fgetcsv($lines, 4096, $delimiter, $enclosure)) !== false) {
//do something
}
}

Reference: http://php.net/manual/en/splfileobject.getcsvcontrol.php

How to install mailcatcher on CentOS 7 and configure it for PHP

The problem

Handling outgoing emails in a web application can be hard, because it’s very easy things to get wrong and send unwanted test mails to real world customers while testing some functionality.
Ensuring sent emails are designed, parsed and formatted correctly is a painstaking problem, too.

… and the solution

Mailcatcher is a program you can use to test sending email. It gives you the ability to inspect sent emails and their headers. It is a simple SMTP server that can receive emails. It also gives you a nice web interface to preview the sent emails.

We’ll cover installing the dependencies for Mailcatcher. Then we’ll install and set it up for easy use in our development environment. This includes use with PHP. Finally, we will setup password protect subdomain for easier access using Nginx.

Continue reading

Mock Yii2 components

The well written code is also testable code – it is loosely coupled to the other components, it follows the single responsibility principle, there are no explicit dependencies and so on. We all know the rules, but there is always an exception.

It’s pretty common situation to unit test component or controller that depends on another core Yii component – for example using \yii\web\Request to get query string or $_GET variable.

Rewriting your library in order to remove the explicit dependencies is not always option, because it may lead to massive refactoring and actually break more things than benefits.

In such as case a what I really want to do is to assign temporarily \Yii::$app->request PHPUnit Mock Class, so I can override the return values e.g.

$request = $this->getMock('\yii\web\Request', ['getUserIP', 'getUserAgent', 'getBodyParams']);

$request->expects($this->any())
 ->method('getUserIP')
 ->will($this->returnValue('127.0.0.1'));

$request->expects($this->any())
 ->method('getUserAgent')
 ->will($this->returnValue('Dummy User Agent'));

$request->expects($this->any())
 ->method('getBodyParams')
 ->will($this->returnValue([]));


\Yii::$app->set('request', $request);

Enjoy!

Symfony 2 : Redirect to Referer

There are few methods of redirecting to referer.
Inside your controller action you can use:

return $this->redirect(
              $this->getRequest()
                   ->headers
                   ->get('referer')
           );

Alternatively you can write it like this:

 $request = $this->getRequest();
 return $this->redirect($request->server->get('HTTP_REFERER'));

Generate huge JSON files with custom PHP >5.3 class

Lately, I’ve been working on transitioning XML feeds to JSON format on big video site.  We generate these feeds in order to feed external search service with results. It’s similar to sitemap, but it provides more detailed information about the pages.

This task is challenging because of the following problems that need to be resolved:

  1. The feed need to represent over 500 000 database entries i.e. videos. It’s just not possible to generate huge PHP multidimensional array with more than 500 000 elements and pass it to json_encode(). Obviously, you need to generate small JSON objects (chunks) concatenated with hand-coded strings and so build the full feed.
  2. The development and production servers we use are equipped with outdated PHP version 5.3.27. That means:
    – No meaningful error messages because json_last_error_msg() function it’s not available prior PHP 5.5
    – No JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, and JSON_UNESCAPED_UNICODE
  3. The code should be easy to test and maintain, so it should provide meaningful debug information and error handling.

Continue reading

Format microtime() to provide better feedback on the time elapsed

As a PHP developer you know that it’s common task to check how long a particular class, function or procedure performs. Usually this involves measuring of the time particular code snippet takes to execute. There are lots of PHP code benchmark scripts out there, but the simplest method remains to check the difference between the start and end time. Continue reading