{"id":13579089,"url":"https://github.com/spatie/icalendar-generator","last_synced_at":"2025-04-14T02:59:11.145Z","repository":{"id":34651398,"uuid":"170831958","full_name":"spatie/icalendar-generator","owner":"spatie","description":"Generate calendars in the iCalendar format","archived":false,"fork":false,"pushed_at":"2025-04-11T14:10:55.000Z","size":503,"stargazers_count":627,"open_issues_count":1,"forks_count":60,"subscribers_count":14,"default_branch":"main","last_synced_at":"2025-04-14T02:59:05.823Z","etag":null,"topics":["calendar","hacktoberfest","icalendar","ics","laravel","php","schedule"],"latest_commit_sha":null,"homepage":"https://spatie.be/open-source","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spatie.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-02-15T08:48:25.000Z","updated_at":"2025-04-11T13:04:24.000Z","dependencies_parsed_at":"2024-03-17T08:47:23.439Z","dependency_job_id":null,"html_url":"https://github.com/spatie/icalendar-generator","commit_stats":{"total_commits":305,"total_committers":34,"mean_commits":8.970588235294118,"dds":0.6262295081967213,"last_synced_commit":"a608c158e51158aef39d91b1bd7b6587dc86d804"},"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Ficalendar-generator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Ficalendar-generator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Ficalendar-generator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Ficalendar-generator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spatie","download_url":"https://codeload.github.com/spatie/icalendar-generator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248813789,"owners_count":21165633,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calendar","hacktoberfest","icalendar","ics","laravel","php","schedule"],"created_at":"2024-08-01T15:01:36.469Z","updated_at":"2025-04-14T02:59:11.107Z","avatar_url":"https://github.com/spatie.png","language":"PHP","funding_links":[],"categories":["PHP"],"sub_categories":[],"readme":"# Generate calendars in the iCalendar format\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/spatie/icalendar-generator.svg?style=flat-square)](https://packagist.org/packages/spatie/icalendar-generator)\n[![Tests](https://github.com/spatie/icalendar-generator/actions/workflows/run-tests.yml/badge.svg)](https://github.com/spatie/icalendar-generator/actions/workflows/run-tests.yml)\n[![Check \u0026 fix styling](https://github.com/spatie/icalendar-generator/actions/workflows/fix-styling.yml/badge.svg)](https://github.com/spatie/icalendar-generator/actions/workflows/fix-styling.yml)\n[![Psalm](https://github.com/spatie/icalendar-generator/actions/workflows/psalm.yml/badge.svg)](https://github.com/spatie/icalendar-generator/actions/workflows/psalm.yml)\n[![Total Downloads](https://img.shields.io/packagist/dt/spatie/icalendar-generator.svg?style=flat-square)](https://packagist.org/packages/spatie/icalendar-generator)\n\nWant to create online calendars so that you can display them on an iPhone's calendar app or in Google Calendar?\nThis can be done by generating calendars in the iCalendar format (RFC 5545), a textual format that can be loaded by different applications.\n\nThe format of such calendars is defined in [RFC 5545](https://tools.ietf.org/html/rfc5545), which is not a pleasant reading experience.\nThis package implements [RFC 5545](https://tools.ietf.org/html/rfc5545) and some extensions from [RFC 7986](https://tools.ietf.org/html/rfc7986) to provide you an easy to use API for creating calendars.\nIt's not our intention to implement these RFC's entirely but to provide a straightforward API that's easy to use.\n\nHere's an example of how to use it:\n\n```php\nuse Spatie\\IcalendarGenerator\\Components\\Calendar;\nuse Spatie\\IcalendarGenerator\\Components\\Event;\n\nCalendar::create('Laracon online')\n    -\u003eevent(Event::create('Creating calender feeds')\n        -\u003estartsAt(new DateTime('6 March 2019 15:00'))\n        -\u003eendsAt(new DateTime('6 March 2019 16:00'))\n    )\n    -\u003eget();\n```\n\nThe above code will generate this string:\n\n```\nBEGIN:VCALENDAR\nVERSION:2.0\nPRODID:spatie/icalendar-generator\nNAME:Laracon online\nX-WR-CALNAME:Laracon online\nBEGIN:VEVENT\nUID:5ef5c3f64cb2c\nDTSTAMP;TZID=UTC:20200626T094630\nSUMMARY:Creating calendar feeds\nDTSTART:20190306T150000Z\nDTEND:20190306T160000Z\nDTSTAMP:20190419T135034Z\nEND:VEVENT\nEND:VCALENDAR\n```\n\n## Support us\n[\u003cimg src=\"https://github-ads.s3.eu-central-1.amazonaws.com/icalendar-generator.jpg?t=1\" width=\"419px\" /\u003e](https://spatie.be/github-ad-click/icalendar-generator)\n\nWe invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).\n\nWe highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).\n\n## Installation\n\nYou can install the package via composer:\n\n```bash\ncomposer require spatie/icalendar-generator\n```\n\n## Upgrading\n\nThere were some substantial changes between v1 and v2 of the package. Check the [upgrade](https://github.com/spatie/icalendar-generator/blob/master/UPGRADING.md) guide for more information.\n\n## Usage\n\nHere's how you can create a calendar:\n\n``` php\n$calendar = Calendar::create();\n```\n\nYou can give a name to the calendar:\n\n``` php\n$calendar = Calendar::create('Laracon Online');\n```\n\nA description can be added to a calendar:\n\n``` php\n$calendar = Calendar::create()\n    -\u003ename('Laracon Online')\n    -\u003edescription('Experience Laracon all around the world');\n```\n\nIn the end, you want to convert your calendar to text so that it can be streamed or downloaded to the user. Here's how you do that:\n\n``` php\nCalendar::create('Laracon Online')-\u003eget(); // BEGIN:VCALENDAR ...\n```\n\nWhen [streaming](#use-with-laravel) a calendar to an application, it is possible to set the calendar's refresh interval by duration in minutes. When setting this, the calendar application will check your server every time after the specified duration for changes to the calendar:\n\n``` php\nCalendar::create('Laracon Online')\n    -\u003erefreshInterval(5)\n    ...\n```\n\n### Event\n\nAn event can be created as follows. A name is not required, but a start date should always be given:\n\n``` php\nEvent::create('Laracon Online')\n    -\u003estartsAt(new DateTime('6 march 2019'));\n```\n\nYou can set the following properties on an event:\n\n``` php\nEvent::create()\n    -\u003ename('Laracon Online')\n    -\u003edescription('Experience Laracon all around the world')\n    -\u003euniqueIdentifier('A unique identifier can be set here')\n    -\u003ecreatedAt(new DateTime('6 march 2019'))\n    -\u003estartsAt(new DateTime('6 march 2019 15:00'))\n    -\u003eendsAt(new DateTime('6 march 2019 16:00'));\n```\n\nWant to create an event quickly with a start and end date?\n\n``` php\nEvent::create('Laracon Online')\n    -\u003eperiod(new DateTime('6 march 2019'), new DateTime('7 march 2019'));\n```\n\nYou can add a location to an event a such:\n\n``` php\nEvent::create()\n    -\u003eaddress('Kruikstraat 22, 2018 Antwerp, Belgium')\n    -\u003eaddressName('Spatie HQ')\n    -\u003ecoordinates(51.2343, 4.4287)\n    ...\n```\n\nYou can set the organizer of an event, the email address is required, but the name can be omitted:\n\n``` php\nEvent::create()\n    -\u003eorganizer('ruben@spatie.be', 'Ruben')\n    ...\n```\n\nAttendees of an event can be added as such:\n\n``` php\nEvent::create()\n    -\u003eattendee('ruben@spatie.be') // only an email address is required\n    -\u003eattendee('brent@spatie.be', 'Brent')\n    ...\n```\n\nYou can also set the participation status of an attendee:\n\n``` php\nEvent::create()\n    -\u003eattendee('ruben@spatie.be', 'Ruben', ParticipationStatus::accepted())\n    ...\n```\n\nThere are five participation statuses:\n\n- `ParticipationStatus::accepted()`\n- `ParticipationStatus::declined()`\n- `ParticipationStatus::tentative()`\n- `ParticipationStatus::needs_action()`\n- `ParticipationStatus::delegated()`\n\n\nYou can indicate that an attendee is required to RSVP to an event:\n\n``` php\nEvent::create()\n    -\u003eattendee('ruben@spatie.be', 'Ruben', ParticipationStatus::needs_action(), requiresResponse: true)\n    ...\n```\n\nAn event can be made transparent, so it does not overlap visually with other events in a calendar:\n\n``` php\nEvent::create()\n    -\u003etransparent()\n    ...\n```\n\nIt is possible to create an event that spans a full day:\n\n``` php\nEvent::create()\n    -\u003efullDay()\n    ...\n```\n\nThe status of an event can be set:\n\n``` php\nEvent::create()\n    -\u003estatus(EventStatus::cancelled())\n    ...\n```\n\nThere are three event statuses:\n\n- `EventStatus::confirmed()`\n- `EventStatus::cancelled()`\n- `EventStatus::tentative()`\n\nAn event can be classified(`public`, `private`, `confidential`) as such:\n\n``` php\nEvent::create()\n    -\u003eclassification(Classification::private())\n    ...\n```\n\nYou can add a url attachment as such:\n\n```php\nEvent::create()\n    -\u003eattachment('https://spatie.be/logo.svg')\n    -\u003eattachment('https://spatie.be/feed.xml', 'application/json')\n    ...\n```\n\nYou can add an embedded attachment (base64) as such:\n\n```php\nEvent::create()\n    -\u003eembeddedAttachment($file-\u003etoString())\n    -\u003eembeddedAttachment($fileString, 'application/json')\n    -\u003eembeddedAttachment($base64String, 'application/json', needsEncoding: false)\n    ...\n```\n\nYou can add an image as such:\n\n``` php\nEvent::create()\n    -\u003eimage('https://spatie.be/logo.svg')\n    -\u003eimage('https://spatie.be/logo.svg', 'text/svg+xml')\n    -\u003eimage('https://spatie.be/logo.svg', 'text/svg+xml', Display::badge())\n    ...\n```\n\nThere are four different image display types:\n\n- `Display::badge()`\n- `Display::graphic()`\n- `Display::fullsize()`\n- `Display::thumbnail()`\n\nYou can add a sequence to an event as such:\n\n``` php\nEvent::create()\n    -\u003esequence(1)\n    ...\n```\n\nAfter creating your event, it should be added to a calendar. There are multiple options to do this:\n\n``` php\n// As a single event parameter\n$event = Event::create('Creating calendar feeds');\n\nCalendar::create('Laracon Online')\n    -\u003eevent($event)\n    ...\n\n// As an array of events\nCalendar::create('Laracon Online')\n    -\u003eevent([\n        Event::create('Creating calender feeds'),\n        Event::create('Creating contact lists'),\n    ])\n    ...\n\n// As a closure\nCalendar::create('Laracon Online')\n    -\u003eevent(function(Event $event){\n        $event-\u003ename('Creating calender feeds');\n    })\n    ...\n```\n\n#### Using Carbon\n\nYou can use the popular [Carbon library](https://carbon.nesbot.com/):\n\n``` php\nuse Carbon\\Carbon;\n\nEvent::create('Laracon Online')\n    -\u003estartsAt(Carbon::now())\n    ...\n```\n\n#### Timezones\n\nEvents will use the [timezones]((https://www.php.net/manual/en/datetime.settimezone.php)) defined in the `DateTime` objects you provide. PHP always sets these timezones in a `DateTime` object. By default, this will be the UTC timezone, but it is possible to [change](https://www.php.net/manual/en/function.date-default-timezone-set.php) this.\n\nJust a reminder: do not use PHP's `setTimezone` function on a `DateTime` object, it will change the time according to the timezone! It is better to create a new `DateTime` object with a timezone as such:\n\n``` php\nnew DateTime('6 march 2019 15:00', new DateTimeZone('Europe/Brussels'))\n```\n\nA point can be made for omitting timezones. For example, when you want to show an event at noon in the world. We define noon at 12 o'clock, but that time is relative. It is not the same for people in Belgium, Australia, or any other country in the world.\n\nThat's why you can disable timezones on events:\n\n``` php\n$starts = new DateTime('6 march 2019 12:00')\n\nEvent::create()\n    -\u003estartsAt($starts)\n    -\u003ewithoutTimezone()\n    ...\n```\n\nYou can even disable timezones for a whole calendar:\n\n``` php\nCalendar::create()\n   -\u003ewithoutTimezone()\n    ...\n```\n\nEach calendar should have Timezone components describing the timezones used within your calendar. Although not all calendar clients require this, it is recommended to add these components.\n\nCreating such Timezone components is quite complicated. That's why this package will automatically add them for you without configuration.\n\nYou can disable this behaviour as such:\n\n``` php\nCalendar::create()\n   -\u003ewithoutAutoTimezoneComponents()\n    ...\n```\n\nYou can manually add timezones to a calendar if desired as such:\n\n```php\n$timezoneEntry = TimezoneEntry::create(\n    TimezoneEntryType::daylight(),\n    new DateTime('23 march 2020'),\n    '+00:00',\n    '+02:00'\n);\n\n$timezone = Timezone::create('Europe/Brussels')\n    -\u003eentry($timezoneEntry)\n    ...\n\nCalendar::create()\n    -\u003etimezone($timezone)\n    ...\n```\n\nMore on these timezones later.\n\n#### Alerts\n\nAlerts allow calendar clients to send reminders about specific events. For example, Apple Mail on an iPhone will send users a notification about the event. An alert always belongs to an event has a description and a number of minutes before the event it will be triggered:\n\n``` php\nEvent::create('Laracon Online')\n    -\u003ealertMinutesBefore(5, 'Laracon online is going to start in five minutes');\n```\n\nYou can also trigger an alert after the event:\n\n``` php\nEvent::create('Laracon Online')\n    -\u003ealertMinutesAfter(5, 'Laracon online has ended, see you next year!');\n```\n\nOr trigger an alert on a specific date:\n\n``` php\nEvent::create('Laracon Online')\n    -\u003ealertAt(\n       new DateTime('05/16/2020 12:00:00'),\n       'Laracon online has ended, see you next year!'\n    );\n```\n\nRemoving timezones on a calendar or event will also remove timezones on the alert.\n\n### Repeating events\n\nIt is possible for events to repeat, for example your monthly company dinner. This can be done as such:\n\n```php\nEvent::create('Laracon Online')\n    -\u003erepeatOn(new DateTime('05/16/2020 12:00:00'));\n```\n\nAnd you can also repeat the event on a set of dates:\n\n```php\nEvent::create('Laracon Online')\n    -\u003erepeatOn([new DateTime('05/16/2020 12:00:00'), new DateTime('08/13/2020 15:00:00')]);\n```\n\n#### Recurrence rules\n\nRecurrence rules or RRule's in short, make it possible to add a repeating event in your calendar by describing when it repeats within an RRule. First, we have to create an RRule:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::daily());\n```\n\nThis rule describes an event that will be repeated daily. You can also set the frequency to `secondly`, `minutely`, `hourly`, `weekly`, `monthly` or `yearly`.\n\nThe RRULE can be added to an event as such:\n\n``` php\nEvent::create('Laracon Online')\n    -\u003errule(RRule::frequency(RecurrenceFrequency::monthly()));\n```\n\nIt is possible to finetune the RRule to your personal taste; let's have a look!\n\nA RRule can start from a certain point in time:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::daily())-\u003estarting(new DateTime('now'));\n```\n\nAnd stop at a certain point:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::daily())-\u003euntil(new DateTime('now'));\n```\n\nIt can only be repeated for a few times, 10 times for example:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::daily())-\u003etimes(10);\n```\n\nThe interval of the repetition can be changed:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::daily())-\u003einterval(2);\n```\n\nWhen this event starts on Monday, for example, the next repetition of this event will not occur on Tuesday but Wednesday. You can do the same for all the frequencies.\n\nIt is also possible to repeat the event on a specific weekday:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::monthly())-\u003eonWeekDay(\n   RecurrenceDay::friday()\n);\n```\n\nOr on a specific weekday of a week in the month:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::monthly())-\u003eonWeekDay(\n   RecurrenceDay::friday(), 3\n);\n```\n\nOr on the last weekday of a month:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::monthly())-\u003eonWeekDay(\n   RecurrenceDay::sunday(), -1\n);\n```\n\nYou can repeat on a specific day in the month:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::monthly())-\u003eonMonthDay(16);\n```\n\nIt is even possible to give an array of days in the month:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::monthly())-\u003eonMonthDay(\n   [5, 10, 15, 20]\n);\n```\n\nRepeating can be done for certain months (for example only in the second quarter):\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::monthly())-\u003eonMonth(\n   [RecurrenceMonth::april(), RecurrenceMonth::may(), RecurrenceMonth::june()]\n);\n```\n\nOr just on one month only:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::monthly())-\u003eonMonth(\n   RecurrenceMonth::october()\n);\n```\n\nIt is possible to set the day when the week starts:\n\n```php\n$rrule = RRule::frequency(RecurrenceFrequency::monthly())-\u003eweekStartsOn(\n   ReccurenceDay::monday()\n);\n```\n\nYou can provide a specific date on which an event won't be repeated:\n\n```php\nEvent::create('Laracon Online')\n    -\u003errule(RRule::frequency(RecurrenceFrequency::daily()))\n    -\u003edoNotRepeatOn(new DateTime('05/16/2020 12:00:00'));\n```\n\nIt is also possible to give an array of dates on which the event won't be repeated:\n\n```php\nEvent::create('Laracon Online')\n    -\u003errule(RRule::frequency(RecurrenceFrequency::daily()))\n    -\u003edoNotRepeatOn([new DateTime('05/16/2020 12:00:00'), new DateTime('08/13/2020 15:00:00')]);\n```\n\nAlternatively you can add RRules as a string:\n\n```php\nEvent::create('SymfonyCon')\n    -\u003erruleAsString('FREQ=DAILY;INTERVAL=1');\n```\n\nIf you add RRules as a string the timezones included in DTSTART and UNTIL are unknown to the package as the string is never parsed and evaluated. If they are known you can add DTSTART and UNTIL separately to help the package discover the timezones:\n\n```php\nEvent::create('SymfonyCon')\n    -\u003erruleAsString(\n        'DTSTART=20231207T090000Z;FREQ=DAILY;INTERVAL=1;UNTIL=20231208T090000Z',\n        new DateTime('7 december 2023 09:00:00', new DateTimeZone('UTC')),\n        new DateTime('8 december 2023 09:00:00', new DateTimeZone('UTC'))\n    );\n```\n\n\n### Use with Laravel\n\nYou can use Laravel Responses to stream to calendar applications:\n\n``` php\n$calendar = Calendar::create('Laracon Online');\n\nreturn response($calendar-\u003eget())\n    -\u003eheader('Content-Type', 'text/calendar; charset=utf-8');\n```\n\nIf you want to add the possibility for users to download a calendar and import it into a calendar application:\n\n``` php\n$calendar = Calendar::create('Laracon Online');\n\nreturn response($calendar-\u003eget(), 200, [\n   'Content-Type' =\u003e 'text/calendar; charset=utf-8',\n   'Content-Disposition' =\u003e 'attachment; filename=\"my-awesome-calendar.ics\"',\n]);\n```\n\n### Crafting Timezones\n\nIf you want to craft timezone components yourself, you're in the right place, although we advise you to read the [section](https://tools.ietf.org/html/rfc5545#section-3.6.5) on timezones from the RFC first.\n\nYou can create a timezone as such:\n\n```php\n$timezone = Timezone::create('Europe/Brussels');\n```\n\nIt is possible to provide the last modified date:\n\n```php\n$timezone = Timezone::create('Europe/Brussels')\n    -\u003elastModified(new DateTime('16 may 2020 12:00:00'));\n```\n\nOr add an url with more information about the timezone:\n\n```php\n$timezone = Timezone::create('Europe/Brussels')\n    -\u003eurl('https://spatie.be');\n```\n\nA timezone consists of multiple entries where the time of the timezone changed relative to UTC, such entry can be constructed for standard or daylight time:\n\n```php\n$entry = TimezoneEntry::create(\n    TimezoneEntryType::standard(),\n    new DateTime('16 may 2020 12:00:00'),\n    '+00:00',\n    '+02:00'\n);\n```\n\nFirstly you provide the type of entry (`standard` or `daylight`). Then a `DateTime` when the time changes. Lastly, an offset relative to UTC from before the change and an offset relative to UTC after the change.\n\nIt is also possible to give this entry a name and description:\n\n```php\n$entry = TimezoneEntry::create(...)\n    -\u003ename('Europe - Brussels')\n    -\u003edescription('Belgian timezones ftw!');\n```\n\nAn RRule for the entry can be given as such:\n\n```php\n$entry = TimezoneEntry::create(...)\n    -\u003errule(RRule::frequency(RecurrenceFrequency::daily()));\n```\n\nIn the end you can add an entry to a timezone:\n\n```php\n$timezone = Timezone::create('Europe/Brussels')\n   -\u003eentry($timezoneEntry);\n```\n\nOr even add multiple entries:\n\n```php\n$timezone = Timezone::create('Europe/Brussels')\n   -\u003eentry([$timezoneEntryOne, $timezoneEntryTwo]);\n```\n\nNow we've constructed our timezone it is time(👀) to add this timezone to our calendar:\n\n```php\n$calendar = Calendar::create('Calendar with timezones')\n   -\u003etimezone($timezone);\n```\n\nIt is also possible to add multiple timezones:\n\n```php\n$calendar = Calendar::create('Calendar with timezones')\n   -\u003etimezone([$timezoneOne, $timezoneTwo]);\n```\n\n\n### Extending the package\n\nWe try to keep this package as straightforward as possible. That's why a lot of properties and subcomponents from the RFC are not included in this package. We've made it possible to add other properties or subcomponents to each component if you might need something not included in the package. But be careful! From this moment, you're on your own correctly implementing the RFC's.\n\n#### Appending properties\n\nYou can add a new property to a component like this:\n\n```php\nCalendar::create()\n    -\u003eappendProperty(\n        TextProperty::create('ORGANIZER', 'ruben@spatie.be')\n    )\n    ...\n```\n\nHere we've added a `TextProperty `, and this is a default key-value property type with a text as value. You can also use one of the default properties included in the package or create your own by extending the `Property` class.\n\nSometimes a property can have some additional parameters, these are key-value entries and can be added to properties as such:\n\n```php\n$property = TextProperty::create('ORGANIZER', 'ruben@spatie.be')\n    -\u003eaddParameter(Parameter::create('CN', 'RUBEN VAN ASSCHE'));\n\nCalendar::create()\n    -\u003eappendProperty($property)\n    ...\n```\n\n#### Appending subcomponents\n\n\nA subcomponent can be appended as such:\n\n```php\nCalendar::create()\n    -\u003eappendSubComponent(\n        Event::create('Extending icalendar-generator')\n    )\n    ...\n```\n\nIt is possible to create your subcomponents by extending the `Component` class.\n\n### Testing\n\n``` bash\ncomposer test\n```\n\n### Alternatives\n\nWe strive for a simple and easy to use API. Want something more? Then check out this [package](https://github.com/markuspoerschke/iCal) by Markus Poerschke.\n\n### Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.\n\n## Contributing\n\nPlease see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.\n\n### Security\n\nIf you've found a bug regarding security please mail [security@spatie.be](mailto:security@spatie.be) instead of using the issue tracker.\n\n## Postcardware\n\nYou're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.\n\nOur address is: Spatie, Kruikstraat 22, box 12, 2018 Antwerp, Belgium.\n\nWe publish all received postcards [on our company website](https://spatie.be/en/opensource/postcards).\n\n## Credits\n\n- [Ruben Van Assche](https://github.com/rubenvanassche)\n- [All Contributors](../../contributors)\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspatie%2Ficalendar-generator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspatie%2Ficalendar-generator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspatie%2Ficalendar-generator/lists"}