Skip to content

Commit 9e571e9

Browse files
committed
Fix instructions for windows-native
1 parent 29774dc commit 9e571e9

File tree

2 files changed

+229
-1
lines changed

2 files changed

+229
-1
lines changed

include/download-instructions/windows-native.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
On the command line, run the following commands:
33
</p>
44
<pre><code class="language-powershell line-numbers">
5-
powershell -c "irm https://php.net/downloads/install.ps1 <?= $version; ?> | iex"
5+
powershell -c "& ([ScriptBlock]::Create((irm 'https://php.net/install/windows.ps1'))) -Version <?= $version; ?>"
66
</code></pre>

install/windows.ps1

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
<#
2+
.SYNOPSIS
3+
Downloads and sets up a specified PHP version on Windows.
4+
5+
.PARAMETER Version
6+
Major.minor or full version (e.g., 7.4 or 7.4.30).
7+
8+
.PARAMETER Path
9+
Destination directory (defaults to C:\php<Version>).
10+
11+
.PARAMETER Arch
12+
Architecture: x64 or x86 (default: x64).
13+
14+
.PARAMETER ThreadSafe
15+
ThreadSafe: download Thread Safe build (default: $False).
16+
17+
.PARAMETER Timezone
18+
date.timezone string for php.ini (default: 'UTC').
19+
#>
20+
21+
[CmdletBinding()]
22+
param(
23+
[Parameter(Mandatory = $true, Position=0)]
24+
[ValidatePattern('^\d+(\.\d+)?(\.\d+)?((alpha|beta|RC)\d*)?$')]
25+
[string]$Version,
26+
[Parameter(Mandatory = $false, Position=1)]
27+
[string]$Path = "C:\php$Version",
28+
[Parameter(Mandatory = $false, Position=2)]
29+
[ValidateSet("x64", "x86")]
30+
[string]$Arch = "x64",
31+
[Parameter(Mandatory = $false, Position=3)]
32+
[bool]$ThreadSafe = $False,
33+
[Parameter(Mandatory = $false, Position=4)]
34+
[string]$Timezone = 'UTC'
35+
)
36+
37+
Function Get-File {
38+
param (
39+
[Parameter(Mandatory = $true, Position=0)]
40+
[ValidateNotNullOrEmpty()]
41+
[string] $Url,
42+
[Parameter(Mandatory = $false, Position=1)]
43+
[string] $FallbackUrl,
44+
[Parameter(Mandatory = $false, Position=2)]
45+
[string] $OutFile = '',
46+
[Parameter(Mandatory = $false, Position=3)]
47+
[int] $Retries = 3,
48+
[Parameter(Mandatory = $false, Position=4)]
49+
[int] $TimeoutSec = 0
50+
)
51+
52+
for ($i = 0; $i -lt $Retries; $i++) {
53+
try {
54+
if($OutFile -ne '') {
55+
Invoke-WebRequest -Uri $Url -OutFile $OutFile -TimeoutSec $TimeoutSec
56+
} else {
57+
Invoke-WebRequest -Uri $Url -TimeoutSec $TimeoutSec
58+
}
59+
break;
60+
} catch {
61+
if ($i -eq ($Retries - 1)) {
62+
if($FallbackUrl) {
63+
try {
64+
if($OutFile -ne '') {
65+
Invoke-WebRequest -Uri $FallbackUrl -OutFile $OutFile -TimeoutSec $TimeoutSec
66+
} else {
67+
Invoke-WebRequest -Uri $FallbackUrl -TimeoutSec $TimeoutSec
68+
}
69+
} catch {
70+
throw "Failed to download the file from $Url and $FallbackUrl"
71+
}
72+
} else {
73+
throw "Failed to download the file from $Url"
74+
}
75+
}
76+
}
77+
}
78+
}
79+
80+
Function Get-Semver {
81+
[CmdletBinding()]
82+
param(
83+
[Parameter(Mandatory = $true, Position=0)]
84+
[ValidateNotNull()]
85+
[ValidatePattern('^\d+\.\d+$')]
86+
[string]$Version
87+
)
88+
$releases = Get-File -Url "https://downloads.php.net/~windows/releases/releases.json" | ConvertFrom-Json
89+
$semver = $releases.$Version.version
90+
if($null -eq $semver) {
91+
$semver = (Get-File -Url "https://downloads.php.net/~windows/releases/archives").Links |
92+
Where-Object { $_.href -match "php-($Version.[0-9]+).*" } |
93+
ForEach-Object { $matches[1] } |
94+
Sort-Object { [System.Version]$_ } -Descending |
95+
Select-Object -First 1
96+
}
97+
if($null -eq $semver) {
98+
throw "Unsupported PHP version: $Version"
99+
}
100+
return $semver
101+
}
102+
103+
Function Get-VSVersion {
104+
param(
105+
[Parameter(Mandatory = $true, Position=0)]
106+
[ValidateNotNull()]
107+
[ValidatePattern('^\d+\.\d+$')]
108+
[string]$Version
109+
)
110+
$map = @{
111+
'5.2' = 'VC6'
112+
'5.3' = 'VC9'; '5.4' = 'VC9'
113+
'5.5' = 'VC11'; '5.6' = 'VC11'
114+
'7.0' = 'VC14'; '7.1' = 'VC14'
115+
'7.2' = 'VC15'; '7.3' = 'VC15'; '7.4' = 'vc15'
116+
'8.0' = 'vs16'; '8.1' = 'vs16'; '8.2' = 'vs16'; '8.3' = 'vs16'
117+
'8.4' = 'vs17'; '8.5' = 'vs17'
118+
}
119+
120+
if ($map.ContainsKey($Version)) {
121+
return $map[$Version]
122+
}
123+
throw "Unsupported PHP version: $Version"
124+
}
125+
126+
Function Get-ReleaseType {
127+
param(
128+
[Parameter(Mandatory = $true, Position=0)]
129+
[ValidateNotNull()]
130+
[ValidatePattern('^\d+(\.\d+)?(\.\d+)?((alpha|beta|RC)\d*)?$')]
131+
[string]$Version
132+
)
133+
if ($Version -match "[a-zA-Z]") {
134+
return "qa"
135+
} else {
136+
return "releases"
137+
}
138+
}
139+
140+
Function Get-PhpFromUrl {
141+
param(
142+
[Parameter(Mandatory = $true, Position=0)]
143+
[ValidateNotNull()]
144+
[ValidatePattern('^\d+\.\d+$')]
145+
[string]$Version,
146+
[Parameter(Mandatory = $true, Position=1)]
147+
[ValidateNotNull()]
148+
[ValidatePattern('^\d+(\.\d+)?(\.\d+)?((alpha|beta|RC)\d*)?$')]
149+
[string]$Semver,
150+
[Parameter(Mandatory = $false, Position=2)]
151+
[ValidateSet("x64", "x86")]
152+
[string]$Arch = "x64",
153+
[Parameter(Mandatory = $false, Position=3)]
154+
[bool]$ThreadSafe = $false,
155+
[Parameter(Mandatory = $true, Position=4)]
156+
[ValidateNotNull()]
157+
[ValidateLength(1, [int]::MaxValue)]
158+
[string]$OutFile
159+
)
160+
$vs = Get-VSVersion $Version
161+
$ts = if ($ThreadSafe) { "ts" } else { "nts" }
162+
$zipName = if ($ThreadSafe) { "php-$Semver-Win32-$vs-$Arch.zip" } else { "php-$Semver-$ts-Win32-$vs-$Arch.zip" }
163+
$type = Get-ReleaseType $Version
164+
165+
$base = "https://downloads.php.net/~windows/$type"
166+
try {
167+
Get-File -Url "$base/$zipName" -OutFile $OutFile
168+
} catch {
169+
try {
170+
Get-File -Url "$base/archives/$zipName" -OutFile $OutFile
171+
} catch {
172+
throw "Failed to download PHP $Semver."
173+
}
174+
}
175+
}
176+
177+
$tempFile = [IO.Path]::ChangeExtension([IO.Path]::GetTempFileName(), '.zip')
178+
try {
179+
if ($Version -match "^\d+\.\d+$") {
180+
$Semver = Get-Semver $Version
181+
} else {
182+
$Semver = $Version
183+
$Semver -match '^(\d+\.\d+)' | Out-Null
184+
$Version = $Matches[1]
185+
}
186+
187+
if (-not (Test-Path $Path)) {
188+
try {
189+
New-Item -ItemType Directory -Path $Path -ErrorAction Stop | Out-Null
190+
} catch {
191+
throw "Failed to create directory $Path. $_"
192+
}
193+
} else {
194+
$files = Get-ChildItem -Path $Path
195+
if ($files.Count -gt 0) {
196+
throw "The directory $Path is not empty. Please provide an empty directory."
197+
}
198+
}
199+
200+
if($Version -lt '5.5' -and $Arch -eq 'x64') {
201+
$Arch = 'x86'
202+
Write-Host "PHP version $Version does not support x64 architecture on Windows. Using x86 instead."
203+
}
204+
205+
Write-Host "Downloading PHP $Semver to $Path"
206+
Get-PhpFromUrl $Version $Semver $Arch $ThreadSafe $tempFile
207+
Expand-Archive -Path $tempFile -DestinationPath $Path -Force -ErrorAction Stop
208+
209+
$phpIniProd = Join-Path $Path "php.ini-production"
210+
if(-not(Test-Path $phpIniProd)) {
211+
$phpIniProd = Join-Path $Path "php.ini-recommended"
212+
}
213+
$phpIni = Join-Path $Path "php.ini"
214+
Copy-Item $phpIniProd $phpIni -Force
215+
$extensionDir = Join-Path $Path "ext"
216+
(Get-Content $phpIni) -replace '^extension_dir = "./"', "extension_dir = `"$extensionDir`"" | Set-Content $phpIni
217+
(Get-Content $phpIni) -replace ';\s?extension_dir = "ext"', "extension_dir = `"$extensionDir`"" | Set-Content $phpIni
218+
(Get-Content $phpIni) -replace ';\s?date.timezone =', "date.timezone = `"$Timezone`"" | Set-Content $phpIni
219+
220+
Write-Host "PHP $Semver downloaded to $Path"
221+
} catch {
222+
Write-Error $_
223+
Exit 1
224+
} finally {
225+
if (Test-Path $tempFile) {
226+
Remove-Item $tempFile -Force -ErrorAction SilentlyContinue
227+
}
228+
}

0 commit comments

Comments
 (0)