From 2d342e5282a367f401d778671e2c13acd145ee9c Mon Sep 17 00:00:00 2001 From: Irfan Hardiyanto Date: Mon, 15 Jun 2026 11:01:09 +0700 Subject: [PATCH 1/2] fix(ext): resolve sqlsrv PECL install across Win/Linux/macOS Windows: rewrite Test-URLExists with Invoke-WebRequest so HEAD probes follow the windows.php.net -> downloads.php.net 302 redirect (and fall back to a ranged GET when mirrors reject HEAD). This unblocks sqlsrv / pdo_sqlsrv installs that were failing with "No compatible package found" even though the zip exists upstream. Linux/macOS: pre-flight unixODBC headers before pecl install sqlsrv| pdo_sqlsrv and surface a package-manager-specific install hint instead of letting the build fail mid-compile. Covers apt, dnf, yum, pacman, zypper and brew (incl. Apple Silicon /opt/homebrew paths). Both platforms now print a post-install advisory pointing at the Microsoft ODBC Driver for SQL Server and the MS Learn setup guide, since the PHP extension alone is not enough to connect at runtime. Bumps phpvm to 1.7.1. --- linux/install.sh | 2 +- linux/phpvm.sh | 54 ++++++++++++++++++++++++++++++++++++++++++++- version.txt | 2 +- windows/install.ps1 | 2 +- windows/phpvm.ps1 | 37 +++++++++++++++++++++++++------ 5 files changed, 86 insertions(+), 11 deletions(-) diff --git a/linux/install.sh b/linux/install.sh index ebf13b8..7a9c229 100644 --- a/linux/install.sh +++ b/linux/install.sh @@ -6,7 +6,7 @@ set -e -PHPVM_VERSION="1.7.0" +PHPVM_VERSION="1.7.1" PHPVM_DIR="${PHPVM_DIR:-$HOME/.phpvm}" PHPVM_REPO="https://raw.githubusercontent.com/devhardiyanto/phpvm/main" diff --git a/linux/phpvm.sh b/linux/phpvm.sh index d43d66e..dd22d95 100644 --- a/linux/phpvm.sh +++ b/linux/phpvm.sh @@ -10,7 +10,7 @@ # phpvm use 8.3.0 # ============================================================================== -PHPVM_VERSION="1.7.0" +PHPVM_VERSION="1.7.1" PHPVM_DIR="${PHPVM_DIR:-$HOME/.phpvm}" PHPVM_VERSIONS="$PHPVM_DIR/versions" PHPVM_CURRENT="$PHPVM_DIR/current" @@ -557,22 +557,74 @@ phpvm_ext_install() { return 1 } + _phpvm_ext_preflight "$name" || return 1 + local ver="${2:-}" if [[ -n "$ver" ]]; then _step "Installing $name-$ver via PECL ..." pecl install "$name-$ver" || { _err "Failed to install $name-$ver via PECL." + _phpvm_ext_runtime_notes "$name" return 1 } else _step "Installing $name via PECL ..." pecl install "$name" || { _err "Failed to install $name via PECL." + _phpvm_ext_runtime_notes "$name" return 1 } fi _ok "Done. Enable with: phpvm ext enable $name" + _phpvm_ext_runtime_notes "$name" +} + +# Build-time prerequisites for specific extensions. Warn early instead of +# letting `pecl install` fail mid-build with cryptic compiler errors. +_phpvm_ext_preflight() { + local name="$1" + case "$name" in + sqlsrv|pdo_sqlsrv) + # unixODBC headers (sql.h / sqlext.h) are required to compile sqlsrv. + if command -v odbc_config &>/dev/null; then return 0; fi + local inc + for inc in /usr/include/sql.h /usr/local/include/sql.h \ + /opt/homebrew/include/sql.h /opt/homebrew/opt/unixodbc/include/sql.h \ + /usr/local/opt/unixodbc/include/sql.h; do + [[ -f "$inc" ]] && return 0 + done + _warn "unixODBC development headers not found — required to build $name." + local pm + pm=$(_phpvm_detect_os) + case "$pm" in + apt) _dim "Install: sudo apt-get install -y unixodbc-dev" ;; + dnf) _dim "Install: sudo dnf install -y unixODBC-devel" ;; + yum) _dim "Install: sudo yum install -y unixODBC-devel" ;; + pacman) _dim "Install: sudo pacman -S --needed unixodbc" ;; + zypper) _dim "Install: sudo zypper install -y unixODBC-devel" ;; + brew) _dim "Install: brew install unixodbc" ;; + *) _dim "Install unixODBC development headers via your package manager." ;; + esac + _dim "Then retry: phpvm ext install $name" + return 1 + ;; + esac + return 0 +} + +# Post-install advisories for extensions that need extra system components. +_phpvm_ext_runtime_notes() { + local name="$1" + case "$name" in + sqlsrv|pdo_sqlsrv) + echo "" + _dim "Note: $name also requires the Microsoft ODBC Driver for SQL Server" + _dim "to actually connect at runtime. Install (one-off, system-wide):" + _dim " https://learn.microsoft.com/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server" + _dim "Setup guide: https://learn.microsoft.com/sql/connect/php/step-1-configure-development-environment-for-php-development" + ;; + esac } phpvm_ext_enable() { diff --git a/version.txt b/version.txt index bd8bf88..943f9cb 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.7.0 +1.7.1 diff --git a/windows/install.ps1 b/windows/install.ps1 index 8ee9ffd..12565f7 100644 --- a/windows/install.ps1 +++ b/windows/install.ps1 @@ -7,7 +7,7 @@ Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" -$PHPVM_VERSION = "1.7.0" +$PHPVM_VERSION = "1.7.1" $PHPVM_DIR = if ($env:PHPVM_DIR) { $env:PHPVM_DIR } else { "$env:USERPROFILE\.phpvm" } $PHPVM_BIN = "$PHPVM_DIR\bin" diff --git a/windows/phpvm.ps1 b/windows/phpvm.ps1 index 477dc89..d5ce7a1 100644 --- a/windows/phpvm.ps1 +++ b/windows/phpvm.ps1 @@ -14,7 +14,7 @@ Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" # -- Constants ----------------------------------------------------------------- -$PHPVM_VERSION = "1.7.0" +$PHPVM_VERSION = "1.7.1" $PHPVM_DIR = if ($env:PHPVM_DIR) { $env:PHPVM_DIR } else { "$env:USERPROFILE\.phpvm" } $VERSIONS_DIR = "$PHPVM_DIR\versions" $CURRENT_LINK = "$PHPVM_DIR\current" @@ -259,13 +259,21 @@ function Get-XDebugHash ([string]$dllUrl) { } function Test-URLExists ([string]$url) { + $ProgressPreference = "SilentlyContinue" + # HEAD via Invoke-WebRequest follows 30x redirects (windows.php.net -> downloads.php.net). try { - $req = [System.Net.WebRequest]::Create($url) - $req.Method = "HEAD" - $res = $req.GetResponse() - $res.Close() - return $true - } catch { return $false } + $r = Invoke-WebRequest -Uri $url -Method Head -MaximumRedirection 5 ` + -UseBasicParsing -TimeoutSec 5 -ErrorAction Stop + return ($r.StatusCode -ge 200 -and $r.StatusCode -lt 400) + } catch { + # Some mirrors reject HEAD (405) — fall back to a 1-byte ranged GET. + try { + $r = Invoke-WebRequest -Uri $url -Method Get -MaximumRedirection 5 ` + -UseBasicParsing -TimeoutSec 5 ` + -Headers @{ Range = "bytes=0-0" } -ErrorAction Stop + return ($r.StatusCode -ge 200 -and $r.StatusCode -lt 400) + } catch { return $false } + } } # ============================================================================== @@ -813,6 +821,21 @@ function Install-PECLExt ([string]$extName, [string]$requestedVer = "") { Remove-Item $tempZip, $tempExtract -Recurse -Force -ErrorAction SilentlyContinue Write-Ok "Done. Enable with: phpvm ext enable $extName" + + Show-ExtRuntimeNotes $extName +} + +# Post-install runtime advisories for extensions that need extra system components. +function Show-ExtRuntimeNotes ([string]$extName) { + switch -Regex ($extName.ToLower()) { + '^(sqlsrv|pdo_sqlsrv)$' { + Write-Host "" + Write-Dim "Note: sqlsrv / pdo_sqlsrv also requires the Microsoft ODBC Driver" + Write-Dim "for SQL Server on this machine. Install (one-off, system-wide):" + Write-Dim " https://learn.microsoft.com/sql/connect/odbc/download-odbc-driver-for-sql-server" + Write-Dim "Setup guide: https://learn.microsoft.com/sql/connect/php/step-1-configure-development-environment-for-php-development" + } + } } function Install-XDebug { From f470ebd4934e44a50e06e5d988e21a98affa9ca3 Mon Sep 17 00:00:00 2001 From: Irfan Hardiyanto Date: Mon, 15 Jun 2026 14:49:29 +0700 Subject: [PATCH 2/2] fix(ci): replace non-ASCII em-dash to satisfy PSScriptAnalyzer windows/phpvm.ps1 has no BOM, so PSUseBOMForUnicodeEncodedFile fires the moment any non-ASCII char appears. Swap the U+2014 em-dash in a comment for plain ASCII to keep the file pure ASCII like main. --- windows/phpvm.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/phpvm.ps1 b/windows/phpvm.ps1 index d5ce7a1..3cf4540 100644 --- a/windows/phpvm.ps1 +++ b/windows/phpvm.ps1 @@ -266,7 +266,7 @@ function Test-URLExists ([string]$url) { -UseBasicParsing -TimeoutSec 5 -ErrorAction Stop return ($r.StatusCode -ge 200 -and $r.StatusCode -lt 400) } catch { - # Some mirrors reject HEAD (405) — fall back to a 1-byte ranged GET. + # Some mirrors reject HEAD (405) -- fall back to a 1-byte ranged GET. try { $r = Invoke-WebRequest -Uri $url -Method Get -MaximumRedirection 5 ` -UseBasicParsing -TimeoutSec 5 `