This article is part of my #100DaysOfCode and #100DaysOfBlogging challenge. R1D11

This is part four of a series of articles about the PHP Version Switcher.


Today I finally breathe life into the module function. 🕺🏼

Administrator privileges

Since the Apache services will be restarted, the module requires administrator privileges. I define the requirement in the module by adding the following line.

#Requires -RunAsAdministrator

When opening a new PowerShell, an error is raised.

Module requires administrator-privileges

Now, I either

  • a) add a condition/parameter that the module is only imported when running an elevated shell or
  • b) move the import to a profile that gets only loaded when running an elevated shell.

HAL9256 was so kind to help me out here by providing an answer.

It works when I add the following condition to my profile.ps1.

$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
if ($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Import-Module pvs
}

Configuration

For right now, I will hard-code the available PHP versions in a switch statement. In the future I would like to extract the configuration or even automate it if possible. I add the following switch statement to my pvs function.

switch ($version) {
    "7.0" { $phpPath = "C:\webserv\php-7.0.33-Win32-VC14-x64" }
    "7.1" { $phpPath = "C:\webserv\php-7.1.29-Win32-VC14-x64" }
    "7.2" { $phpPath = "C:\webserv\php-7.2.18-Win32-VC15-x64" }
    "7.3" { $phpPath = "C:\webserv\php-7.3.5-Win32-VC15-x64" }
    "7.4" { $phpPath = "C:\webserv\php-7.4-ts-windows-vc15-x64-r3322ae2" }
    Default { throw "Provided PHP version $version is not supported" }
}

The following lines remove the existing symlink.

Write-Host "Removing SymbolicLink..." -ForegroundColor DarkCyan
Write-Host ""
(Get-Item C:\webserv\php\).Delete()

The following lines create the new symlink.

Write-Host "Creating SymbolicLink..." -ForegroundColor DarkCyan
Write-Host ""
New-Item -ItemType SymbolicLink -Path C:\webserv\ -Name php -Value $phpPath

Restart Apache service

The following lines restart the Apache service.

Write-Host "Restarting Apache..." -ForegroundColor DarkCyan
Write-Host ""
C:\webserv\httpd-2.4.39-win64-VC15\Apache24\bin\httpd.exe -k restart

Summary

My pvs.psm1 file looks like the following.

<#
  .Synopsis
  PHP version switcher for Windows

  .Description
  This function switches to a specified PHP version in an environment where
  multiple PHP versions are installed as Apache Modules.

  .Parameter version
  The PHP version to switch to.

  .Example
  pvs 7.3
#>

#Requires -RunAsAdministrator

# @todo Add configuration file with
# - PHP versions
# - Apache path
# - Smylink path & name
# - Directory(/ies) containing log files
# @todo Parameter to just restart Apache
# @todo Parameter to delete log files
function pvs {
    [CmdletBinding()]

    # Fetch version to switch to
    Param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [Alias("v")] [String]$version
    )

    switch ($version) {
        "7.0" { $phpPath = "C:\webserv\php-7.0.33-Win32-VC14-x64" }
        "7.1" { $phpPath = "C:\webserv\php-7.1.29-Win32-VC14-x64" }
        "7.2" { $phpPath = "C:\webserv\php-7.2.18-Win32-VC15-x64" }
        "7.3" { $phpPath = "C:\webserv\php-7.3.5-Win32-VC15-x64" }
        "7.4" { $phpPath = "C:\webserv\php-7.4-ts-windows-vc15-x64-r3322ae2" }
        Default { throw "Provided PHP version $version is not supported" }
    }

    Write-Host "PHP Version Switcher 1.0.0 by Andi Rückauer" -ForegroundColor Blue
    Write-Host ""
    Write-Host "Switching to version: $version..." -ForegroundColor DarkCyan
    Write-Host ""

    # Remove SymbolicLink
    # @todo Only delete, if it does exist. Get-Item throws an error otherwise.
    Write-Host "Removing SymbolicLink..." -ForegroundColor DarkCyan
    Write-Host ""
    (Get-Item C:\webserv\php\).Delete()

    # Create new symlink
    Write-Host "Creating SymbolicLink..." -ForegroundColor DarkCyan
    Write-Host ""
    New-Item -ItemType SymbolicLink -Path C:\webserv\ -Name php -Value $phpPath
re
    # Restart Apache
    # @todo If log files are to be deleted: Stop Apache service, delete log files, start Apache service
    Write-Host "Restarting Apache..." -ForegroundColor DarkCyan
    Write-Host ""
    C:\webserv\httpd-2.4.39-win64-VC15\Apache24\bin\httpd.exe -k restart
}

Export-ModuleMember -Function pvs

As you may have noticed, I added already some @todo tags for improvement and further ideas.

Test

I will now test the pvs module by switching from PHP 7.2 to PHP 7.3.

php -v;pvs 7.3;php -v

PHP Version Switcher in action

Bingo! 🙌🏼

Next steps

There is already a to-do list with improvements. Configuration is probably one of the most important due to reusability reasons. I would prefer a less verbose output.

What would you add or change? Let me know on Twitter.