Visitar URL original
zammad-api-client-php/docs/migration-v3-examples.md at master · zammad/zammad-api-client-php · GitHub
Skip to content

Latest commit

 

History

History
377 lines (295 loc) · 7.09 KB

migration-v3-examples.md

File metadata and controls

377 lines (295 loc) · 7.09 KB

Migration from v2 to v3 — Side-by-Side Examples

Connecting

v2:

use ZammadAPIClient\Client;

$client = new Client([
    'url'        => 'https://zammad.example/api/v1',
    'http_token' => 'your-token',
]);

v3:

use ZammadAPIClient\Core\Auth;
use ZammadAPIClient\ZammadClient;

$client = ZammadClient::create(
    'https://zammad.example',
    Auth::token('your-token'),
);

Authentication Methods

v2:

new Client(['url' => $url, 'http_token' => '...']);      // Token
new Client(['url' => $url, 'oauth2_token' => '...']);     // OAuth2
new Client(['url' => $url, 'username' => '...', 'password' => '...']); // Basic

v3:

ZammadClient::create($url, Auth::token('...'));                // Token
ZammadClient::create($url, Auth::oauth2('...'));               // OAuth2
ZammadClient::create($url, Auth::basic('...', '...'));         // Basic

Fetching by ID

v2:

$ticket = $client->resource(ResourceType::TICKET)->get(1);
$title = $ticket->getValue('title');

v3:

$ticket = $client->ticket()->find(1);
$title = $ticket->title;

Accessing Values

v2:

$title  = $ticket->getValue('title');
$data   = $ticket->getValues();

v3:

$title  = $ticket->title;
$data   = $ticket->toArray();

Creating

v2:

$ticket = $client->resource(ResourceType::TICKET);
$ticket->setValue('title', 'My ticket');
$ticket->setValue('group_id', 1);
$ticket->save();

v3:

$ticket = $client->ticket()->create(new TicketDTO(
    title: 'My ticket',
    group_id: 1,
));

Updating

v2:

$ticket = $client->resource(ResourceType::TICKET)->get(1);
$ticket->setValue('title', 'Updated');
$ticket->setValue('state_id', 3);
$ticket->save();

v3:

// Via array
$client->ticket()->patch(1, ['title' => 'Updated']);

// Via TicketUpdateDTO
$client->ticket()->patch(1, new TicketUpdateDTO(
    title: 'Updated',
));

// Via TicketDTO (same behavior — all non-null fields are sent)
$client->ticket()->patch(1, new TicketDTO(
    title: 'Updated',
    state_id: 3,
));

Stateful Resource (Change Tracking)

v2:

$ticket = $client->resource(ResourceType::TICKET)->get(1);
$ticket->setValue('title', 'New');
$ticket->setValue('state_id', 3);
$ticket->save(); // Sends all values back to Zammad

v3:

$resource = $client->ticket()->resource(1);
$resource->title = 'New';
$resource->state_id = 3;
$resource->save(); // Sends only {title, state_id}

// Delete
$resource->destroy();

Deleting

v2:

$ticket = $client->resource(ResourceType::TICKET)->get(1);
$ticket->delete();

v3:

$client->ticket()->delete(1);

Searching

v2:

$tickets = $client->resource(ResourceType::TICKET)->search('some text');
if (!is_array($tickets)) {
    print $tickets->getError();
} else {
    foreach ($tickets as $t) {
        echo $t->getValue('title');
    }
}

v3:

try {
    foreach ($client->ticket()->search('some text') as $ticket) {
        echo $ticket->title;
    }
} catch (NotFoundException $e) {
    echo $e->getMessage();
}

Listing All

v2:

$tickets = $client->resource(ResourceType::TICKET)->all();

v3:

foreach ($client->ticket()->all() as $ticket) {
    echo $ticket->title;
}

Pagination

v2:

$page = $client->resource(ResourceType::TICKET)->all(1, 25);

v3:

$list = $client->ticket()->list(['per_page' => 25]);
$list->page(1);      // First page
$list->page(2);      // Second page
$list->pageNext();   // Next page
$list->pagePrev();   // Previous page
$list->each(function ($t) { echo $t->title; });

Error Handling

v2:

$ticket = $client->resource(ResourceType::TICKET)->get(999);
if ($ticket->hasError()) {
    echo $ticket->getError();
}

v3:

try {
    $ticket = $client->ticket()->find(999);
} catch (NotFoundException $e) {
    echo $e->getMessage();        // "Resource not found: tickets/999"
} catch (ValidationException $e) {
    print_r($e->errors);          // Per-field validation messages
} catch (AuthenticationException $e) {
    // Invalid credentials
} catch (RateLimitException $e) {
    echo $e->retryAfterSeconds;   // Auto-retried, only thrown on exhaustion
} catch (ServerErrorException $e) {
    // 5xx server error
} catch (NetworkException $e) {
    // DNS, timeout, connection refused
}

Ticket Articles

v2:

$ticket = $client->resource(ResourceType::TICKET)->get(1);
$articles = $ticket->getTicketArticles();

v3:

foreach ($client->ticketArticle()->getForTicket(1) as $article) {
    echo $article->body;
}

Ticket Article Attachments

v2:

$ticket_article = $client->resource(ResourceType::TICKET_ARTICLE);
$content = $ticket_article->getAttachmentContent(23);

v3:

$content = $client->ticketArticle()->getAttachmentContent(
    ticketId: 1,
    articleId: 5,
    attachmentId: 23,
);

Tags

v2:

$client->resource(ResourceType::TAG)->add($ticketId, 'urgent', 'Ticket');
$client->resource(ResourceType::TAG)->remove($ticketId, 'urgent', 'Ticket');

$tag = $client->resource(ResourceType::TAG)->get($ticketId, 'Ticket');
$tags = $tag->getValue('tags');

v3:

$client->tag()->add('Ticket', $ticketId, 'urgent');
$client->tag()->remove('Ticket', $ticketId, 'urgent');

foreach ($client->tag()->all(['object' => 'Ticket', 'o_id' => $ticketId]) as $tag) {
    echo $tag->value;
}

$results = $client->tag()->tagSearch('urg');

CSV Import

v2:

$csv = file_get_contents('users.csv');
$client->resource(ResourceType::USER)->import($csv);

v3:

$csv = file_get_contents('users.csv');
$client->user()->import($csv);

Impersonation (On-Behalf-Of)

v2:

$client->setOnBehalfOfUser('myuser');
// ... API calls ...
$client->unsetOnBehalfOfUser();

v3:

use ZammadAPIClient\Core\Transport\ImpersonationHandler;

$asUser = new ZammadClient(new ImpersonationHandler($client->getHandler(), 1));
$asUser->ticket()->find(42);

// $client itself keeps acting as the authenticated user

Breaking: v2 toggled impersonation on the client itself, so the state was global and had to be reset. v3 scopes it to a separate client instance — there is nothing to unset and nothing can leak between calls. A user ID, login or email all work (int|string).

No credentials are passed to ImpersonationHandler: it decorates $client's existing handler and inherits its authentication, adding only the From header.


Resource Access — Typed Accessors

v3 (recommended — typed accessors with IDE autocomplete):

$client->ticket()->find(1);
$client->user()->find(1);
$client->organization()->find(1);
$client->group()->find(1);
$client->role()->all();
$client->ticketArticle()->getForTicket(1);
$client->ticketState()->all();
$client->ticketPriority()->all();
$client->tag()->add('Ticket', 1, 'urgent');
$client->textModule()->find(1);
$client->link()->find(1);

The underlying repo() method is @internal — prefer the typed accessors.