Skip to content

Latest commit

 

History

History
477 lines (354 loc) · 13.6 KB

File metadata and controls

477 lines (354 loc) · 13.6 KB

celestial — PHP binding

Extension: celestial (ext-php-rs)
PHP version: 8.1+
All functions are in the global namespace with the celestial_ prefix.

Quick start

cd bindings/php && cargo build --release
# Add to php.ini:  extension=/path/to/libcelestial.so

This guide covers usage patterns, phpstan integration, and tradition-specific examples. The authoritative constant values and per-function signatures are generated from source in generated/binding_api.md — consult it (not hand-copied numbers) when you need an exact value or signature.


Note on Rust builder structs: CalcOptions, RiseTransOptions, SearchOptions, and AspectOrbs are Rust-only builder structs. The PHP extension exposes the underlying functions directly with the celestial_ prefix: celestial_calc_ut, celestial_calc_many, celestial_rise_trans, celestial_match_aspect3, celestial_match_aspect4, etc.

Installation

From source

# Install PHP development headers
sudo apt-get install php-dev   # Ubuntu / Debian
sudo dnf install php-devel     # Fedora / RHEL
brew install php               # macOS

# Build the extension
cd bindings/php
cargo build --release

# Add to php.ini
extension=/path/to/target/release/libcelestial.so   # Linux
extension=/path/to/target/release/libcelestial.dylib  # macOS

phpstan integration

# phpstan.neon
parameters:
    bootstrapFiles:
        - vendor/path/to/bindings/php/phpstan-stubs.php

Stubs file: bindings/php/phpstan-stubs.php


Constants

Body indices

define('SE_SUN',       0);
define('SE_MOON',      1);
define('SE_MERCURY',   2);
define('SE_VENUS',     3);
define('SE_MARS',      4);
define('SE_JUPITER',   5);
define('SE_SATURN',    6);
define('SE_URANUS',    7);
define('SE_NEPTUNE',   8);
define('SE_PLUTO',     9);
define('SE_MEAN_NODE', 10);
define('SE_TRUE_NODE', 11);
define('SE_CHIRON',    15);

Calculation flags

define('FLG_BUILTIN',    2);
define('FLG_SPEED',      256);
define('FLG_SIDEREAL',   65536);
define('FLG_EQUATORIAL', 2048);
define('FLG_HELCTR',     8);

Sidereal modes

define('SIDM_FAGAN_BRADLEY', 0);
define('SIDM_LAHIRI',        1);
define('SIDM_RAMAN',         3);
define('SIDM_KRISHNAMURTI',  5);

Core functions

Time

// Calendar → Julian Day
$jd = celestial_julday(2025, 3, 20, 9.0, GREG_CAL);

// Julian Day → calendar date
$date = celestial_revjul($jd, GREG_CAL);
// $date['year'], $date['month'], $date['day'], $date['hour']

// Current Julian Day
$now = celestial_jdnow();

Planetary positions

// Single body
// Returns [lon, lat, dist, speed_lon, speed_lat, speed_dist, ret_flags]
$sun = celestial_calc_ut($jd, SE_SUN, FLG_BUILTIN | FLG_SPEED);
printf("Sun lon=%.4f°  dist=%.6f AU\n", $sun[0], $sun[2]);

// Multiple bodies in parallel
// Returns array of [lon, lat, dist, speed_lon, ...] for each body
$bodies  = [SE_SUN, SE_MOON, SE_MERCURY, SE_VENUS, SE_MARS,
            SE_JUPITER, SE_SATURN, SE_URANUS, SE_NEPTUNE,
            SE_PLUTO, SE_MEAN_NODE, SE_CHIRON];
$results = celestial_calc_many($jd, $bodies, FLG_BUILTIN | FLG_SPEED);
// $results[$i] corresponds to $bodies[$i]

// Nutation (IAU 2000B) — one arg, returns [dpsi, deps] (degrees)
$nut = celestial_nutation($jd);
printf("dpsi=%.6f°  deps=%.6f°\n", $nut[0], $nut[1]);

// Fixed star
$star = celestial_fixstar_ut('Aldebaran', $jd, FLG_BUILTIN);
$mag  = celestial_fixstar_mag('Aldebaran');

Houses

// Returns ['cusps' => float[12], 'ascmc' => float[8]]
// cusps[0..11] are the twelve house cusps
// ascmc[0]=ASC, ascmc[1]=MC, ascmc[2]=ARMC, ascmc[3]=Vertex
$h = celestial_houses_ex($jd, 48.85, 2.35, ord('P'), 0);
printf("ASC=%.2f°  MC=%.2f°\n", $h['ascmc'][0], $h['ascmc'][1]);

// With flags (e.g. sidereal)
$hSid = celestial_houses_ex($jd, 48.85, 2.35, ord('P'), FLG_SIDEREAL);

House system codes: ord('P') Placidus · ord('K') Koch · ord('E') Equal · ord('W') Whole-Sign · ord('O') Porphyry · ord('R') Regiomontanus

Sidereal positions

celestial_set_sid_mode(SIDM_LAHIRI, 0.0, 0.0);
$moon = celestial_calc_ut($jd, SE_MOON, FLG_BUILTIN | FLG_SIDEREAL);
printf("Moon (Lahiri) = %.4f°\n", $moon[0]);

$ayan = celestial_ayanamsa_ut($jd);
printf("Lahiri ayanamsa = %.4f°\n", $ayan);

Moon phases

$phase = celestial_moon_phase($jd);          // int (phase variant)
$illum = celestial_moon_illumination($jd);   // float 0.0–1.0
$elong = celestial_moon_elongation($jd);     // float 0°–360°

$info  = celestial_moon_phase_info($jd);
// $info['phase_name'], $info['illumination'], $info['age_days']
// $info['next_phase_name'], $info['next_phase_jd']
printf("%s  %.1f%%\n", $info['phase_name'], $info['illumination'] * 100);

$newMoon  = celestial_next_new_moon($jd);
$fullMoon = celestial_next_full_moon_phase($jd);

Celtic calendar

$sabbats = celestial_sabbats_for_year(2025);
foreach ($sabbats as $s) {
    $d = celestial_revjul($s['jd'], GREG_CAL);
    printf("%-14s  %04d-%02d-%02d\n", $s['name'], $d['year'], $d['month'], $d['day']);
}

$esbats = celestial_esbats_for_year(2025);
foreach ($esbats as $m) {
    $d = celestial_revjul($m['jd'], GREG_CAL);
    printf("%-18s  %04d-%02d-%02d\n", $m['display_name'], $d['year'], $d['month'], $d['day']);
}

Vedic / Jyotish

celestial_set_sid_mode(SIDM_LAHIRI, 0.0, 0.0);
$moon = celestial_calc_ut($jd, SE_MOON, FLG_BUILTIN | FLG_SIDEREAL);

[$nak, $pada] = celestial_long_to_nakshatra($moon[0]);
printf("Nakshatra: %s, pada %d\n", celestial_nakshatra_name($nak), $pada + 1);

$rasi    = celestial_long_to_rasi($moon[0]);     // 0–11
$navamsa = celestial_long_to_navamsa($moon[0]);  // 0–11

$dashas  = celestial_vimshottari_dasha($jd, $moon[0], 120.0);
foreach (array_slice($dashas, 0, 3) as $d) {
    printf("%s dasha: %.1f years\n", $d['planet_name'], $d['years']);
}

Hellenistic / Persian

$sun = celestial_calc_ut($jd, SE_SUN, FLG_BUILTIN);
$h   = celestial_houses_ex($jd, 48.85, 2.35, ord('P'), 0);

// Day or night chart
$isDay = celestial_is_day_chart($sun[0], $h['cusps']);

// Egyptian terms ruler (planet index 0–6)
$ruler = celestial_egyptian_terms_ruler($sun[0]);

// Chaldean decan ruler
$decan = celestial_decan_ruler($sun[0]);

// Full dignity: [dignity_name, score]
[$dignityName, $score] = celestial_full_dignity(SE_SUN, $sun[0], $isDay);
printf("Sun dignity: %s (score %d)\n", $dignityName, $score);

// Almuten: [body_raw, score]
[$almutenBody, $almutenScore] = celestial_almuten($sun[0], $isDay);

// Firdaria periods: array of ['major_lord', 'minor_lord', 'start_jd', 'end_jd', 'years']
$periods = celestial_firdaria($jd, $isDay, 75.0);
foreach (array_slice($periods, 0, 3) as $p) {
    printf("Major: %d  Minor: %d  Start JD: %.1f\n",
        $p['major_lord'], $p['minor_lord'], $p['start_jd']);
}

// Annual profection: [house_number, profected_lon]
[$houseNum, $profLon] = celestial_annual_profection($h['cusps'], 35);
printf("Age 35 → House %d (%.2f°)\n", $houseNum, $profLon);

Chinese astrology (Ba Zi)

$sun     = celestial_calc_ut($jd, SE_SUN, FLG_BUILTIN);
$pillars = celestial_four_pillars($jd, 9.0, $sun[0]);

$labels = ['Year', 'Month', 'Day', 'Hour'];
foreach ($pillars as $i => $pillar) {
    printf("%s: %s %s (%s)\n",
        $labels[$i], $pillar['stem_name'], $pillar['branch_name'], $pillar['animal']);
}

// Solar term: [current_idx, deg_into, next_idx, deg_to_next]
[$curIdx, $degInto, $nextIdx, $degToNext] = celestial_solar_term_position($sun[0]);

Mesoamerican calendars

// Aztec Tonalpohualli: [trecena, sign_idx, nahuatl_name, english]
$tonal = celestial_tonalpohualli($jd);
printf("Tonalpohualli: %d %s (%s)\n", $tonal[0], $tonal[2], $tonal[3]);

// Aztec Xiuhpohualli: [month_idx, day, name, english]
$xiu = celestial_xiuhpohualli($jd);

// Maya Tzolkin: [trecena, sign_idx, mayan_name, english]
$tzolkin = celestial_tzolkin($jd);

// Maya Haab: [month_idx, day, name]
$haab = celestial_haab($jd);

// Calendar Round: [tz_trecena, tz_sign, haab_day, haab_month]
$cr = celestial_calendar_round($jd);

Solar (Schwabe) cycle

// Inside the numbered Schwabe cycles (1755 → ~2030):
$info = celestial_solar_cycle(2_451_545.0);
if ($info === null) {
    echo "outside numbered cycles\n";
} else {
    [$cycle_num, $phase, $phase_name, $min_jd, $max_jd, $next_min_jd,
     $years_since_min, $nickname, $grand_epoch] = $info;
    printf("Cycle %s — %s (%.1fy in)\n", $cycle_num, $phase_name, (float)$years_since_min);
    if ($nickname !== '') echo "  aka: $nickname\n";
}

// Centuries-scale label, callable for any JD (null when normal):
$epoch = celestial_grand_solar_epoch(2_341_973.0);   // "Maunder Minimum"

// Informal cycle nicknames (null for cycles without one):
echo celestial_cycle_nickname(19); // "the Great Cycle"
echo celestial_cycle_nickname(20) ?? '(none)';

All numeric fields come back as strings (PHP binding convention for tuple- shaped returns); cast to float / int as needed.

Returns null for non-finite input or for dates outside cycles 1..=25.


Indigenous / Egyptian

$sun = celestial_calc_ut($jd, SE_SUN, FLG_BUILTIN);

// Medicine Wheel: [animal, element, clan, season]
$totem = celestial_medicine_wheel_totem($sun[0]);
printf("Totem: %s — %s element, %s clan, %s\n",
    $totem[0], $totem[1], $totem[2], $totem[3]);

// Egyptian decan: [idx, decan_name, rising_star]
$decan = celestial_egyptian_decan($sun[0]);
printf("Decan %d: %s (rising star: %s)\n", $decan[0] + 1, $decan[1], $decan[2]);

Angle transits

// Natal angle transits (ic / asc / dsc added alongside existing mc_transit_ut)
$jd_mc  = celestial_mc_transit_ut($planet, $jd_natal, $jd_start, $lat, $lon, $hsys, $flags, false);
$jd_ic  = celestial_ic_transit_ut($planet, $jd_natal, $jd_start, $lat, $lon, $hsys, $flags, false);
$jd_asc = celestial_asc_transit_ut($planet, $jd_natal, $jd_start, $lat, $lon, $hsys, $flags, false);
$jd_dsc = celestial_dsc_transit_ut($planet, $jd_natal, $jd_start, $lat, $lon, $hsys, $flags, false);

Ba Zi — Four Pillars of Destiny

// Returns flat string array per pillar (Year/Month/Day/Hour):
// [stem_index, branch_index, stem_name, branch_name, animal, yang, ...]
$pillars = celestial_four_pillars($jd_ut, $hour_ut, $sun_lon);
for ($i = 0; $i < 4; $i++) {
    $base = $i * 6;
    echo $pillars[$base + 2] . " " . $pillars[$base + 3]; // e.g. "Jia Zi"
}

Error handling

Functions return null on failure:

$pos = celestial_calc_ut($jd, SE_SUN, FLG_BUILTIN);
if ($pos === null) {
    error_log('celestial_calc_ut failed');
    return;
}

Return type reference

Function Returns
celestial_calc_ut [lon, lat, dist, speed_lon, speed_lat, speed_dist, ret]
celestial_calc_many array of the above arrays
celestial_houses_ex ['cusps' => float[13], 'ascmc' => float[8]]
celestial_nutation [float $dpsi, float $deps] (degrees)
celestial_revjul ['year' => int, 'month' => int, 'day' => int, 'hour' => float]
celestial_moon_phase_info ['phase_name', 'illumination', 'age_days', 'next_phase_name', …]
celestial_four_pillars array[4] of ['stem_name', 'branch_name', 'animal', …]
celestial_firdaria array of ['major_lord', 'minor_lord', 'start_jd', 'end_jd', 'years']
celestial_full_dignity [string $name, int $score]
celestial_almuten [int $body, int $score]
celestial_is_day_chart bool
celestial_tonalpohualli [int $trecena, int $sign_idx, string $name, string $english]
celestial_medicine_wheel_totem [string $animal, string $element, string $clan, string $season]
celestial_egyptian_decan [int $idx, string $name, string $rising_star]

Legacy / compatibility aliases

These SwissEph-compatible names are available alongside the celestial_-prefixed versions:

// All available as both bare and celestial_-prefixed:
$norm  = degnorm(361.5);           // same as norm_deg()
$diff  = difdeg2n(10.0, 350.0);   // same as diff_deg_signed()
$nm    = next_sabbat_name($jd);   // returns name string
$fm    = next_full_moon($jd);     // same as next_full_moon_after()
$cross = solcross_ut(0.0, $jd, FLG_BUILTIN); // vernal equinox JD

Recent additions — 19 new functions

ISO 8601 week

[$iso_year, $week] = iso_week(2456293.0);      // [2012, 52]
$dow               = day_of_year(2024, 3, 15);
$wks               = weeks_in_iso_year(2020);  // 53

Maya Long Count

[$b, $k, $t, $u, $ki] = maya_long_count(2456283.0);  // [13, 0, 0, 0, 0]
$s                     = maya_long_count_str(2451545.0); // "12.19.6.15.2"

Yallop crescent visibility

$jd_best            = best_time_method($jd_sunset, $jd_moonset);
[$q, $class_code]   = yallop_q($arcv_deg, $arcl_deg, $sd_arcmin);
$class              = chr((int) $class_code);   // 'A'..'F'

Coptic / Ethiopic (feature: calendar-traditions)

$jd             = coptic_to_jd(1740, 1, 1);
[$y, $m, $d]    = jd_to_coptic($jd);
$is_leap        = is_coptic_leap_year(1739);    // true
$days           = coptic_month_days(1739, 13);  // 6

Zoroastrian Fasli (feature: calendar-traditions)

$jd_nowruz = fasli_nowruz_jd(2024);   // float|null
$date      = jd_to_fasli(2460400.0);  // [int, int, int]|null

Tibetan Phugpa (feature: calendar-traditions)

$jd_losar                             = losar_jd(2024);
[$cycle, $yic, $el, $gender, $animal] = tibetan_year_name(2024);
// ["17", "38", "Wood", "Male", "Dragon"]

Vietnamese Âm Lịch

$jd_month_start = vietnamese_month_start_jd(2460000.0);
$diverges       = vietnamese_chinese_boundary_differs(2460000.0);