WFO logo

Snapshots of the taxonomy

WFO Logo

As classified in WFO snapshot

June 2025

latest classification for this taxon

species

Phoenix dactylifera L.

This species name was first published in Sp. Pl. : 1188 (1753)  

At the time of this classification snapshot, this species name was accepted by WFO (placed as the accepted name of a taxon). Its description and other taxonomic data can be found on World Flora Online, id: wfo-0000269752.

Synonyms of Phoenix dactylifera L.

Name Author Protologue Nomenclator WFO link
Palma dactylifera (L.) Mill. Gard. Dict., ed. 8. : n.° 1 (1768) wfo-0000263283
Palma major Garsault Fig. Pl. Méd. : t. 47 (1764) wfo-0000263287
Phoenix atlantica var. maroccana A.Chev. Compt. Rend. Hebd. Séances Acad. Sci. 2: 172 (1952) wfo-0000269744
Phoenix dactylifera var. adunca D.H.Christ ex Becc. Malesia 3: 357 (1890) wfo-0000269754
Phoenix dactylifera var. costata Becc. Malesia 3: 357 (1890) wfo-0000269755
Phoenix dactylifera var. cylindrocarpa Mart. Hist. Nat. Palm. 3: 258 (1838) wfo-0000269756
Phoenix dactylifera var. gonocarpa Mart. Hist. Nat. Palm. 3: 258 (1838) wfo-0000269757
Phoenix dactylifera var. oocarpa Mart. Hist. Nat. Palm. 3: 258 (1838) wfo-0000269759
Phoenix dactylifera var. oxysperma Mart. Hist. Nat. Palm. 3: 258 (1838) wfo-0000269760
Phoenix dactylifera var. sphaerocarpa Mart. Hist. Nat. Palm. 3: 258 (1838) wfo-0000269761
Phoenix dactylifera var. sphaerosperma Mart. Hist. Nat. Palm. 3: 258 (1838) wfo-0000269762
Phoenix dactylifera var. sylvestris Mart. Hist. Nat. Palm. 3: 258 (1838) wfo-0000269763
Phoenix excelsior Cav. Icon. 2: 13 (1793) wfo-0000269769
Zamia pungens L.f. ex Salisb. Prodr. Stirp. Chap. Allerton 401. 1796 [Nov-Dec 1796] wfo-0000429941
Zamia pallida Salisb. Prodr. Stirp. Chap. Allerton : 401 (1796) wfo-0000429957
Macrozamia tridentata var. pungens (Willd.) J.Schust. Pflanzenr. , IV, 1: 93 (1932) wfo-0000453770
Phoenix chevalieri D.Rivera, S.Ríos & Obón Varied. Trad. Frut. Cuenca Río Segura Cat. Etnobot. 1: 79 (1997) wfo-0000490854
Phoenix iberica D.Rivera, S.Ríos & Obón Varied. Trad. Frut. Cuenca Río Segura Cat. Etnobot. 1: 73 (1997) wfo-0000490855
Encephalartos pungens (L.f. ex Aiton) Lehm. Allg. Gartenzeitung 2(11): 86 (1834) wfo-0000667446
Zamia pungens L.f. Hort. Kew. (W. Aiton) 3: 478 1789 wfo-1200029895
`, data() { const wfoCategories = [ "synonym", "accepted", "unplaced", "null", "species", "subspecies", "variety", "subvariety", "subform", "form", "subseries", "series", "subsection", "section", "subgenus", "genus", "subtribe", "tribe", "supertribe", "subfamily", "family", "suborder", "order", "superorder", "subclass", "class", "phylum", "subkingdom", "kingdom", "code", "unranked", "depricated", ]; // Recommended approach: Set domain for consistent colors, with fallback for new ranks const rankColorScale = d3.scaleOrdinal() .domain(wfoCategories) .range(d3.schemePaired) .unknown(() => { // For unknown ranks, assign the next available color from schemePaired const usedColors = wfoCategories.length; const schemeLength = d3.schemePaired.length; const nextColorIndex = usedColors % schemeLength; return d3.schemePaired[nextColorIndex]; }); return { pieLayout: d3.pie().value(d => d.value).sortValues(null), pickedStat: null, pickedGraph: 'species', colours: rankColorScale, _isInitialLoad: true // Flag to track initial load } }, computed: { stats() { return this.groupedStats[this.pickedGraph] || [] }, outerRadius() { return Math.min(this.svgWidth, this.svgHeight) / 2 - 20 }, innerRadius() { return this.outerRadius * .45 }, arc() { return d3.arc().outerRadius(this.outerRadius).innerRadius(this.innerRadius).cornerRadius(4) }, pieData() { return this.stats.length ? this.pieLayout(this.stats) : [] }, currentTotalValues() { return this.stats.reduce((acc, s) => acc + s.value, 0) }, centreGroup() { return `translate(${this.svgWidth/2}, ${this.svgHeight/2})` }, isRankTypeStat() { return this.pickedGraph === 'rank' || this.pickedGraph === 'accepted'; } }, watch: { pickedStat() { this.updateActiveClass() }, pickedGraph() { this.updatePie() this._isInitialLoad = false; } }, mounted() { this.setupSvg() this.updatePie(true); }, methods: { setupSvg() { const svg = d3.select(this.$refs.svgContainer); svg.selectAll('*').remove(); // Ensure a clean slate // Create the main group 'g' only once this._svgGroup = svg .attr('width', this.svgWidth) .attr('height', this.svgHeight) .attr('class', "container") .append('g') .attr('class', 'pies') .attr('transform', this.centreGroup) }, updateActiveClass() { if (this._pathElements) { this._pathElements.attr('class', d => d.data.id === this.pickedStat ? 'active' : ''); } }, updatePie(isInitial = false) { const self = this; const paths = this._svgGroup.selectAll('path') .data(this.pieData, d => d.data.label); const durationValue = isInitial ? 700 : 800; // EXIT selection paths.exit() .transition() .duration(durationValue) .attrTween('d', function(d) { // 'this._current' holds the *last* known angular state of this element before it exited. const start = this._current || d; // Use its last known position as the start of the exit animation const end = { startAngle: start.startAngle, // Collapse to its own START angle endAngle: start.startAngle // Making start and end angles equal creates a zero-width arc at the start edge }; const interpolate = d3.interpolate(start, end); return t => self.arc(interpolate(t)); }) .remove(); // ENTER selection const enter = paths.enter() .append('path') .each(function(d) { // Initialize _current for new elements. // If initial load, they start from (0,0) and tween. // If not initial, they appear at their start angle and tween in from there. this._current = isInitial ? { startAngle: 0, endAngle: 0 } : { startAngle: d.startAngle, endAngle: d.startAngle }; }) .on('mouseover', (event, d) => { self.pickedStat = d.data.id; }) .on('mouseout', () => { self.pickedStat = null; }); // MERGE (Enter + Update) selection this._pathElements = enter.merge(paths); // Animate all paths (new and existing) this._pathElements .attr('fill', (d, i) => { return self.colours(d.data.label); }) .transition() .duration(durationValue) .attrTween('d', function(d) { // Use the _current state (from previous transition or initial setup) // as the starting point for interpolation. const previous = this._current; const interpolate = d3.interpolate(previous, d); // Crucially, update _current to the *target* state for the next transition. this._current = d; return t => self.arc(interpolate(t)); }) }, percentage(value) { const total = this.currentTotalValues const percentage = (value / total) * 100 return percentage < 1 ? Math.round(percentage * 10) / 10 : Math.round(percentage) }, totalForStatsWithKey(key) { const stats = this.groupedStats[key] || [] return stats.length ? stats.reduce((acc, s) => acc + s.value, 0) : 0 }, formatNumber(amount) { if (isNaN(amount)) return '' const sign = amount < 0 ? '-' : '' const abs = Math.abs(amount) return sign + abs.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") }, tweenPie(b) { const i = d3.interpolate({ startAngle: 0, endAngle: 0 }, b) return t => this.arc(i(t)) }, capitalize(s) { if (!s) return '' return s.charAt(0).toUpperCase() + s.slice(1) }, } }) var vm = new Vue({ el: "#el", delimiters: ["${", "}"], data: function () { const urlParams = new URLSearchParams(window.location.search); const subTaxaInitalPage = parseInt(urlParams.get('subTaxaPage')); const unplacedInitalPage = parseInt(urlParams.get('unplacedPage')); const perPage = 10; return { groupedStats: groupedStats, hideSyns: false, children: children, unplaced: unplaced, totalSyns: totalSyns, subTaxaPageIsLoading: false, unplacedPageIsLoading: false, subTaxaPaging: this.createPaging(partsCount, perPage, (subTaxaInitalPage && subTaxaInitalPage > 0) ? subTaxaInitalPage : 1, partsCount), // totalItems, perPage, currentPage unplacedPaging: this.createPaging(unplacedCount, perPage, (unplacedInitalPage && unplacedInitalPage > 0) ? unplacedInitalPage : 1, unplacedCount), // totalItems, perPage, currentPage, allRanks: typeof allRanks !== "undefined" ? allRanks : [], // assign global safely }; }, created() { }, mounted() { this.init() }, methods: { init: function () { //on page load check the url for any info const urlParams = new URLSearchParams(window.location.search); this.hideSyns = (urlParams.get('hide_syns') === 'true'); }, getTaxonUri: function (taxon) { var url = "/taxon/"; url += taxon.id; if(taxon.id.length < 22) { url += '-' + latestClassification.id } return url }, getNomenclature: function (taxon) { var uir = ""; var kind; var ipniIdentifier = taxon.identifiersOther.filter(nomenclature => nomenclature.kind === 'ipni'); var tropicosIdentifier = taxon.identifiersOther.filter(nomenclature => nomenclature.kind === 'tropicos'); if (ipniIdentifier.length) { uir = `https://www.ipni.org/n/${ipniIdentifier[0].value}`.trim() kind = 'ipni'; } else if (tropicosIdentifier.length) { uir = `https://www.tropicos.org/name/${tropicosIdentifier[0].value}`.trim() kind = 'tropicos'; } return { kind: kind, uir: uir} }, createPaging: function (totalItems, perPage, currentPage) { return { totalItems: totalItems, perPage: perPage, currentPage: currentPage || 1, } }, getOffset: function (paging) { return (paging.perPage * paging.currentPage) - paging.perPage; }, getRangeFirst: function (paging) { return this.getOffset(paging) + 1; }, getRangeLast: function (paging) { return Math.min(this.getOffset(paging) + paging.perPage, paging.totalItems); }, isSecondLastPage: function (paging) { return paging.currentPage === this.totalPages(paging) - 1; }, isLastPage: function (paging) { return paging.currentPage >= this.totalPages(paging); }, remainingItemsCount: function (paging) { return paging.totalItems % paging.perPage || paging.perPage; }, totalPages: function (paging) { if (!paging.perPage) return 1; // avoid div by zero return Math.ceil(paging.totalItems / paging.perPage); }, prevPage: function (paging) { if (paging.currentPage > 1) paging.currentPage--; }, nextPage: function (paging) { if (!this.isLastPage(paging)) paging.currentPage++; }, async performSubTaxaQuery(offset, limit) { const query = `query { taxonConceptById(taxonId: "${taxonId}") { id children: hasPart(offset: ${offset}, limit: ${limit}) { id title hasName { ...taxonFields } hasSynonym { ...taxonFields } } } } fragment taxonFields on TaxonName { id title nameString fullNameStringHtml fullNameStringNoAuthorsHtml fullNameStringNoAuthorsPlain fullNameStringPlain speciesString genusString authorsString authorsStringHtml citationMicro classificationId comment nomenclaturalStatus rank role stableUri identifiersOther { kind value } }`; const response = await this.fetchItems(JSON.stringify({ query })); if (!response || !response.data || !response.data.taxonConceptById) { console.warn("Invalid response from GraphQL:", response); return []; } return response.data.taxonConceptById.children; }, async performUplacedItemsQuery(offset, limit) { console.log("perfoming Query!"); const query = `query { taxonConceptById(taxonId: "${taxonId}") { id hasUnplacedName(offset: ${offset} , limit: ${limit}) { ...taxonFields } } } fragment taxonFields on TaxonName { id title nameString fullNameStringHtml fullNameStringNoAuthorsHtml fullNameStringNoAuthorsPlain fullNameStringPlain speciesString genusString authorsString authorsStringHtml citationMicro classificationId comment nomenclaturalStatus rank role stableUri identifiersOther { kind value } }`; const response = await this.fetchItems(JSON.stringify({ query })); console.log(response); if (!response || !response.data || !response.data.taxonConceptById) { console.warn("Invalid response from GraphQL:", response); return []; } return response.data.taxonConceptById.hasUnplacedName; }, fetchItems: async function (query) { let opts = { method: "POST", headers: {}, body: query }; const response = await fetch(requestURL, opts); const responseJson = await response.json(); return responseJson }, updateUrlParam(paramName, value) { const urlParams = new URLSearchParams(window.location.search); urlParams.set(paramName, value); history.pushState(null, null, "?" + urlParams.toString()); }, capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); }, }, watch: { hideSyns: function () { //if checkbox changes, also update the url const urlParams = new URLSearchParams(window.location.search); urlParams.set('hide_syns', this.hideSyns); history.pushState(null, null, "?"+urlParams.toString()); }, 'subTaxaPaging.currentPage': async function (newPage) { // Update URL for subtaxa page this.updateUrlParam('subTaxaPage', newPage); // Load new subtaxa data this.subTaxaPageIsLoading = true; this.children = await this.performSubTaxaQuery( this.getOffset(this.subTaxaPaging), this.subTaxaPaging.perPage ); this.subTaxaPageIsLoading = false; }, 'unplacedPaging.currentPage': async function (newPage) { //if page changes, also update the url // Update URL for unplaced taxa page this.updateUrlParam('unplacedPage', newPage); // Load new unplaced data this.unplacedPageIsLoading = true; this.unplaced = await this.performUplacedItemsQuery( this.getOffset(this.unplacedPaging), this.unplacedPaging.perPage ); this.unplacedPageIsLoading = false; }, }, computed: { currentNoOfSyns() { var hits = this.children.reduce((accumulator, element) => accumulator + element.hasSynonym.length, 0); return hits }, subTaxaHeading() { if (!this.children || this.children.length === 0) { return { shortName: "subtaxa", fullName: "Subtaxa" }; } // Count how many children per rank const rankCounts = {}; this.children.forEach(child => { const rank = child.hasName?.rank; if (rank) rankCounts[rank] = (rankCounts[rank] || 0) + 1; }); const uniqueRanks = Object.keys(rankCounts); // Case 1: only one rank used if (uniqueRanks.length === 1) { const rankId = uniqueRanks[0]; const count = rankCounts[rankId]; const rank = this.allRanks?.find(r => r.id === rankId); const singular = rank?.id || rankId; const plural = rank?.plural || (rankId + "s"); return { shortName: count === 1 ? singular.toLowerCase() : plural.toLowerCase(), fullName: count === 1 ? this.capitalize(singular) : this.capitalize(plural) }; } // Case 2: mixed ranks — lowercase in shortName and fullName const labels = uniqueRanks.map(rankId => { const count = rankCounts[rankId]; const rank = this.allRanks?.find(r => r.id === rankId); const label = count === 1 ? (rank?.id || rankId) : (rank?.plural || (rankId + "s")); return label.toLowerCase(); }); return { shortName: "subtaxa", fullName: `Subtaxa (${labels.join(", ")})` }; }, hideNomenclator() { return !this.children.some(child => { // Check the main taxonConcept const hasMain = Array.isArray(child.hasName?.identifiersOther) && child.hasName.identifiersOther.some(id => id && ["ipni", "tropicos"].includes(id.kind) ); // Check synonyms if visible const hasSyn = !this.hideSyns && Array.isArray(child.hasSynonym) && child.hasSynonym.some(syn => Array.isArray(syn.identifiersOther) && syn.identifiersOther.some(id => id && ["ipni", "tropicos"].includes(id.kind) ) ); return hasMain || hasSyn; }); } } }) ;