Upgrading from vobject 2.x to 3.x

VObject 3.0 got a major overhaul, and much better built-in support for all kinds of properties and escaping.

This version fixes the most important bugs, specifically the issue #19.

To do this, a few backwards compatibility breaks had to be made. This document describes each of them, as well as all the new features.

Overview of new features

Since sabre/vobject 3.1:

Backwards compatibility breaks

Creating components

Before, it was possible to create components such as VEVENT, VTODO, etc with this syntax:

<?php

$event = \Sabre\VObject\Component::create('VEVENT');
$event->summary = 'Birthday party!';

// Or:

$event = new \Sabre\VObject\Component('VEVENT');
$event->summary = 'Birthday party!';

?>

Neither of those are legal any longer. Components now must be created through the Document object.

Example:

<?php

$vcalendar = new \Sabre\VObject\Component\VCalendar();
$event = $vcalendar->createComponent('VEVENT');
$event->summary = 'Birthday party!';

?>

Or:

<?php

$vcalendar = new \Sabre\VObject\Component\VCalendar();
$vcalendar->add('VEVENT', [
    'summary' => 'Birthday party!',
]);

?>

Creating properties

Creating properties works the exact same way.

Old:

<?php

$location = new \Sabre\VObject\Property('LOCATION', 'Home');

// Or:

$location = \Sabre\VObject\Property::create('LOCATION', 'Home');

?>

Now you must also use the document:

Example:

<?php

$card = new \Sabre\VObject\Component\VCard();
$location = $card->createProperty('LOCATION','Home');

?>

Note that in most cases, this syntax is highly recommended instead:

<?php

$card = new \Sabre\VObject\Component\VCard();
$location = $card->add('LOCATION','Home');

?>

In this case it doesn't make much of a difference, but when constructing highly complex objects with sub-components, this will make a big difference.

Component::children() and Property::parameters() return arrays.

Before VObject 3 they returned an ElementList.

The signature for DateTime::setDateTime has changed.

Before, you would use the following 4 syntaxes to set the date and time:

<?php

use Sabre\VObject\Property;

$now = new DateTime('now');

$dt = new Property\DateTime('DTSTART');
$dt->setDateTime($now, Property\DateTime::DATE); // Date only
$dt->setDateTime($now, Property\DateTime::LOCAL); // Floating time
$dt->setDateTime($now, Property\DateTime::UTC); // Convert to UTC
$dt->setDateTime($now, Property\DateTime::LOCALTZ); // Local to timezone information.

?>

This has completely changed:

<?php

// Date only
$now = new DateTime('now');
$dt = $calendar->create('DTSTART');
$dt->setValue($now);
$dt['VALUE'] = 'date';

// Floating time
$dt = $calendar->create('DTSTART');
$dt->setValue($now, $floating = true);

// Convert to UTC
$now->setTimeZone(\DateTimeZone('UTC'));
$dt = $calendar->create('DTSTART');
$dt->setValue($now);

// Local time + timezone information
$dt = $calendar->create('DTSTART');
$dt->setValue($now);

?>

Note that the preceding examples are all a bit convoluted. In most cases you just want to do something like:

<?php

// Assuming this a vevent
$event->DTSTART = $now;

?>

In addition, the MultiDateTime property is no more, and its methods are simply merged into DateTime.

The $value property is now protected everywhere.

Both the Property and the Parameter classes had a public $value property, which allowed you to retrieve the string value for either of those.

This is now protected, so you must access it in this manner:

<?php
// Assuming $prop is a property object.

$prop->setValue('Birthday');
echo $prop->getValue();

?>

// For properties that have more than 1 value, you can use setParts and getParts:

<?php

$org->setParts(['Company', 'Department']);
print_r($org->getParts());

?>

Binary properties are automatically de- and encoded.

The ATTACH, LOGO and PHOTO properties now automatically de- and encode their binary values. In vObject 2 they were accessed by their raw base64 values.

Components and documents get injected with default properties.

When creating a new VCalendar, it will automatically get the VERSION, CALSCALE and PRODID properties.

If you were adding your own with this syntax:

<?php

$calendar = new Sabre\VObject\Component\VCalendar();
$calendar->VERSION = '2.0';

?>

Then nothing will go wrong, and the properties will simply be overwritten. However, if you used add() before in this manner:

<?php

$calendar = new Sabre\VObject\Component\VCalendar();
$calendar->add('version', '2.0');

?>

You will end up with 2 VERSION properties, making the document invalid.

componentMap and propertyMap properties have moved.

When you wanted to automatically map certain components or properties to certain PHP classes, you could do so with Component::$componentMap and Property::$propertyMap.

These properties have now moved to the document classes: