The thin line between an Invocation

PHP language changes and until we understand them. Did this caught your attention?

The release of PHP 8.1 is quite some days ago, like November the year before last year, and when I first learned about first class callable syntax (by the RFC, but the manual has it, too) it was like this is a benefit for static code analysis (only).

This one also looks like a nice short for of Closure::fromCallable(<callable>) and comes with the same object and scope bindings:

# first class callable syntax:

strlen(...)($string);
# NOTE: the three dots ... are not an omission


# short form of closure from callable:

Closure::fromCallable("strlen")($string);

Now this example looks quite dull. We could just call strlen(string) and case closed. Obviously we only use it when we want a Closure, not a callable.


Yesterday, I revisited an older answer of mine on Stack Overflow in regard to a very simple, ground working PHP function, get_object_vars().

The question asked How to programmatically find public properties of an object from inside one of it’s class methods?

Using get_object_vars($this) returns all properties within scope, so my answer back in 2012 was to write a global function, pass the object and call get_object_vars() within:

function get_object_public_vars($object) {
    return get_object_vars($object);
}

class Foo {
    public function getPublicVars() {
        return get_object_public_vars($this);
    }
}

Sure, that’s not what the OP really has hoped for, because you have to add another global function into your utilities instead of having something at your disposal directly.

It took two more years until 2014 when Brad Kent had the one-liner answer:

    public function getPublicVars() {
        return call_user_func('get_object_vars', $this);
    }

Wait, what? – If calling get_object_vars() directly yields privates, why calling it with call_user_func() as the callable string 'get_object_vars' changes the scope? – Well we don’t know but it passed the year and then with the PHP 7.0.0 release in December 2015 these semantics changed and it was not such a thing any longer. (Change log only, sadly I still couldn’t find a related bug report.)

Now commentators below the answer then were keen to point out that it relies on a bug (again, sadly no references to it), until then sometime Brad edited in telling the required PHP version and otherwise use reflection.

Same for me, this was also my line of defense in my answer and I had reflection in it, too.


But I do not really like to rely on reflection / meta programming during programming as it often demands many more interruptions over time as reflection changes far more often as the language progresses while it is running behind actual progress in the language. Often the code that is produced by it is not robust, it does not feel well.

As create_function() is not an answer for longtime and closures could have it I was looking into them. And there I found a cadeau surprise:

    public function getPublicVars() {
        return get_object_vars(...)->__invoke($this);
    }

The __invoke method is part of PHPs’ final internal Closure class, also known for classes not extending from Closure as magic method that turns an object into a callable.

In this example get_object_vars is turned into a closure and it is bound to the scope of $this/getPublicVars() so that it can obtain all the properties.

However, triggering the __invoke() event moves it far away enough out of scope to return only the public properties similar to call_user_func('get_object_vars') once did.

So thanks to the new PHP 8.1 first class callable syntax it is now again easier to write and to rely on important code functions like get_object_vars() and to draw the thin line between invocations.



Now is this a bug as it was one in call_user_func()? Well, different to call_user_func(), which has only one form of invocation and therfore perhaps required the change, here the Closure has two forms:

# the two forms how to invoke a Closure in PHP:
get_object_vars(...)($this);
get_object_vars(...)->__invoke($this);

Therefore there is a thin line to draw here and get_object_vars(…)($this) allows to call_user_function('get_object_vars', $this) as in PHP 7+ and with __invoke($this) as it was before. For the many other functions that are not scope aware this should not make a difference and we can safely assume that the first, standard form is not affected by it. Therefore the differentiation remains to the caller offered by the implementors’ choice.

Therefore instead of calling it a bug, why not see it as implementation-specified behaviour and call it a feature. It is a one of the Closure from callable and it won’t translate out of it.

# the two forms how to invoke a Closure in PHP:
get_object_vars(...)->__invoke(...)($this);
get_object_vars(...)->__invoke(...)->__invoke($this);


You can make use of __invoke() in your own implementations and resolve the scope issue with it as well. This is PHP 7.0+ code again:

(new class {function __invoke($object) {
    return get_object_vars($object);}
})($this);

Or by relying on another method of Closure, bindTo() (again PHP 7.0+):

(function ($object) {return get_object_vars($object);})
    ->bindTo(null, null)($this);

By the way, this function constructor of a Closure doesn’t have the first class callable semantics as function is not scope sensitive, it has the scope bound:

# yields privates
(function ($object) {return get_object_vars($object);})
    ->__invoke($this);

You have to use a true native callable to unveil it.


And good old call_user_func()? Here is the PHP 5.4+ variant, you see how much syntax and with it the semantics changed:

call_user_func(
    call_user_func(
        array(
            function ($object) {return get_object_vars($object);},
            'bindTo'
        ), null, null
    ), $this                     
);

Luckily PHP 7.0 brought in more consistent function calling and method invocation syntax and we don’t need to write out call_user_func() any longer.

Not even for call_user_func('get_object_vars', $this) thanks to PHP 8.1 first class callable syntax in shis short form: get_object_vars(…)->__invoke($this).

References

Based on Théodore Géricault Study of the Head of a Youth, ca. 1821–1824 (via Wikipedia)

Posted in PHP Development, Pressed, The Know Your Language Department, Uncategorized | Tagged , , | Leave a comment

An Exquisite Amble through the Realm of Desugaring

Bonjour Confrères and Consoeurs,

Ai, Yay, Yay,

wish to invite you on a captivating sojourn into the sophisticated sphere of Desugaring. In the lexicon of programming, Desugaring denotes the elegant procedure of translating more ornate linguistic constructs—dubbed as Syntactic Sugar — into their simpler, fundamental equivalents.

Language processors, including compilers and static analyzers, often expand sugared constructs into their more verbose equivalents before processing, a process sometimes called “desugaring”.
“it could be exposed to societal prejudices and harmful stereotypes and integrate these into its images” (Craiyon)

Let’s delve into this with a trifecta of illuminating illustrations:


Java 8: Lambda expressions—an epitome of chic in Java 8. They are nothing short of syntactic sugar elegantly draped over the structure of functional interfaces.

Runnable r = () -> System.out.println("Executing with élan in Java!");
r.run();

Manifests as:

Runnable r = new Runnable(){
    public void run(){
        System.out.println("Executing with élan in Java!");
    }
};
r.run();
PHP Syntactic Sugar Illustration (Craiyon)

Python: Drawing our gaze to Python, we find the list comprehension—a charming vignette of syntactic sugar.

elegantlist = [x**2 for x in range(5)]

Transforms to:

elegantlist = []
for x in range(5):
  elegantlist.append(x**2)

Go: In the realm of Go, short variable declarations are a sublime manifestation of syntactic sugar.

func main() {
  g := 42
  fmt.Println(g)
}

Becomes:

func main() {
  var g int
  g = 42
  fmt.Println(g)
}
The eyes, its always the eyes. Affirmative, Dave. I read you. (Craiyon)

PHP Constructor Property Promotion

Meandering onto our home turf, PHP 8.0, we encounter Constructor Property Promotions—an exhibition of syntactic sugar par excellence:

class Vertex {
  public function __construct(
   public float $x = 0.0,
   public float $y = 0.0,
   public float $z = 0.0,
  ) {}
}

Unveils as:

class Vertex {
  public float $x;
  public float $y;
  public float $z;

  public function __construct(
     float $x = 0.0,
     float $y = 0.0,
     float $z = 0.0,
  ) {
    $this->x = $x;
    $this->y = $y;
    $this->z = $z;
  }
}

Venting through the protocol:

( new class (Vertex::class) { public function __construct(string $_) { var_dump ([
    // :: show instance without a call to contructor :: //
    ($_ = new ReflectionClass($_))->newInstanceWithoutConstructor(),
    // :: show default values :: ................... :: //
    ...array_map(fn ($_) => [$_->getName() => $_->getDefaultValue()], $_->getProperties())
]) ; } } );

Emits:

array(4) {
  [0] =>
  class Vertex#3 (3) {
    public float $x =>    *uninitialized*
    public float $y =>    *uninitialized*
    public float $z =>    *uninitialized*
  }
  [1] =>  array(1) {
    'x' =>    NULL
  }
  [2] =>  array(1) {
    'y' =>    NULL
  }
  [3] =>  array(1) {
    'z' =>    NULL
  }
}

Our programming languages—true art maestros—deftly handle the canvas of syntactic sugar, providing us, fortunate souls, with a more expressive, palatable syntax.

For those in pursuit of deeper enlightenment:

Posted in Surviving the Internet, Uncategorized | Tagged , , | Leave a comment

Git Committer Date is Author Date (Amend)

Amend the last commit (HEAD) and set the committer date as the author date – as “–committer-date-is-author-date” may have done (a git-rebase option):

GIT_COMMITTER_DATE="$(git show -s --format=%at HEAD)" git commit \
--amend -C HEAD

(Explainshell)

Git Author Date is Committer Date (Amend)

And for setting the author date to the committer date while keeping the committer date:

GIT_COMMITTER_DATE="$(git show -s --format=%ct HEAD)" git commit \
--amend -C HEAD --date="$(git show -s --format=%ct HEAD)"

(Explainshell)


Previously:


Image motives based on a visual excerpt from a TV series episode named “git gone” which is also the imaginary product name, the further text reads “kills bugs on contact” on the spray can label.
Posted in Uncategorized | Tagged , | Leave a comment

Expect more from you Linux Command Line

Just stumbled over two nice written articles about command line usage on Linux by Robert Elder:

Posted in Hakre's Tips, Linked, Pressed, Tools | Leave a comment

Docker Run without “docker run”

So there was this one question on Stackoverflow in which the OP was linking an .htaccess tester for Mod-Rewrite-Rules. Despite this being all fine I was asking myself what about really(tm) testing this?

So I remembered the rewrite-log from the days ago and thought: Why not just fire up a docker container, do the setup for testing rewrites by turning the logs to screaming and give it a drive.

But all the setup.

So I had an idea: What about you put the whole example into the Dockerfile? It has the RUN directive, so the moment the image builds it is actually executing it.

Having it exit non-zero even prevents of storing the image locally.

Ah yeah, and why actually write a Dockerfile even.


<<'EOD' docker build –rm –tag rewrite-tester –no-cache –
FROM httpd:alpine
RUN set -e \
; sed -i -e 's/^#LoadModule rewrite_module/LoadModule rewrite_module/' \
-e 's/^LogLevel .*$/LogLevel debug rewrite:trace8/' \
-e '\|<Directory "/usr/local/apache2/htdocs">|,\ </Directory> s/^ AllowOverride .*$/ AllowOverride All/' \
/usr/local/apache2/conf/httpd.conf \
; echo -e ' \n\
RewriteEngine On \n\
RewriteBase / \n\
RewriteCond %{REQUEST_URI} \.(gif|jpg|jpeg|png)$ \n\
RewriteRule ^(.*)$ $1?i=jplx [DPI,QSA] \n\
RewriteCond %{REQUEST_URI} !^/sites/default/files/js/ \n\
RewriteCond %{REQUEST_URI} !^/sites/default/files/css/ \n\
RewriteRule ^sites/default/files/(.*)$ index.php?q=system/files/$1 [END,QSA,R] \n\
' | tee /usr/local/apache2/htdocs/.htaccess \
; httpd-foreground & sleep 1 \
; apk add curl \
; curl -I 'http://127.0.0.1/sites/default/files/Slide074.png?abc&#39; \
; exit 123
EOD
;: https://stackoverflow.com/a/58527089/367456

Explainshell

This also clearly highlights a missing feature in docker: no support for here-doc strings in the Dockerfile since 2013, echo -e to the rescue (but it’s cumbersome).

Posted in Hakre's Tips, Patched, Pressed, Professional Webdevelopers At Work, Scripts, Surviving the Internet, Tools, Uncategorized | Tagged , , , , | Leave a comment

Speedpills 4 Linting PHP Files in Parallel

B1x9217x1428-gimp

Quite some time ago I’ve already written about linting PHP files in the shell / build.

Even though parallel linting is fine, when the code-base is growing larger and larger, the build becomes slower and slower. A slow build sucks.

Git to the Rescue

One easy way to speed things up again is by reducing the number of files. So instead of linting all PHP files in directories, only linting the files that recently changed is a power-up.

For example if working with topic branches (e.g. bug-fixes or features) and having a main branch where changes are normally merged in (e.g. develop or master) the list of files to lint can be generated by listing all file-names changed (modified, added, deleted, …) between HEAD and the target branch (e.g. develop or master).

Let’s consider working on a topic-branch while having it checked out (HEAD) and the target branch is develop.

git log --no-decorate --pretty=format: --abbrev-commit \
        --no-merges --first-parent --name-only develop..

Explainshell

The output is not yet totally useful. First of all it contains empty lines but also deleted files. And it contains all files, when the change log was edited it will be also listed next to the php files interested for linting. And as this can span easily over multiple commits, files can be duplicated.

The answer to that are filters in the shell.

Streams all the Way Down

The first filter is to reduce the list already by file extension. Here is a filter w/ sed letting only pass .php and .phtml files:

sed -n '/\.ph\(p\|tml\)$/p'

Explainshell

Next is to remove the duplicates (if any), sort is suitable here:

sort -u

Explainshell

Last but not least only existing files (not the deleted ones) must be passed to PHP for linting as otherwise it would rightfully error out.

I had to crack a bit on this one as in my mindset there is a lot of find when it is about finding files, but this time there is no find. What I came up with is ls as it does no output (just errors) when a file (or directory) does not exists. With xargs it is easy to provide multiple arguments to ls at once so that there is not so much to spawn.

xargs ls -f1 -- 2>/dev/null

Explainshell

This ensures to only list existing files, one per line, and the error output goes to /dev/null. So the full filter first removes any files of unfitting type (sed), any duplicates (sort) and non-existing files (xargs, ls):

sed -n '/\.ph\(p\|tml\)$/p' \
  | sort -u | xargs ls -f1 -- 2>/dev/null

Explainshell

This then only needs to get wired up to the existing parallel lint command which is xargs to do the parallelism, php for linting and grep to detect any error (see as well the older blogpost).

But before taking a look at the command as a whole, as this is not so much about having it run far away like on Travis CI last time, let’s consider that not all changes are yet staged nor committed. So next to listing the files changed since branching from develop, there are also all the files currently dealing with:

    git diff --cached --name-only
    git diff --name-only

Explainshell

To wrap this all up a shell compound-list in curly brackets is handy to execute it in process.

  { git log --no-decorate --pretty=format: --abbrev-commit --no-merges --first-parent --name-only develop..
    git diff --cached --name-only
    git diff --name-only
  } | sed -n '/\.ph\(p\|tml\)$/p' \
    | sort -u | xargs ls -f1 -- 2>/dev/null \
    | 2>/dev/null xargs -n1 -P8 php -n -d short_open_tag=0 -l \
    | grep -v '^No syntax errors detected'

Exit status 1 means success, any other status a lint failure (requires set +e as in the earlier post).

Regardless how large the overall code-base is, this keeps linting speed fast. Especially for the local build.B1x9217x1428-gimp.png

Posted in Hakre's Tips, PHP Development, PHP Development, Pressed, Scripts, Tools, Uncategorized | Tagged , , , , , | 1 Comment

Sed Cheatsheet

Just a post about some of the sed lines I find scattered, to be extend in future edits.

Merge same Lines Together

$ sed '/^ \*$/{h;d};{H;s/.*//;x;s/^\n//}'

This sed example merges all “ *” lines that follow each other (e.g. empty lines in a class level Docblock comment in a PHP file). The pattern can be replaced with any pattern to describe the lines to merge together.

It copies each matching line into the hold buffer and drops the line.

On any other non matching line, the line is appended to the hold buffer, the read buffer emptied and exchanged w/ the hold buffer (clearing the hold buffer), any starting newline removed from the pattern space (as appending to an empty hod buffer would have created it but it’s unwanted).

Limitations: Won’t work when line pattern matches the last line / GNU sed

Indent all but first line

$  | sed '1{p;d}; s/^/  /'

1 applies to first line only, p prints and d deletes so there is no continuation to the second expression in which s searches for ^ start of line to replace it with two spaces. ; separates expressions, { and } group them.

switch -e has been left out.

Similar to

$  | sed '1p; 1d; s/^/  /'
Posted in Hakre's Tips, Uncategorized | Tagged | Leave a comment

Gnome Shell Quickfix Cheatsheet

Disable work-space up/down movers which block key bindings I use in Phpstorm. Important with that is that I don’t use these dynamic work-spaces at all, so making them static and only one:

dconf write /org/gnome/desktop/wm/preferences/num-workspaces 1
dconf write /org/gnome/mutter/dynamic-workspaces false
dconf write /org/gnome/desktop/wm/keybindings/switch-to-workspace-up "['disabled']"
dconf write /org/gnome/desktop/wm/keybindings/switch-to-workspace-down "['disabled']"

Just in case for restoring needs, these were my previous values (where not obvious):

switch-to-workspace-up=['<Control><Alt>Up']
switch-to-workspace-down=['<Control><Alt>Down']

More reference on searching for keyboard bindings on the command line is outlined in Hunting the Keyboard Shortcut (Dec 2018).

Posted in Hakre's Tips, Uncategorized | Tagged , , , , , | Leave a comment

Git – Set the Author Date to The Committer Date of a Recent Commit

hakre-git-committer-date-git-gone-1

Ah gosh that one commit has the author date just too far off, but if it
would be the same as the committer date, that would be fine…

  1. Locate the commit when rebase interactively and mark for edit. Then
    go there to edit [1].
  2. Extract and export that commits committer date as GIT_COMMITTER_DATE
    $ export GIT_COMMITTER_DATE="$(git log --format=%cD -1)"
  3. Amend w/ the author date then set to the committer date while preserving it via the exported environment parameter (variable)
    $ git commit --amend --date="$GIT_COMMITTER_DATE" -C HEAD
  4. Unset the GIT_COMMITTER_DATE
    $ unset GIT_COMMITTER_DATE
  5. Continue the rebase to finish
    $ git rebase --continue

An update to this post with one-liners and a couple of more options is available:


hakre-git-committer-date-git-gone-2

[1] A date/time related intro to interactive rebase is also given in Change the date of a git commit (by Hugo Di Francesco; Aug 2018), the whole story in the git manual on interactive rebase which is always worth the read.

Images motive based on a visual excerpt from a TV series episode named “git gone” which is also the imaginary product name, the further text reads “kills bugs on contact” on the spray can label.

Posted in Hakre's Tips, Pressed | Tagged | Leave a comment

Install / Update Dbeaver Community on Ubuntu

Update: Turns out I was too eager to get the command line running. While it’s fine to have it perhaps for some systems, it is actually the case that Dbeaver has both a Debian repository and an Unbuntu PPA as I just learned:

sudo add-apt-repository ppa:serge-rider/dbeaver-ce
sudo apt-get update
sudo apt-get install dbeaver-ce

It’s all on the download page [2] and all you need is to have the patience to scroll down (or Ctrl+F).

Highly recommended as there are updates often, it’s perhaps worth to schedule the downloads in the background as the repository can be slow.


 

I recently started to use Dbeaver [1] on my Ubuntu system. It gets updated quite seriously and luckily there are releases with .deb packages, so the package manager can install and update them. And there is an URL redirecting always to the lastest version.

So her is my current state of the one-liner to run the upgrade when I get noticed:

$ sudo apt install "./$(
    curl -O "$(
      curl -sL -I -w '%{url_effective}' \
        https://dbeaver.io/files/dbeaver-ce_latest_amd64.deb \
    | tail -1 )" -w '%{filename_effective}'
  )"

Standard disclaimers apply, verify checksums and the yadda yadda, otherwise, you know, install as root from the internet has never let you down than once.

[1] https://dbeaver.io/

Posted in Hakre's Tips, Tools, Uncategorized | 4 Comments

Hunting the Keyboard Shortcut

Recently while in the mood I decided to upgrade my Thinkpad X280  from Ubuntu 16.04 LTS (for which it had the approval) to more current Ubuntu 18.04 LTS.

That also meant that I’m back on Gnome Shell which I’m not really a fan of, I was able to get my hands dirty on it when I was using Fedora a lot and it was new (“Gnome 3”) and well, I found it a bit rough.

However for the UI now – that is some years later – as it has been tailored for the Ubuntu flavor I find it quite acceptable (not because of Ubuntu but just the package is fine). I merely had some issues with the Laptop on Ubuntu 18.04 which most likely are not exactly related to Ubuntu 18.04 in specific, I’d like to write down about in this blog post:

ThinkPad Pro Docking Station with ThinkPad X280 on Ubuntu 18.04

First of all with the Lenovo ThinkPad Pro Docking Station (the USB-C one where you put the Laptop into and the USB-C docks from the left) I have in use there were some problems with my USB Keyboard on the docking station – it was just not enabled. This can be checked if it has a Num Lock LED and pressing Num Lock should toggle the light on and off. If you’ve got a keyboard with Num Lock LED at least in desktop mode this is a good check, while booting this is no check at all because there is no Num Lock LED going on, at least not for me. Apart from input devices via USB (I only have input devices on the dock at boot time normally) everything else worked with the docking station out of the box: Video via VGA port and Ethernet adapter.

It took me quite some time until I learned about having some BIOS settings influencing USB connectivity at boot time. Right now it works since some days in an acceptable manner (boot within dock and outside, suspend, take out, use out, suspend, put in etc.) and two BIOS settings I could identify I need to have for this working:

  1. Config / Thunderbolt (TM) 3 / Security Level: “No Security” (while having the Thunderbolt(TM) device “Disabled” for support in Pre Boot Environment)
  2. Config / USB / USB UEFI Bios Suppport: “Enabled”

As it was quite a bit of change here change there, this is perhaps not all settings, but I was using these. There is a warning to not enable a specific Linux one (which I had enabled to try it but disabled it quickly again as it is reported to brick Thinkpads on change (!)) and quite some users are reporting problems with the docking station regarding video which never was an issue for me from the beginning.

From my subjective impression, it was more an out-of-the-box experience while on Ubuntu 16.04, but it might be just since I upgraded the OS I perhaps wanted to finally get this into order, so this might be useful regardless of which Ubuntu version (or the underlying Kernel version).

Hunting the Keyboard Shortcut in the Dconf

While it was not enough to have actual keyboard connectivity problems (which really suck as the X280 has only one USB port left for use when in the dock, so I could only have mouse or keyboard working) with the Ubuntu upgrade to 18.04 I even “lost” one of the main keyboard shortcuts you have in browsers / editors / programming: CTRL+F to find in page / document / editor.

Finally I found a way to trouble-shoot this quickly, it works for any system that supports the dconf utility. With dconf dump it is possible to search for keyboard shortcut sequences, in my case CTRL+F is a “f” there, it can be quickly (and case independently) searched for:

$ dconf dump / | grep -i 'f'
move-to-workspace-9=['f']

Finally I could locate the culprit. Finding out under which configuration path needs a sed filter with a little “program” (examples of case insensitivity and hold buffer):

$ dconf dump / | sed -n '/^\[.*\]$/h;/f/I{x;p;x;p}'
[org/gnome/desktop/wm/keybindings]
move-to-workspace-9=['f']

It then shows the path to the setting above the match. The rest was merely straight forward to edit out that keyboard shortcut which I have no idea at all how it ended in there:

$ dconf write /org/gnome/desktop/wm/keybindings/move-to-workspace-9 "['disabled']"

I don’t know how I was finally able to check that one, I actually was trying out the Ubuntu Keyboard Shortcuts Troubleshooting guide in the Wiki which made a good impression to me as it allowed me to check if/what is actually working with my keyboard, however it’s more on the event level which turned out working for me. And then I needed to look further and with one of many shattered Stackoverflow postings, eventually another time the hint on Dconf Editor and that it has Keyboard Shortcut configuration “somewhere there” did let me fiddle with searching within the shell.

In my opinion a recommended utility to install on Ubuntu 18.04 LTS when using the Gnome Shell for sure is “gnome-tweaks” also known as Tweaks or Gnome Tweaks Tool.

Posted in Hakre's Tips | Tagged , , , , , , , , , | 1 Comment

Compile ripgreg (rp) on Ubuntu 16.04 LTS

Just a quick note to myself on how to compile the insanely fast rg utility from git sources w/ AVX and SIMD activated.

  1. Clone from sources: git clone git@github.com:BurntSushi/ripgrep.git --depth 1 && cd ripgrep
  2. Install rustup to be able to compile against nightly Rust releases: curl https://sh.rustup.rs -sSf | sh
  3. Enable the nightly rust release for the ripgrep project: rustup override set nightly
  4. Compile: ./compile
  5. The new binary can be found run from ./target/release/rg

Shell installer are quite fishy, so this is not the preferred way of installation, there is also the possibility to directly install it via (packaged) cargo command (cargo install ripgrep) but that version is w/o AVX/SIMD as both can not compile (currently) with the stable Rust version.

Additionally there is a home-/ linux- brew based installer, but I have not tried it.

References:

Posted in Uncategorized | Tagged , , , | Leave a comment

Using Assertions with (Legacy) PHP Code

hakre-pantheon-preserveWhile it was not much advised to use assertions (the assert PHP language construct) prior to PHP 7 due to the fact that it actually eval’ed a string’ed code, these days are gone. This is probably a lesser known fact with all the other immense improvements PHP 7 and 7.1 came with, so I’d like to take the opportunity with this post to highlight the PHP assertion feature that comes with zero run-time overhead and zero side-effects for production code. Continue reading

Posted in Developing, Hakre's Tips, PHP Development, PHP Development, Pressed, The Know Your Language Department, Tools | Tagged , , , , , , , | Leave a comment

Lazy Loading in PHP Object Composition

When it comes to nicely performing PHP scripts (yes in PHP these are all scripts as PHP code is run-time) there is a nice addition since PHP 7 named the Null coalescing operator which plays very well with the basic nature that PHP is loosely typed and unset variables are basically null when warnings are not in effect. You know what? Not set warnings (like with isset) are not in effect with the  ?? Null Coalescing Operator (PHP Manual).

So how about a simple and quick usage example for lazy-loading? By default all class members are null when defined:

class MyFoo
{
  /**
   * @var Config
   */
  private $config;
}

With any new MyFoo() that private property will be null. Now one thing could be to properly inject the Config in the constructor (__construct()) but while you’re writing code you might want to defer the details to later (dependency injection is not always useful but don’t get me wrong it’s generally the option to go on with constructor injection while you progress) one way to deal with the outcome is lazy loading (back to constructor injection, you might want to inject a ConfigFactory then).

So what is about lazy loading here? Let’s say MyFoo is used more centrally in an application (a primitive)  so might be some kind of service to your application, you only want to instantiate the Config in case it is actually used. You know that it is used when it is acquired from the service-like-acting MyFoo when the getter is called (mind the Law od Demeter and Getters and Setters can be a smell, too):

class MyFoo
{
    ...
    public function getConfig(): Config {
        return $this-&gt;config;
    }
}

Now when that getConfig() method is called, it will return null unless the Config has been set to private MyFoo::$config so far – which is not a case in our scenario. Also the Config of MyFoo is a singleton (not the (anti-) pattern) , so it is easy to implement it on the go:

class MyFoo
{
    ...

    public function getConfig(): Config {
        return $this-&gt;config ?? $this-&gt;config = new Config();
    }
}

Creating the Config object is here deferred to the point when getConfig() is called the first time. That is also the first time it is needed (by definition of this simplified example at least). The Null Coalescing Operator is helpful here to do this in a single line.

It is also easy to switch to constructor injection (eager loading) or even constructor injection based lazy loading when you inject a factory that will create (or a repository that providea) the Config at that time in place.

I hope this is a nice example to show how well the Null Coalescing Operator in PHP plays with non-initialized object properties (or even unset variables). Which reminds me I should not use it too often.

In the next PHP version (7.2) this can be shortened even more btw (see the PHP RFC: Null Coalescing Assignment Operator):

class MyFoo
{
    ...

    public function getConfig(): Config {
        return $this-&gt;config ??= new Config();
    }
}

The only thing missed for ?? addicts like me might be the sometimes unnecessary operand after the operator:

    $var = $unset ??; # expressing just null

This will spare isset() if conditionals but might also direct dealing with nulls to other places (which can add a lot of burden to consumers). But I’m just too little experienced in writing PHP wiki RFCs and I couldn’t even provide a patch, so with closing time for PHP 7.2 this is really future material (and perhaps just a sign I want “wrong” things).

/Edit: An RFC exists already: PHP RFC: Unary null coalescing operator


Read On:

Posted in Hakre's Tips, PHP Development, PHP Development, Pressed, The Know Your Language Department, Tools | Tagged , | Leave a comment

Make any Composer Command Segfault

This is from the shock your co-worker department: There is an easy one-liner to make any composer based project spit “Segmentation fault (core dumped)” regardless of the Composer command entered: Continue reading

Posted in Bugs and Features, PHP Development, Pressed, Tools | Tagged , , | Leave a comment

History of the PHP date timezone settings warning

Elephant and Duck

Now with the newborn elefant PHP 7 in the herd, there is a lift on the date timezone settings warning: it has just been removed. That means, it’s now that you need to take care in the server’s configuration that the proper default timezone value is set, otherwise it will fall-back to UTC with no more reminder spamming the log-files or screen. Alternatively, you can make use of the date_default_timezone_set() function within your application to configure the default value.

Continue reading

Posted in Pressed, The Know Your Language Department | Tagged , , , , | Leave a comment

Linting PHP Files in Parallel on Travis

php-lint-travis-krita

With PHP 7 around the corner here is a small tip how you can at least lint the code in your project to be PHP 7 syntax compatible. That allows you to easier obtain forward-compatible PHP code with ease. So if you already integrate with Travis, all you need to do is to add some two-to-four lines to your .travis.yaml file and you’re done. Here is how: Continue reading

Posted in Hakre's Tips, PHP Development, Pressed, Tools | Tagged , , , , , , , , | Leave a comment

The SimpleXMLElement Magic Wonder World in PHP

PHP’s Simplexml ships with a lot of magic to simplify access to an XML documents element and attribute node values. Some criticize this and suggest to use the DOM library instead. The DOM library on the other hand, even it can do everything tend to be known with an XML document, it’s pretty verbose – and yes that’s some critique with XML as well, the verbosity. Sure there are many nice libraries around the DOM library and wrapping it and one of these libraries again is Simplexml.

From a data-type perspective, the SimpleXMLElement is quite an interesting one actually, literally I mean figuratively -what not. It’s something like a hierarchical data-structure. One that comes with it’s own query method via the xpath() method. It can be iterated, traversed, nodes added and leafs unset as if it would be an array or an std class. And it comes with a serializer built in – into XML – in both directions.

From it’s internals, it’s fully backed from C code below from libxml, it’s also pretty fast and perhaps also fine with the memory (at least I hope).

It speaks Unicode in the popular UTF-8 encoding you know from the web and if you need to, it can even convert to other encodings.

And one of it’s magic properties is that it’s such a class of classes in PHP that can be casted from one class to another. This works by converting one (subclass of a) SimpleXMLElement to another subclass of it by sending it through DOM (the besaid sister-library):

$foo  = new Foo("<doc/>");
$via  = dom_import_simplexml($foo);
$cast = simplexml_import_dom($via, 'Bar');
var_dump(get_class($cast)); # string(3) "Bar"

This is actually not only true for SimpleXMLElement but also to the node-classes in a DOMDocument to a certain degree but this post is about SimpleXMLElement so just saying.

I have to say it: With so much simplification and magic, there is a price to pay and there are limitations, too. The constructor is final, so you can’t override it. No way :). This hinders you in terms of “classic” object inheritance. One path out is to decorate the elements, but even I did this in the past, it doesn’t feel equally well as well. It might also be more work as first thought. But most often, extending SimpleXMLElement just more to sugar-in some methods, so it’s often not worth for a full-feature decoration. So this is a limitation. ERR_TOO_MUCH_MAGIC comes to mind.

And some argue as for the data-structure you can’t use it as array or object store as all class-properties or array-indexes represent either XML element or attribute nodes only accepting scalar types (actually stringy values).

Storing Arrays and Objects in a SimpleXMLElement

Let me elaborate on that last point a little. It’s normally not possible to store array or object data inside a SimpleXMLElement. As you couldn’t serialize it as XML, by default it’s fordidden to do:

class Foo extends SimpleXMLElement
{
}

$foo  = new Foo("<doc/>");
# Warning: It is not yet possible to assign complex types to properties
$foo->bar = $foo;

If you now think that creating a private field and assigning the data to the private field would be a solution, it will teach you about another limitation: there are no private fields with a SimpleXMLElement. It’s field are all exposed XML nodes so all you can store there are strings.

But wouldn’t it be nice to actually be able to store some objects therein? Let’s elaborate a bit on the internals which is how I discovered some nice properties of the document model in PHP and it’s use from within Simplexml.

The SimpleXMLElement is somewhat a shell around some other object only. It perhaps can be describben as a Flyweight (as in the pattern), an interface of factory and object manager of the underlying document nodes. And the document again can be represented as a DOMNode which again is a shell/interface around the underlying document node managed by libxml. This is the underlying structure of not only the SimpleXMLElements but also the tree structure of the DOM. The PHP SimpleXML/DOM extensions manage all these document nodes nicely for us.

If it is now possible to turn a SimpleXMLElement into a DOMNode it is then – because of the object model in PHP with the dynamic properties (every object in PHP is actually somewhat an array/hash) – possible to assing data to a document node without creating a new element as it would be the case on level of SimpleXMLElement:

class Foo extends SimpleXMLElement
{
    function setData($data) {
        $element = dom_import_simplexml($this);
        $element->data = $data;
    }
}

$foo = new Foo("<doc/>");
$foo->addChild('bar')->setData($foo);

This does actually work, but the data won’t yet persist. What is necessary to keep the dynamic property data here in memory within the DOM is to add as circular reference to the DOMNode, let’s call that one circref in this example. It’s then possible to write and read the data:

        ...

        function setData($data) {
            $element = dom_import_simplexml($this);            
            $element->data    = $data;
            $element->circref = $element;
        }

        function getData() {
            $element = dom_import_simplexml($this);
            return $element->data;
        }

        ...

The usage example demonstrates that it is now possible to store (or attach) an object to the document node accessed via Simplexml:

$foo = new Foo("<doc/>");
$foo->addChild('bar')->setData($foo);

var_dump($foo->bar->getData());

# class Foo#1 (1) {
#   public $bar =>
#   class Foo#2 (0) {
#   }
# }

For those who hate Simplexml but even read until here: As already written earlier, this same principle works with pure DOMDocument / DOMNode as well. Just in case you want to re-use the node based data-structure and you need to add (object) information to it. All you need is the circular reference to keep the association between the data and the node in memory. And it’s really within the same document:

# obtaining the data via DOMDocument
$doc = dom_import_simplexml($foo)->ownerDocument;

$bar = $doc->getElementsByTagName('bar')->item(0);
var_dump($bar->data);

As you can imagine same applies for xpath queries – both via DOMXPath or SimpleXMLElement.

Posted in Developing, Hakre's Tips, PHP Development, Pressed, The Know Your Language Department, Uncategorized | Tagged , , , , | Leave a comment

Kubuntu Default Browser

The system-settings don’t reflect the whole picture in Kubuntu. Settings can be done via the command-line. Here exemplary to chromium:

gvfs-mime --set x-scheme-handler/http chromium-browser.desktop
gvfs-mime --set x-scheme-handler/https chromium-browser.desktop

I had an issue with this for quite some time, I finally found the answer via “opening web link from evolution uses wrong browser”.

Posted in Hakre's Tips, Pressed, Uncategorized | Leave a comment

Installing PDF Printer under Kubuntu with AppArmor and Samba

It actually should be as little as installing cups-pdf (CUPS-PDF (Ubuntuusers German)):

$ sudo apt-get install cups-pdf

Then opening Printers in system preferences did show the new printer.

However printing a test-page didn’t work. I then just followed the tail of the syslog:

# tail -f /var/log/syslog

to find out that app-armor blocked something:

Feb  9 09:47:15 producer25 kernel: [43208.761736] type=1400 audit(1423471635.886:111): apparmor="DENIED" operation="connect" profile="/usr/lib/cups/backend/cups-pdf" name="/run/samba/winbindd/pipe" pid=14195 comm="cups-pdf" requested_mask="rw" denied_mask="rw" fsuid=0 ouid=0

With this error message at hand it was easy to find a bug-report which offered a solution that worked for me directly:

add this to your profile (in the cups-pdf section):

/run/samba/winbindd/pipe rw,

then do this:

$ sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.cupsd

After that I restarted cups.d and apparmor.d and it directly worked.

Printing the PDF

PDF files are stored under ~/PDF by default. If you print large files, it takes some time until the PDF file is written in full. Unless totally done, you (normally) can’t open it successfully. There is no notification given (like with compressing files for example) when the print job as been done and the PDF is fully written. There is also no temporary name. I didn’t look into the configuration of Cups-PDF deeply as I only wanted to get it to the run quickly, so just sharing the experiences, it’s probably worth a feature-request when I find the time.

Posted in Hakre's Tips | Tagged , , , | Leave a comment