承接 blindaue/phpade 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

blindaue/phpade

Composer 安装命令:

composer require blindaue/phpade

包简介

PHP 8 ADE Web API Client

README 文档

README

PHP 8 client for ADE Web API from Adesoft.

This is an unofficial development. I am in no way related to this company. Use it at your own risk.

Installation

composer require blindaue/phpade

Configuration

Environment Variables

Create a .env.local file in your project root:

ADE_WEB_API_URL="https://ade.domain.tld/jsp/webapi"
ADE_WEB_API_LOGIN="your_login"
ADE_WEB_API_PASSWORD="your_password"

Or use environment variables directly:

export ADE_WEB_API_URL="https://ade.domain.tld/jsp/webapi"
export ADE_WEB_API_LOGIN="your_login"
export ADE_WEB_API_PASSWORD="your_password"

Standalone Usage

<?php

require_once 'vendor/autoload.php';

use Phpade\AdeWebAPI;

$api = new AdeWebAPI();
$api->connect();
$api->setProject(4);

$projects = $api->getProjects(['detail' => 4]);
$instructors = $api->getResources(['category' => 'instructor', 'detail' => 6]);

foreach ($instructors as $instructor) {
    echo $instructor['name'] . ' - ' . ($instructor['email'] ?? 'no email') . "\n";
}

$api->disconnect();

Detail Levels (ADE Reader 10/07/2025)

Recommended levels for current ADE Reader docs:

  • getEvents: use detail=4 for base event data.
  • getEvents: use detail=7 for lifecycle fields such as creation and lastUpdate.
  • getEvents: use detail=8 for full payload with nested resources / additional.
  • getActivities: use detail=15 to include nested resources in activities.

Notes:

  • getEvents(detail>4) now auto-falls back to detail=4 when ADE returns only empty <event/> nodes.
  • Flattened rows now keep nested children (resources, additional, rights, etc.), including single-item responses.

Samples

  • php sample/events_detail_probe.php [activityId] [projectId] Compare getEvents detail 4, 7 and 8, print diagnostics and lifecycle/resource fields.
  • php sample/events_cache_fallback_probe.php [activityId] [projectId] Simulate a degenerate high-detail cache payload and show automatic fallback/recovery.
  • php sample/activities_detail_ladder_probe.php [codeX] [projectId] Demonstrate adaptive activity detail ladder (4 -> 10 -> 15) with required-field coverage.
  • php sample/object_search_playbook.php [projectId] [codeX] [--email=...] [--path=...] [--category=trainee] End-to-end object-search playbook with diagnostics for resources and activities.
  • php sample/events_by_email_and_codex.php <email> [codeX] [projectId] Fetch instructor events with optional codeX.
  • php sample/events_by_email_and_codex_monthly.php <email> [projectId] [--codex=ILL] [--sessions] [--json] Monthly aggregation/reporting sample (--sessions also prints creation / lastUpdate).

Caching

The API supports file-based caching:

$api->setCacheDir('/tmp/ade_cache', 172800, 21600);
// 172800s = 48h for resources/activities
// 21600s = 6h for events

Or use any PSR-16 compatible cache:

use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Psr16Cache;

$psr6Pool = new FilesystemAdapter('ade_api', 0, '/tmp/ade_cache');
$psr16Cache = new Psr16Cache($psr6Pool);
$api->setCache($psr16Cache);

Cache Policy, Fallback and Diagnostics

You can configure stale-cache fallback globally:

$api->setCachePolicy([
    'stale_on_error' => true,
    'stale_max_age_seconds' => 7 * 24 * 3600, // optional
]);

And override policy per call:

$resources = $api->getResources(
    ['category' => 'instructor', 'detail' => 6],
    true,
    ['stale_on_error' => false]
);

This also applies to tree=true lookups and hierarchy helpers:

$nodes = $api->useProject(4, fn (AdeWebAPI $api) => $api->getHierarchyFromPath(
    'Iut Illkirch.CHIMIE',
    [
        'resourceCategory' => 'trainee',
        'leafCategory' => 'trainee',
        'cachePolicy' => [
            'stale_on_error' => true,
            'stale_max_age_seconds' => 604800,
        ],
    ]
));

Fallback behavior details:

  • HTTP client and server errors (4xx and 5xx), XML parsing failures, timeouts, and network/transport errors are treated as fallbackable when stale_on_error=true.
  • findResourceByPath* first tries stale cache with the exact segment query key (name, fatherIds, detail, category), then falls back to broader cached category snapshots.
  • getEvents fallback also handles degenerate high-detail payloads ([[], [], ...]) by retrying with detail=4, then overwriting the high-detail cache key with recovered data.
  • queryActivities now supports adaptive detail ladders to limit cost and escalate only when needed:
$activities = $api->queryActivities(
    ['codeX' => 'ILL'],
    15,
    [
        'prefer_lower_detail' => true,                // try 4 then 10 before 15
        'required_fields' => ['code', 'CODE'],        // escalate if missing
        'min_required_fields_coverage' => 0.85,       // expected row coverage
        // optional: 'detail_ladder' => [4, 10, 15],  // explicit order
    ]
);

After a call, diagnostics are available:

$diagnostic = $api->getLastCallDiagnostic();
// [
//   'source' => 'network' | 'cache_fresh' | 'cache_stale',
//   'fallbackReason' => 'http_4xx' | 'http_500' | 'http_5xx' | 'timeout' | 'parse_error' | ...
//   'cache' => ['key' => ..., 'expiresAt' => ..., 'isExpired' => ...]
// ]

Cache metadata can include expired entries:

$meta = $api->getCacheEntryMetadata(
    'getResources',
    ['category' => 'instructor', 'detail' => 6],
    true // includeExpired
);

Efficient Object Search

When ADE datasets are large, performance mainly depends on query order and detail levels. Use this playbook to keep requests fast and only pay for high-detail payloads when required.

1. Start With Narrow Resource Lookups

Prefer precise lookups before broad lists:

$instructor = $api->findResourceByField('instructor', 'email', $email, 10);
$group = $api->findResourceByPathInCategory('Iut Illkirch.CHIMIE', 'trainee', 2);
  • detail=2 is usually enough for path/category traversal.
  • detail=10 is useful when matching on fields like email.

2. Use Adaptive Detail For Activities

Activities can be expensive at high detail. Use the ladder:

$activities = $api->queryActivities(
    ['codeX' => 'ILL'],
    15,
    [
        'prefer_lower_detail' => true,
        'detail_ladder' => [4, 10, 15],
        'required_fields' => ['code', 'CODE'],
        'min_required_fields_coverage' => 0.85,
    ]
);
  • Fast path: keep detail 4 or 10 if coverage is already good.
  • Escalation path: move to 15 only if required fields are missing.

3. Query Events Only For Selected Activities

Build event queries from resolved activity IDs (not broad time windows when avoidable):

$eventRows = $api->queryEvents([
    'activities' => implode('|', $activityIds),
], 7);

Use detail=8 only if you also need nested children (resources, additional). getEvents already contains native fallback for degenerate high-detail payloads.

4. Keep Cache And Diagnostics On

$api->setCacheDir('/tmp/ade_cache', 172800, 21600);
$api->setCachePolicy([
    'stale_on_error' => true,
    'stale_max_age_seconds' => 7 * 24 * 3600,
]);

After each step, inspect diagnostics:

$diagnostic = $api->getLastCallDiagnostic();

Useful indicators:

  • source=cache_fresh|cache_stale|network
  • fallbackReason=detail_ladder_to_10|detail_fallback_to_4|http_500|...
  • requestedDetail / detailUsed (for queryActivities)

5. Typical Efficient Sequence

  1. Resolve a resource (findResourceByField or findResourceByPathInCategory)
  2. Fetch activities with adaptive ladder (queryActivities)
  3. Fetch events for selected activity IDs (queryEvents)
  4. Check diagnostics and tune ladder thresholds

Symfony Integration

1. Install

composer require blindaue/phpade

2. Configure (.env)

ADE_WEB_API_URL=https://ade.domain.tld/jsp/webapi
ADE_WEB_API_LOGIN=your_login
ADE_WEB_API_PASSWORD=your_password

3. Register Services

config/services.yaml:

services:
    Phpade\Config:
        public: true

    ade.cache.pool:
        class: Symfony\Component\Cache\Adapter\FilesystemAdapter
        arguments:
            - 'ade_api'
            - 0
            - '%kernel.cache_dir%/ade_api'

    ade.cache.psr16:
        class: Symfony\Component\Cache\Psr16Cache
        arguments:
            - '@ade.cache.pool'

    Phpade\AdeWebAPI:
        arguments:
            $config: '@Phpade\Config'
        calls:
            - method: setCache
              arguments:
                  - '@ade.cache.psr16'

Or with a framework cache pool:

framework:
    cache:
        pools:
            cache.app.ade_api:
                adapter: cache.adapter.filesystem
                default_lifetime: 86400

services:
    Phpade\Config:
        public: true

    ade.cache.psr16:
        class: Symfony\Component\Cache\Psr16Cache
        arguments:
            - '@cache.app.ade_api'

    Phpade\AdeWebAPI:
        arguments:
            $config: '@Phpade\Config'
        calls:
            - method: setCache
              arguments:
                  - '@ade.cache.psr16'

4. Usage in a Controller

<?php

namespace App\Controller;

use Phpade\AdeWebAPI;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class ScheduleController extends AbstractController
{
    #[Route('/instructors', name: 'instructors')]
    public function listInstructors(AdeWebAPI $api): Response
    {
        $api->connect();
        $api->setProject(4);

        $instructors = $api->getResources([
            'category' => 'instructor',
            'detail' => 6
        ]);

        $api->disconnect();

        return $this->render('instructors.html.twig', [
            'instructors' => $instructors
        ]);
    }
}

API Reference

See adesoft_webapi_doc.txt for complete API documentation.

Main Methods

MethodDescription
connect()Connect to the API
disconnect()Disconnect from the API
setCachePolicy([...])Configure global cache fallback policy
getLastCallDiagnostic()Get last call source/fallback/cache diagnostic
getCacheEntryMetadata($function, $params, $includeExpired = false)Get cache metadata (optionally including expired entry)
getProjects(['detail' => 4], $useCache = true, $cachePolicy = [])Get available projects
setProject($projectId)Set the current project
getResources([...], $useCache = true, $cachePolicy = [])Get resources (instructors, rooms, etc.)
findResourceByPath(..., $cachePolicy = [])Resolve a path with native stale-cache fallback
getActivities([...], $useCache = true, $cachePolicy = [])Get activities
getEvents([...], $useCache = true, $cachePolicy = [])Get events (includes nested child nodes such as resources)
getEventsByInstructorEmail($email, $codeX = null, $eventDetail = 4)High-level lookup by instructor email with configurable event detail
getHierarchyFromPath($path, ['cachePolicy' => ...])High-level hierarchy lookup with fallback policy support
queryActivities($filters, $detail, $options)Adaptive activity detail ladder (prefer_lower_detail, required_fields, detail_ladder)
queryEvents($filters, $detail = 4)Events query helper (use detail=7 for creation/lastUpdate)

Error Handling

Transport exceptions are enriched with:

  • getHttpStatus()
  • getAdeFunction()
  • getFailureReason() (for example: http_4xx, http_500, http_5xx, timeout, parse_error, transport_error)

Testing

vendor/bin/phpunit tests/php/
vendor/bin/phpcs --standard=PSR12 src/

Integration test is opt-in:

ADE_RUN_INTEGRATION_TESTS=1 ADE_TEST_PROJECT_ID=4 vendor/bin/phpunit tests/php/AdeWebAPITest.php

统计信息

  • 总下载量: 313
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: GPL-3.0-or-later
  • 更新时间: 2026-02-25

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固