This shows you how to enable logging so you can write stuff like $app->log->debug('this will show up in the error_log');
.
<?php --- snip %< --- $app = new \Slim\Slim(array( 'log.enabled' => true, 'log.level' => \Slim\Log::DEBUG )); $app->log->debug('this will show up in your error-log'); --- >% /snip ---
[opt-in]
Wondering why PHP doesn’t see your environment variables? Why getenv('var')
won’t return a value while it does on the commandline?
You’re probably using PHP-FPM.
Cause: The environment, with all its variables, is cleared for FPM. This is default behavior.
[ update ]
Set the IP-address to the following DNS-name: docker.for.mac.localhost (yes, literally)!
Working with the IP-address doesn’t work anymore
[ /update ]
Want to get XDebug working for your PHPUnit tests which run in Docker? Or for behat? Or any other CLI application? Follow me!
Roughly this is what you’ll need to do: Continue reading
In the process of upgrading PHP5.3 code I had to change all deprecated mysql_* functions to their mysqli_* counterparts.
For a lot of functions the signature stayed the same.
But mysqli_query and mysqli_connect have differences. So you can’t just find and replace them.
Instead of doing this manually, I wanted to find and replace recursively while changing the order of the arguments.
In vim:
# change mysql_query(param1, param2) to:
# mysqli_query(param2, param1)
:%s/mysql_query(\(.\{-}\),\(.\{-}\))/mysqli_query(\2, \1)/g
Using sed:
# on linux
# mysql_query(param1, param2) to
# mysqli_query(param2, param1)
sed -i 's|mysql_query(\(.*\),\(.*\))|mysqli_query(\2, \1)|g' devices.php
# on mac (otherwise you get the 'invalid command mode' when
# you run the sed command)
# mysql_query(param1, param2) to:
# mysqli_query(param2, param1)
sed -i '' -e 's|mysql_query(\([^,]*\),\([^)]*\))|mysqli_query(\2, \1)|g' devices.php
Recursively changing all files:
# in all files under current directory:
# mysql_query(param1, param2) to:
# mysqli_query(param2, param1)
fgrep -rl mysql_query . | while read file; do
sed -i '' -e 's|mysql_query(\([^,]*\),\([^)]*\))|mysqli_query(\2, \1)|g' $file
done
Note that sed
cannot do non greedy matching.
That’s why we’re searching for anything but the separator until the separator like this:
# non greedy matching with sed
\([^,]*\),
It basically states: get everything except for the comma until you get a comma (which is the first one to appear).
This script disables xdebug for one run. No more error-messages like:
$ composer update
You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug
and:
$ php-cs-fixer fix --dry-run .
You are running PHP CS Fixer with xdebug enabled. This has a major impact on runtime performance.
If you need help while solving warnings, ask at https://gitter.im/PHP-CS-Fixer, we will help you!
We’ll create a script which will:
the script we’ll name php-no-xdebug
(or whatever you like)
With Xdebug (note the last line)
$ php --version
PHP 7.1.10 (cli) (built: Oct 6 2017 01:08:19) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
with Xdebug v2.5.5, Copyright (c) 2002-2017, by Derick Rethans
Without Xdebug (note the missing last line)
$ php-no-xdebug --version
PHP 7.1.10 (cli) (built: Oct 6 2017 01:08:19) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
php-no-xdebug
Create the script /usr/local/bin/php-no-xdebug
with the following contents.
# file /usr/local/bin/php-no-xdebug
#!/bin/bash
php=$(which php)
# get the xdebug config
xdebugConfig=$(php -i | grep xdebug | while read line; do echo $line; exit; done)
# no xdebug? Nothing to do!
if [ "$xdebugConfig" == "" ]; then
$php "$@"
exit
fi
# get the configfile (which should be the first value)
# so strip off everything after the first space of the xdebug-config
xdebugConfigFile=$(php -i | grep xdebug | while read line; do echo $line; exit; done)
# test whether we got it right
if [ ! -f "$xdebugConfigFile" ]; then
echo "No XDebug configfile found!"
exit 1
fi
# disable xdebug by renaming the relevant .ini file
mv ${xdebugConfigFile}{,.temporarily-disabled}
# dissect the argument to extract the first one (which should be a script or an application in $PATH) from the rest
index=0
for arg in $(echo $@ | tr ' ' "\n")
do
if [ "$index" == "0" ]; then
firstArg=$arg
else
restArg="$restArg $arg"
fi
((index++))
done
# check whether the command to be executed is a local PHP file or something in the $PATH like composer or php-cs-fixer
fullPath="$(which $firstArg)"
if [ "$fullPath" == "" ]; then
# check whether it's a local file
if [ ! -f $firstArg ]; then
echo "Could not find $firstArg. No such file or directory"
exit 1
else
# just run the commands
$php $@
fi
else
# run the command with the fullpath followed by the rest of the arguments provided
$php $fullPath $restArg
fi
# execute the command
$php "$@"
# re-enable xdebug
mv ${xdebugConfigFile}{.temporarily-disabled,}
# test whether the conf file is restored correctly
if [ ! -f "$xdebugConfigFile" ]; then
echo "Something went wrong with restoring the configfile for xdebug!"
exit 1
fi
and make it executable
$ chmod +x /usr/local/bin/php-no-xdebug
That’s it! Run it like this:
$ php-no-xdebug composer update
This article is a slimmed-down, firing-from-the-hips, get right to the action version based on the ones listed below. If you miss some background info or want a more spelled out version, please do visit these articles:
If you want to install deprecated versions of PHP (< PHP7.2), then you’ll need to add this tap to homebrew:
brew tap shivammathur/php
#versions="php@7.2 php@7.3 php@7.4 php@8.0 php@8.1" # in bash
versions=(php@8.1 php@8.2 php@8.3) # in ZSH
for version in $versions; do
echo "installing ${version}"
brew install shivammathur/php/${version}
done
# install xdebug for php >= 7.2
pecl uninstall -r xdebug
pecl install xdebug
If you receive the error configure: error: Cannot find libz
you need to install required libraries via XCode:
xcode-select --install
brew upgrade
To easily switch PHP versions, install the following script.
curl -L https://raw.githubusercontent.com/rhukster/sphp.sh/main/sphp.sh > /usr/local/bin/sphp
$ chmod +x /usr/local/bin/sphp
As I don’t add Apache on my host machine, change apache_change=1
to apache_change=0
in the script.
vi `which sphp`
Without arguments, this command returns useful information like which versions are installed and which is the active one right now:
$ sphp 7.4
If you need to enter your administrator password, then you probably need to disable the part where Apache is restarted (see chapter above).
Switching to php@7.4
Switching your shell
Unlinking /usr/local/Cellar/php@5.6/5.6.40... 0 symlinks removed
Unlinking /usr/local/Cellar/php@7.0/7.0.33... 0 symlinks removed
Unlinking /usr/local/Cellar/php@7.1/7.1.33... 0 symlinks removed
Unlinking /usr/local/Cellar/php@7.2/7.2.31_1... 0 symlinks removed
Unlinking /usr/local/Cellar/php@7.3/7.3.19... 25 symlinks removed
Unlinking /usr/local/Cellar/php/7.4.7... 0 symlinks removed
Linking /usr/local/Cellar/php/7.4.7... 24 symlinks created
PHP 7.4.7 (cli) (built: Jun 12 2020 00:04:10) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.7, Copyright (c), by Zend Technologies
All done!
NOTE FOR XDEBUG: if you want to use xdebug
you’re switch command needs to be expanded to:
sphp 7.4 && pecl uninstall -r xdebug && pecl install xdebug
Now you’ll see that xdebug is enabled for PHP:
php -v
PHP 7.4.7 (cli) (built: Jun 12 2020 00:04:10) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Xdebug v2.9.6, Copyright (c) 2002-2020, by Derick Rethans
with Zend OPcache v7.4.7, Copyright (c), by Zend Technologies
That’s it!
Again; take a look at the great, kept up-to-date, article of Andy Miller over at his website: https://getgrav.org/blog/macos-monterey-apache-multiple-php-versions
The other day I had to add some logic right after an user was saved to the database. I ended up using events to get this done without cluttering the entity.
I first added the logic in the User-entity but I then realised this logic was not really related to the user entity itself. Or the application, for that matters.
In order to seperate concerns, I decided to create a hook after the User save-action. That would allow me to add logic at that particular time without cluttering the User entity with nonrelevant code.
This has a downside though. When you want to debug what the heck happens after the User is saved to the database, you won’t find it in the User entity. This might send you down a long code-hunt. But you will see the dispatching of the event though. So if you’re new to this, remind yourself that there can be a whole different world behind the dispatching of an event.
Setting it up consists of 3 steps:
The event is nothing more than a class.
The event is the object which is passed around. Therefore you want to populate the event with all the information the subscriber(s) need.
For that purpose I create a setter and a getter. The code which will dispatch the event will use the setter, the event subscriber will use the getter.
# file src/AppBundle/Event/UserCreatedEvent.php
<?php
namespace AppBundle\Event;
use AppBundle\Entity\User;
use Symfony\Component\EventDispatcher\Event;
class UserCreatedEvent extends Event
{
private $user;
public function setUser(User $user)
{
$this->user = $user;
}
public function getUser()
{
return $this->user;
}
}
Now we decide in what moment of time we’ll dispatch (fire) the event. In our example this will be right after the user is saved to the database.
# file src/AppBundle/Entity/User.php
/* other code */
public function createUser(User $user)
{
/* more code */
// save the user to the database
$this->em->persist($user);
$this->em->flush();
// dispatch an event where others can work with the newly created user
$eventDispatcher = $this->container->get('event_dispatcher');
$event = new UserCreatedEvent();
$event->setUser($user);
$eventDispatcher->dispatch('user.event.created', $event);
return $user;
}
The subscriber is the class with the method which gets called once the event gets dispatched.
# file src/AppBundle/EventSubscriber/UserCreatedSubscriber.php
<?php
namespace AppBundle\EventSubscriber;
class UserCreatedSubscriber
{
public function newUserCreated(UserCreatedEvent $event)
{
var_dump($event->getUser());
}
}
Now that we have the code for the subscriber, we need to actually subscribe the subcriber to the event. This is the glue between dispatching an event and acting upon it.
You do this in services.yml as you register it as a service.
# create a listener for the UserCreatedEvent
valuation.event.created:
class: AppBundle\EventSubscriber\UserCreatedSubscriber
tags:
- { name: kernel.event_listener, event: valuation.event.created, method: newUserCreated }
That’s it!
If you want to read more:
In order to benefit from the Symfony3 translations in javascript files, I use BazingaJsTranslationBundle from
I had the weirdest thing: whenever I logged out, cleared my cache, went to the login page and logged in, I got redirected to /translations which showed me the generated JSON file with the translations.
Cause: the login page tried to load the JSON translation because of my <script src="{{ url('bazinga_jstranslation_js', {}) }}?locales=en,nl"></script>
script import. But that failed as security did not allow anonymous access to that URI.
Symfony registered the failed URL and, as I’m on the login page, redirected me to the url that first failed once I was logged in.
Solution: allow anonymous access to URI /translations.
In file app/config/security.yml
I added the following:
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/translations, roles: IS_AUTHENTICATED_ANONYMOUSLY }
We will be installing the following:
Getting a white page (the infamous the white page of death) when you instruct your browser to open your website? Want to debug an error, but you don’t see error messages on the screen but you do in your logfiles?
Then you should enable the displaying of errors in PHP.
There are few ways you can do this. But the best (fool proof) way is to have this in your php.ini
file:
; file /etc/php5/apache2/php.ini
; here goes other settings
display_errors = On
NB: Don’t forget to restart your webserver after changing PHP’s configuration for it to have effect: sudo service apache2 restart