Skip to content

Instantly share code, notes, and snippets.

@andkirby
Last active December 31, 2023 12:21
Show Gist options
  • Save andkirby/67e87e319c376b8676d559edb759e3fe to your computer and use it in GitHub Desktop.
Save andkirby/67e87e319c376b8676d559edb759e3fe to your computer and use it in GitHub Desktop.
Download PHP binaries archive on Windows from GitBash console or similar
#!/usr/bin/env bash
################################################################################
# This script can install PHP binaries on Windows in Bash.
#
# Link to this file:
# https://gist.github.com/andkirby/67e87e319c376b8676d559edb759e3fe/raw/php-git-bash-win.sh
#
# Download latest version by command in GitBash Windows console:
# $ curl -Ls bit.ly/php-bash-win | bash
#
# Example to download 7.0.x version:
# $ curl -Ls bit.ly/php-bash-win | bash -s -- 7.0
#
# Example to download latest version with Xdebug:
# $ curl -Ls bit.ly/php-bash-win | bash -s -- --xdebug
# Or
# $ curl -Ls bit.ly/php-bash-win | bash -s -- 7.1 --xdebug
#
# By default it will get x64 version. You may download x86
# $ curl -Ls bit.ly/php-bash-win | bash -s -- [VERSION] --x86
#
# Direct link usage:
# $ curl -Ls https://gist.github.com/andkirby/67e87e319c376b8676d559edb759e3fe/raw/php-git-bash-win.sh | bash
#
# Downloaded files hierarchy:
# ~/bin/
# /php - Last installed PHP version.
# /php70 - PHP 7.0.x
# /php56 - PHP 5.6.x
# ~/.php/
# /php-install - Script to execute this online file
# /xdebug-install - Xdebug installer.
# It can install Xdebug into your current php version.
# Or you may give it path to a PHP binary file.
################################################################################
gist_version=2018-08-09
set -o errexit
set -o pipefail
set -o nounset
#set -o xtrace
ERR_FATAL=1
ERR_LOGIC=2
ERR_PARAMS=3
ERR_FILE_SYSTEM=4
ERR_CONNECTION=6
# colors
t_red='\e[0;31m'
t_green='\e[0;32m'
t_yellow='\e[0;33m'
t_cyan='\e[0;36m'
t_reset='\e[0m'
echo_head() {
echo -e "${t_yellow}${@}${t_reset}"
}
echo_note() {
echo -e "${t_cyan}${@}${t_reset}"
}
echo_notice() {
echo -e "${t_yellow}notice:${t_reset} ${@}"
}
echo_warning() {
echo -e "${t_red}warning:${t_reset} ${@}"
}
show_help () {
cat << EOF
Download PHP binaries
${gist_version}
Run this command in GitBash Windows console
$ curl -Ls https://gist.github.com/andkirby/67e87e319c376b8676d559edb759e3fe/raw/php-git-bash-win.sh | bash
Example to dowload 7.0.x version.
$ curl -Ls https://gist.github.com/andkirby/67e87e319c376b8676d559edb759e3fe/raw/php-git-bash-win.sh | bash -s -- 7.0
Example to dowload latest version with Xdebug.
$ curl -Ls https://gist.github.com/andkirby/67e87e319c376b8676d559edb759e3fe/raw/php-git-bash-win.sh | bash -s -- --xdebug
Short version (bit.ly):
$ curl -Ls bit.ly/php-bash-win | bash
OPTIONS
-t,--ts
Use thread-safety packages.
See: http://php.net/manual/en/faq.obtaining.php#faq.obtaining.threadsafety
-8,--x86
By default it will get x64 version. You may download x86 by passing this option.
-i,--add-php-ini PATH_PHP_INI
This file will be merged with default php.ini-development
-f,--force
Force downloading. It will try to overwrite exist files.
-x,--xdebug
Install with Xdebug.
-v,--verbose
Verbose mode (shows curl download status).
-h,--help
Show this help.
EOF
}
check_error () {
local status=${1}
shift
if [ '0' != "${status}" ]; then
echo "error: $@" > /dev/stderr
exit ${status}
fi
}
init_options() {
if [ -n "${1:-}" ] && [ "${1:0:1}" != '-' ]; then
minor_version="${1:-}"
test -n "${1:-}" && shift
# check if not empty and it's not an option
if [[ ! "${minor_version}" =~ ^[0-9]+\.[0-9]+$ ]]; then
check_error ${ERR_PARAMS} "Invalid version format (${minor_version}). Please use this one: #.##" > /dev/stderr
exit
fi
fi
# Process options
# validate and redefine options
declare -A options
options=(
[t]=ts
[8]=x86
[i:]=add-php-ini:
[f]=force
[D]=no-download
[x]=xdebug
[v]=verbose
[h]=help
)
OPTS=`getopt -o $(echo ${!options[*]} | tr -d ' ') -l $(echo ${options[*]} | tr ' ' ',') -- "$@"`
eval set -- "${OPTS}"
nts='-nts'
force=0
xdebug_install=0
verbose_level=0
curl_options=''
type_x86='x64'
while true; do
case "${1}" in
-t|--ts)
nts=''
shift
;;
-8|--x86)
type_x86='x86'
shift
;;
-f|--force)
force=1
shift
;;
-x|--xdebug)
xdebug_install=1
shift
;;
-i|--add-php-ini)
php_ini_file_add="${1}"
shift 2
;;
-v|--verbose)
verbose_level=1
;;
-h|--help)
show_help
exit 0
;;
-\?)
show_help
exit ${ERR_PARAMS}
;;
--)
shift
break
;;
*)
check_error ${ERR_PARAMS} "${0}: unparseable option ${1}."
;;
esac
done
}
init_user_home_bin() {
if [ ! -d "$(cd; pwd)/bin" ]; then
mkdir -p "$(cd; pwd)/bin"
fi
}
######################
# Init
init_options ${@:-}
if [[ ${verbose_level} == 0 ]]; then
curl_options='-s'
elif [[ ${verbose_level} == 1 ]]; then
curl_options=''
fi
releases_url=https://windows.php.net/downloads/releases/
php_root_dir=$(cd; pwd)'/.php'
if [ ! -d ${php_root_dir} ]; then
printf 'Making PHP home dir ~/.php/...'
mkdir -p ${php_root_dir}
echo 'OK'
fi
######################
# Find target PHP version
reg_version=${minor_version:-'[0-9]+\.[0-9]+'}'\.[0-9]+'
if [ -n "${minor_version:-}" ]; then
echo_head 'Looking for the latest PHP v'${minor_version}'.x releases ('${releases_url}')...'
else
echo_head 'Looking for the latest PHP release ('${releases_url}')...'
fi
# download last node.exe binary
last_version=$(curl ${curl_options} ${releases_url} \
| grep -Eo '>php-'${reg_version}${nts:-}'[^<]+Win32[^<]+'${type_x86}'\.zip' \
| tr -d '>' \
| sort -V | uniq | tail -1)
[ -z "${last_version}" ] && check_error ${ERR_CONNECTION} 'Cannot fetch last PHP version.'
download_version=$(echo ${last_version} | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+')
download_path=${php_root_dir}/$(echo ${last_version} | sed -r 's|\.zip||')
init_user_home_bin
bin_path=$(cd; pwd)'/bin'
echo_head "Found PHP version: ${download_version}"
mkdir -p ${download_path}
######################
# Fetch PHP archive
if [ ${force} != 1 ] && [ -f ${download_path}/php.exe ]; then
echo_notice 'This version already downloaded.'
else
if [ ${force} != 1 ] && [ -f ${php_root_dir}/${last_version} ]; then
echo_notice 'Archive already downloaded by path '${php_root_dir}/${last_version}
else
echo 'Fetching '${last_version}'...'
curl ${curl_options} -L ${releases_url}${last_version} \
-o ${php_root_dir}/${last_version}
echo 'OK'
fi
echo "Unzipping: ${download_path}/${last_version}..."
unzip -o ${php_root_dir}/${last_version} -d ${download_path}
fi
# validate unpacked php.exe
if [ ! -f ${download_path}/php.exe ]; then
check_error ${ERR_FATAL} "No binary file by path: ${download_path}/php.exe"
fi
# Remove archive
rm -f ${download_path}/${last_version}
######################
# Install php.ini file
if [ ! -f ${download_path}/php.ini ]; then
if [ -f ${download_path}/php.ini-development ]; then
echo "Copying php.ini development version..."
cp ${download_path}/php.ini-development ${download_path}/php.ini
fi
if [ ! -f ${php_root_dir}/php.ini ]; then
echo "Downloading default php.ini content..."
curl ${curl_options} -L https://gist.github.com/andkirby/67e87e319c376b8676d559edb759e3fe/raw/php.ini.default?ts=$(date | tr -d ' ,.') \
--output ${php_root_dir}/php.ini
echo 'OK'
echo_note 'Content of ~/.php/php.ini file will added into all downloaded packages.'
fi
if [ -f ${php_root_dir}/php.ini ]; then
echo 'Adding content from ~/.php/php.ini...'
echo >> ${download_path}/php.ini
cat ${php_root_dir}/php.ini >> ${download_path}/php.ini
fi
if [ -n "${php_ini_file_add:-}" ]; then
if [ -f ${php_ini_file_add} ]; then
echo "Adding content from user file ${php_ini_file_add}..."
cat ${php_ini_file_add} >> ${download_path}/php.ini
else
echo_warning "File '${php_ini_file_add:-}' not found."
fi
fi
echo 'OK'
fi
######################
# Generate binary input files
short_version="$(echo ${download_version} \
| grep -Eo '^([0-9]+)\.([0-9]+)' | tr -d '.')"
download_path_print=$(echo ${download_path} | sed -r 's|'$(cd; pwd)'|~|g')
# bin files for BASH
cat << EOF > ${bin_path}/php
#!/usr/bin/env bash
${download_path}/php.exe \${@}
EOF
cat << EOF > ${bin_path}/php${short_version}
#!/usr/bin/env bash
${download_path}/php.exe \${@}
EOF
# bin files for CMD
download_path_win=$(echo ${download_path} | sed -r 's|^[/]([a-z])[/]|\1:/|' | tr '/' '\\')
cat << EOF > ${bin_path}/php.cmd
${download_path_win}\\php.exe %*
EOF
cat << EOF > ${bin_path}/php${short_version}.cmd
${download_path_win}\\php.exe %*
EOF
echo 'Binary files:'
echo ' EXE: '${download_path_print}'/php.exe'
echo ' '${bin_path/$(cd; pwd)/'~'}'/php'
echo ' '${bin_path/$(cd; pwd)/'~'}'/php'${short_version}
echo ' (Windows CMD)'
echo ' '${bin_path/$(cd; pwd)/'~'}'/php.cmd'
echo ' '${bin_path/$(cd; pwd)/'~'}'/php'${short_version}'.cmd'
# generate install input file
if [ ! -f $(cd; pwd)/.php/php-install ]; then
cat << 'EOF' > $(cd; pwd)/.php/php-install
#!/usr/bin/env bash
curl -Ls https://gist.github.com/andkirby/67e87e319c376b8676d559edb759e3fe/raw/php-git-bash-win.sh | bash -s -- ${@}
EOF
fi
echo ' ~/.php/php-install'
# generate xdebug-install input file
if [ ! -f $(cd; pwd)/.php/xdebug-install ]; then
cat << 'EOF' > $(cd; pwd)/.php/xdebug-install
#!/usr/bin/env bash
curl -Ls https://gist.github.com/andkirby/67e87e319c376b8676d559edb759e3fe/raw/xdebug-download.sh | bash -s -- ${@}
EOF
fi
echo ' ~/.php/xdebug-install [PHP_BIN_FILE]'
echo
echo 'SWITCH'
echo 'To switch main '${bin_path/$(cd; pwd)/'~'}'/php binary file to any version. You may use "~/.php/php-install".'
echo 'It will use downloaded version but it will try to fetch latest #.##.x version.'
echo
echo 'XDEBUG INSTALL'
echo 'Run ~/.php/xdebug-install to install xdebug for current PHP.'
echo 'Or run "~/.php/xdebug-install /path/to/php.exe" to install xdebug for selected version.'
if [ ${xdebug_install} == 1 ]; then
echo
echo -e ${t_yellow}'Installing Xdebug...'${t_reset}
bash ~/.php/xdebug-install
if ! type xd_swi 2> /dev/null > /dev/null; then
echo
echo -e ${t_yellow}'Installing Xdebug Switcher (https://github.com/rikby/xdebug-switcher)...'${t_reset}
curl -Ls https://raw.github.com/rikby/xdebug-switcher/master/download | bash
fi
xd_swi off
echo 'Please use "xd_swi" command to change Xdebug status. (see: xd_swi --help)'
fi
; Custom
; 2017-09-05
extension_dir = "ext"
extension=php_bz2.dll
extension=php_curl.dll
extension=php_fileinfo.dll
extension=php_gd2.dll
extension=php_gettext.dll
extension=php_mbstring.dll
extension=php_mysqli.dll
extension=php_openssl.dll
extension=php_pdo_mysql.dll
extension=php_soap.dll
extension=php_sockets.dll
extension=php_xmlrpc.dll
;extension=php_zip.dll
; You document root or projects
;doc_root = d:\home
date.timezone = "Europe/Kiev"
[Phar]
phar.require_hash = Off
phar.readonly = Off
#!/usr/bin/env bash
################################################################################
# Download PHP Xdebug library
#
# Link to this file:
# https://gist.github.com/andkirby/67e87e319c376b8676d559edb759e3fe/raw/xdebug-download.sh
#
# 2017-09-05
################################################################################
set -o pipefail
set -o errexit
set -o nounset
#set -o xtrace
# Set magic variables for current file & dir
__dir="$(cd; pwd)/.php"
readonly __dir
###############################################################################
# Helper variables #
###############################################################################
t_red='\e[0;31m'
t_green='\e[0;32m'
t_yellow='\e[0;33m'
t_reset='\e[0m'
phpinfo() {
local keys reg
declare -a keys
# "^" will be replaced with " " (space)
keys=(
xdebug
extension_dir
Server^API
OS
PHP^Version
Debug^Build
Thread^Safe
Configuration^File
SYSTEMROOT
WINDIR
)
reg='^('$(echo ${keys[*]} | tr ' ' '|' | tr '^' ' ')'|(Zend|PHP)[^=]+|_ =>)'
${php_bin} -i | grep -v '$_SERVER' | grep '=>' | tr -d "'" | grep -E "${reg}" ;
}
fetch_xdebug_version_php() {
local path=${1:-${__dir}/xdebugVersion.php} ts=$(date | tr -d ' ,.')
# always download this file to have latest version
# OLD URL: https://raw.githubusercontent.com/xdebug/xdebug.org/master/html/include/phpinfo-scanner.php
curl -Ls https://raw.githubusercontent.com/xdebug/xdebug.org/63456ca5e666b8e21215a7a4d38f593c9d27b5f1/html/include/phpinfo-scanner.php?ts=${ts} > ${path}
}
fetch_xdebug_info_php() {
local path=${1:-${__dir}/xdebug-info.php}
if [ ! -f ${path} ]; then
curl -Ls curl -Ls https://gist.github.com/andkirby/67e87e319c376b8676d559edb759e3fe/raw/xdebug-info.php > ${path}
fi
}
# fetch xdebug version library files
fetch_xdebug_version_php
fetch_xdebug_info_php
php_bin=${1:-php}
printf "Target version: ${t_green}"
echo -en "$(${php_bin} --version | grep -Eo 'PHP\s[0-9.]+')"
printf "${t_reset}\n"
xdebug_info=$(${php_bin} -f ${__dir}/xdebug-info.php | tr '\\' '/')
###############################################################################
# Download Xdebug
###############################################################################
# Define options
php_ini_file=$(sed -n 1p <<< "${xdebug_info}")
xdebug_file=$(sed -n 2p <<< "${xdebug_info}")
xdebug_ini_content='zend_extension = '${xdebug_file}
ext_xdebug_file=$(sed -n 3p <<< "${xdebug_info}" | cut -d= -f2 | xargs)
ext_dir=$(dirname ${ext_xdebug_file})
if [ ${ext_dir:0:1} != '/' ] || [ ${ext_dir:1:1} != ':' ] ; then
ext_dir=$(dirname ${php_ini_file})/${ext_dir}
fi
xdebug_file_url=$(sed -n 4p <<< "${xdebug_info}")
cd $(dirname ${php_ini_file})
# Downloading DLL
if [ -f ${ext_dir}/${xdebug_file} ]; then
echo 'Found downloaded file:'
echo ' '${ext_dir}/${xdebug_file}
else
curl -Ls ${xdebug_file_url} --output ${ext_dir}/${xdebug_file}
printf 'Downloaded: %s.\n' $(ls ${ext_dir}/${xdebug_file})
fi
match_string=$(cat ${php_ini_file} | grep -E 'zend_extension\s*=.*xdebug' || true)
if [ -n "${match_string}" ]; then
arg='-r'
if [ "$(uname)" == "Darwin" ] || [ "$(expr substr $(uname -s) 1 5)" == "MINGW" ] ; then
arg='-E'
fi
sed -i.bak ${arg} "s|${match_string}|${xdebug_ini_content}|g" ${php_ini_file}
else
echo -e "$(cat <<-EOF
[xdebug]
${xdebug_ini_content}
xdebug.remote_autostart = On
xdebug.remote_enable=1
xdebug.remote_mode=req
xdebug.remote_port=9000
xdebug.remote_host=127.0.0.1
xdebug.remote_connect_back=0
EOF
)" >> ${php_ini_file}
fi
echo 'Done.'
<?php
/**
* Get current phpinfo without HTML tags
*
* @return string
*/
function getPhpInfo() {
ob_start();
phpinfo();
$phpInfo = strip_tags(ob_get_contents());
ob_end_clean();
return $phpInfo;
}
require_once __DIR__ . '/xdebugVersion.php';
$xd = new xdebugVersion();
ob_start();
$xd->analyse(isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : getPhpInfo());
$output = ob_get_contents();
ob_end_clean();
if ($xd->determineSupported()) {
echo <<<RESULT
{$xd->configFile}
{$xd->determineFile()}
{$xd->determineIniLine()}
http://xdebug.org/files/{$xd->determineFile()}
RESULT;
}
@andkirby
Copy link
Author

andkirby commented Aug 1, 2017

Download any minor version of PHP on Windows in bash console.

  1. Check existing versions: https://windows.php.net/downloads/releases/
  2. Run in console:
curl -Ls https://gist.github.com/andkirby/67e87e319c376b8676d559edb759e3fe/raw/php-git-bash-win.sh | bash -s -- 8.1

Short link:

curl -Ls bit.ly/php-bash-win | bash -s -- 8.1

Omitted version number will download latest version:

curl -Ls bit.ly/php-bash-win | bash

2.1. Debug it if needed by adding -x for bash command:

curl -Ls bit.ly/php-bash-win | bash -xs -- 8.1

Explanation

It will add content of php.ini.default automatically. It will use php.ini-development as a base content for php.ini file.

It will download files into ~/.php/-php-some-dir-version-/ (like ~/.php/php-7.1.21-nts-Win32-VC14-x64)
and bin files will be placed into ~/bin/
It will create:

~/bin/php
~/bin/php## (like ~/php71 for 7.1.x version)

and for windows the same with .cmd extension:

~/bin/php.cmd
~/bin/php##.cmd (like ~/php71.cmd for 7.1.x version)

@Jamshid-git
Copy link

Thank you a lot

@andkirby
Copy link
Author

andkirby commented Aug 5, 2020

Thank you a lot

@Jamshid-git, glad you found it helpful. ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment