Install via yarn add locutus and import:
import { is_array } from 'locutus/php/var/is_array'.
Or with CommonJS: const { is_array } = require('locutus/php/var/is_array')
Use a bundler that supports tree-shaking so you only ship the functions you actually use.
Vite,
webpack,
Rollup, and
Parcel
all handle this. For server-side use this is less of a concern.
Examples
These examples are extracted from test cases that automatically verify our functions against their native counterparts.
In Locutus, javascript objects are like php associative arrays,
thus JavaScript objects will also
return true in this function (except for objects which inherit properties,
being thus used as objects),
unless you do ini_set(‘locutus.objectsAsArrays’, 0),
in which case only genuine JavaScript arrays
will return true
Dependencies
This function uses the following Locutus functions:
const hasNumericLength = (value: IsArrayValue): value is ArrayLikeAssoc => value !== null && typeof value === 'object' && typeofgetPhpObjectEntry(value, 'length') === 'number'
exportfunctionis_array(mixedVar: IsArrayValue): boolean { // discuss at: https://locutus.io/php/is_array/ // original by: Kevin van Zonneveld (https://kvz.io) // improved by: Legaev Andrey // improved by: Onno Marsman (https://twitter.com/onnomarsman) // improved by: Brett Zamir (https://brett-zamir.me) // improved by: Nathan Sepulveda // improved by: Brett Zamir (https://brett-zamir.me) // bugfixed by: Cord // bugfixed by: Manish // bugfixed by: Brett Zamir (https://brett-zamir.me) // note 1: In Locutus, javascript objects are like php associative arrays, // note 1: thus JavaScript objects will also // note 1: return true in this function (except for objects which inherit properties, // note 1: being thus used as objects), // note 1: unless you do ini_set('locutus.objectsAsArrays', 0), // note 1: in which case only genuine JavaScript arrays // note 1: will return true // example 1: is_array(['Kevin', 'van', 'Zonneveld']) // returns 1: true // example 2: is_array('Kevin van Zonneveld') // returns 2: false // example 3: is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}) // returns 3: true // example 4: ini_set('locutus.objectsAsArrays', 0) // example 4: is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}) // returns 4: false // example 5: is_array(function tmp_a (){ this.name = 'Kevin' }) // returns 5: false
const _getFuncName = function (fn: IsArrayValue): string { const name = /\W*function\s+([\w$]+)\s*\(/.exec(String(fn)) if (!name) { return'(Anonymous)' } return name[1] ?? '(Anonymous)' } const _isArray = function (mixedVar: IsArrayValue): boolean { // return Array.isArray(mixedVar); // The above works, but let's do the even more stringent approach: // (since Object.prototype.toString could be overridden) // Null, Not an object, no length property so couldn't be an Array (or String) if (!hasNumericLength(mixedVar)) { returnfalse } const candidate = mixedVar const len = candidate.length candidate[candidate.length] = 'bogus' // The only way I can think of to get around this (or where there would be trouble) // would be to have an object defined // with a custom "length" getter which changed behavior on each call // (or a setter to mess up the following below) or a custom // setter for numeric properties, but even that would need to listen for // specific indexes; but there should be no false negatives // and such a false positive would need to rely on later JavaScript // innovations like __defineSetter__ if (len !== candidate.length) { // We know it's an array since length auto-changed with the addition of a // numeric property at its length end, so safely get rid of our bogus element candidate.length -= 1 returntrue } // Get rid of the property we added onto a non-array object; only possible // side-effect is if the user adds back the property later, it will iterate // this property in the older order placement in IE (an order which should not // be depended on anyways) delete candidate[candidate.length] returnfalse }
if (!mixedVar || typeof mixedVar !== 'object') { returnfalse }
consthasNumericLength = (value) => value !== null && typeof value === 'object' && typeofgetPhpObjectEntry(value, 'length') === 'number'
exportfunctionis_array(mixedVar) { // discuss at: https://locutus.io/php/is_array/ // original by: Kevin van Zonneveld (https://kvz.io) // improved by: Legaev Andrey // improved by: Onno Marsman (https://twitter.com/onnomarsman) // improved by: Brett Zamir (https://brett-zamir.me) // improved by: Nathan Sepulveda // improved by: Brett Zamir (https://brett-zamir.me) // bugfixed by: Cord // bugfixed by: Manish // bugfixed by: Brett Zamir (https://brett-zamir.me) // note 1: In Locutus, javascript objects are like php associative arrays, // note 1: thus JavaScript objects will also // note 1: return true in this function (except for objects which inherit properties, // note 1: being thus used as objects), // note 1: unless you do ini_set('locutus.objectsAsArrays', 0), // note 1: in which case only genuine JavaScript arrays // note 1: will return true // example 1: is_array(['Kevin', 'van', 'Zonneveld']) // returns 1: true // example 2: is_array('Kevin van Zonneveld') // returns 2: false // example 3: is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}) // returns 3: true // example 4: ini_set('locutus.objectsAsArrays', 0) // example 4: is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}) // returns 4: false // example 5: is_array(function tmp_a (){ this.name = 'Kevin' }) // returns 5: false
const _getFuncName = function (fn) { const name = /\W*function\s+([\w$]+)\s*\(/.exec(String(fn)) if (!name) { return'(Anonymous)' } return name[1] ?? '(Anonymous)' } const _isArray = function (mixedVar) { // return Array.isArray(mixedVar); // The above works, but let's do the even more stringent approach: // (since Object.prototype.toString could be overridden) // Null, Not an object, no length property so couldn't be an Array (or String) if (!hasNumericLength(mixedVar)) { returnfalse } const candidate = mixedVar const len = candidate.length candidate[candidate.length] = 'bogus' // The only way I can think of to get around this (or where there would be trouble) // would be to have an object defined // with a custom "length" getter which changed behavior on each call // (or a setter to mess up the following below) or a custom // setter for numeric properties, but even that would need to listen for // specific indexes; but there should be no false negatives // and such a false positive would need to rely on later JavaScript // innovations like __defineSetter__ if (len !== candidate.length) { // We know it's an array since length auto-changed with the addition of a // numeric property at its length end, so safely get rid of our bogus element candidate.length -= 1 returntrue } // Get rid of the property we added onto a non-array object; only possible // side-effect is if the user adds back the property later, it will iterate // this property in the older order placement in IE (an order which should not // be depended on anyways) delete candidate[candidate.length] returnfalse }
if (!mixedVar || typeof mixedVar !== 'object') { returnfalse }
// php/info/ini_get (Locutus dependency module) functionini_get(varname: string): string { // discuss at: https://locutus.io/php/ini_get/ // original by: Brett Zamir (https://brett-zamir.me) // note 1: The ini values must be set by ini_set or manually within an ini file // example 1: ini_set('date.timezone', 'Asia/Hong_Kong') // example 1: ini_get('date.timezone') // returns 1: 'Asia/Hong_Kong'
if (entry && entry.local_value !== undefined) { if (entry.local_value === null) { return'' } returnString(entry.local_value) }
return'' }
// php/var/is_array (target function module) typeIsArrayValue = PhpRuntimeValue
typeArrayLikeAssoc = PhpAssoc<IsArrayValue> & { length: number }
const hasNumericLength = (value: IsArrayValue): value is ArrayLikeAssoc => value !== null && typeof value === 'object' && typeofgetPhpObjectEntry(value, 'length') === 'number'
functionis_array(mixedVar: IsArrayValue): boolean { // discuss at: https://locutus.io/php/is_array/ // original by: Kevin van Zonneveld (https://kvz.io) // improved by: Legaev Andrey // improved by: Onno Marsman (https://twitter.com/onnomarsman) // improved by: Brett Zamir (https://brett-zamir.me) // improved by: Nathan Sepulveda // improved by: Brett Zamir (https://brett-zamir.me) // bugfixed by: Cord // bugfixed by: Manish // bugfixed by: Brett Zamir (https://brett-zamir.me) // note 1: In Locutus, javascript objects are like php associative arrays, // note 1: thus JavaScript objects will also // note 1: return true in this function (except for objects which inherit properties, // note 1: being thus used as objects), // note 1: unless you do ini_set('locutus.objectsAsArrays', 0), // note 1: in which case only genuine JavaScript arrays // note 1: will return true // example 1: is_array(['Kevin', 'van', 'Zonneveld']) // returns 1: true // example 2: is_array('Kevin van Zonneveld') // returns 2: false // example 3: is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}) // returns 3: true // example 4: ini_set('locutus.objectsAsArrays', 0) // example 4: is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}) // returns 4: false // example 5: is_array(function tmp_a (){ this.name = 'Kevin' }) // returns 5: false
const _getFuncName = function (fn: IsArrayValue): string { const name = /\W*function\s+([\w$]+)\s*\(/.exec(String(fn)) if (!name) { return'(Anonymous)' } return name[1] ?? '(Anonymous)' } const _isArray = function (mixedVar: IsArrayValue): boolean { // return Array.isArray(mixedVar); // The above works, but let's do the even more stringent approach: // (since Object.prototype.toString could be overridden) // Null, Not an object, no length property so couldn't be an Array (or String) if (!hasNumericLength(mixedVar)) { returnfalse } const candidate = mixedVar const len = candidate.length candidate[candidate.length] = 'bogus' // The only way I can think of to get around this (or where there would be trouble) // would be to have an object defined // with a custom "length" getter which changed behavior on each call // (or a setter to mess up the following below) or a custom // setter for numeric properties, but even that would need to listen for // specific indexes; but there should be no false negatives // and such a false positive would need to rely on later JavaScript // innovations like __defineSetter__ if (len !== candidate.length) { // We know it's an array since length auto-changed with the addition of a // numeric property at its length end, so safely get rid of our bogus element candidate.length -= 1 returntrue } // Get rid of the property we added onto a non-array object; only possible // side-effect is if the user adds back the property later, it will iterate // this property in the older order placement in IE (an order which should not // be depended on anyways) delete candidate[candidate.length] returnfalse }
if (!mixedVar || typeof mixedVar !== 'object') { returnfalse }
return { ini, locales, localeCategories, pointers, locale_default: localeDefault, } }
functiongetPhpObjectEntry(value, key) { if ((typeof value !== 'object' && typeof value !== 'function') || value === null) { returnundefined }
let current = value while (current) { const descriptor = Object.getOwnPropertyDescriptor(current, key) if (descriptor) { if (typeof descriptor.get === 'function') { const getterValue = descriptor.get.call(value) returntypeof getterValue === 'undefined' ? undefined : getterValue } const directValue = descriptor.value returntypeof directValue === 'undefined' ? undefined : directValue } current = Object.getPrototypeOf(current) }
returnundefined }
// php/info/ini_get (Locutus dependency module) functionini_get(varname) { // discuss at: https://locutus.io/php/ini_get/ // original by: Brett Zamir (https://brett-zamir.me) // note 1: The ini values must be set by ini_set or manually within an ini file // example 1: ini_set('date.timezone', 'Asia/Hong_Kong') // example 1: ini_get('date.timezone') // returns 1: 'Asia/Hong_Kong'
if (entry && entry.local_value !== undefined) { if (entry.local_value === null) { return'' } returnString(entry.local_value) }
return'' }
// php/var/is_array (target function module) consthasNumericLength = (value) => value !== null && typeof value === 'object' && typeofgetPhpObjectEntry(value, 'length') === 'number'
functionis_array(mixedVar) { // discuss at: https://locutus.io/php/is_array/ // original by: Kevin van Zonneveld (https://kvz.io) // improved by: Legaev Andrey // improved by: Onno Marsman (https://twitter.com/onnomarsman) // improved by: Brett Zamir (https://brett-zamir.me) // improved by: Nathan Sepulveda // improved by: Brett Zamir (https://brett-zamir.me) // bugfixed by: Cord // bugfixed by: Manish // bugfixed by: Brett Zamir (https://brett-zamir.me) // note 1: In Locutus, javascript objects are like php associative arrays, // note 1: thus JavaScript objects will also // note 1: return true in this function (except for objects which inherit properties, // note 1: being thus used as objects), // note 1: unless you do ini_set('locutus.objectsAsArrays', 0), // note 1: in which case only genuine JavaScript arrays // note 1: will return true // example 1: is_array(['Kevin', 'van', 'Zonneveld']) // returns 1: true // example 2: is_array('Kevin van Zonneveld') // returns 2: false // example 3: is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}) // returns 3: true // example 4: ini_set('locutus.objectsAsArrays', 0) // example 4: is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}) // returns 4: false // example 5: is_array(function tmp_a (){ this.name = 'Kevin' }) // returns 5: false
const _getFuncName = function (fn) { const name = /\W*function\s+([\w$]+)\s*\(/.exec(String(fn)) if (!name) { return'(Anonymous)' } return name[1] ?? '(Anonymous)' } const _isArray = function (mixedVar) { // return Array.isArray(mixedVar); // The above works, but let's do the even more stringent approach: // (since Object.prototype.toString could be overridden) // Null, Not an object, no length property so couldn't be an Array (or String) if (!hasNumericLength(mixedVar)) { returnfalse } const candidate = mixedVar const len = candidate.length candidate[candidate.length] = 'bogus' // The only way I can think of to get around this (or where there would be trouble) // would be to have an object defined // with a custom "length" getter which changed behavior on each call // (or a setter to mess up the following below) or a custom // setter for numeric properties, but even that would need to listen for // specific indexes; but there should be no false negatives // and such a false positive would need to rely on later JavaScript // innovations like __defineSetter__ if (len !== candidate.length) { // We know it's an array since length auto-changed with the addition of a // numeric property at its length end, so safely get rid of our bogus element candidate.length -= 1 returntrue } // Get rid of the property we added onto a non-array object; only possible // side-effect is if the user adds back the property later, it will iterate // this property in the older order placement in IE (an order which should not // be depended on anyways) delete candidate[candidate.length] returnfalse }
if (!mixedVar || typeof mixedVar !== 'object') { returnfalse }
if (asString === '[object Object]' && asFunc === 'Object') { // Most likely a literal and intended as assoc. array returntrue } }
returnfalse }
Improve this function
Locutus is a community effort following
The McDonald's Theory:
we ship first iterations, hoping others will improve them.
If you see something that could be better, we'd love your contribution.