Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/astrxnomo/tourify/llms.txt

Use this file to discover all available pages before exploring further.

Tourify’s MySQL schema is managed entirely by Laravel migrations in backend/database/migrations/. Eleven application tables cover authentication, tourism content, user interactions, and push notifications. Three of those tables — images, favorites, and reviews — use polymorphic relationships so they can belong to multiple entity types without duplicating columns.

Entity reference

Seeded at deploy time. The default role for every new user registration is id = 2 (regular user).
ColumnTypeConstraints
idbigint unsignedPK, auto-increment
namevarcharunique
labelvarchar
descriptiontextnullable
created_attimestamp
updated_attimestamp
Eloquent: RolehasMany(User::class)
Created by the base Laravel migration. The push_token column is added by a separate migration (2026_05_04_add_push_token_to_users_table).
ColumnTypeConstraints
idbigint unsignedPK, auto-increment
role_idbigint unsignedFK → roles.id, default 2, cascade delete
namevarchar
emailvarcharunique
passwordvarcharbcrypt-hashed
remember_tokenvarchar(100)nullable
push_tokenvarcharnullable
created_attimestamp
updated_attimestamp
Eloquent: UserbelongsTo(Role), hasMany(Favorite), hasMany(Review), hasMany(Notification), hasMany(EventRegistration)
Top-level geographic entity. Deleting a city cascades to its places and events.
ColumnTypeConstraints
idbigint unsignedPK, auto-increment
namevarchar
descriptiontextnullable
countryvarchar
created_attimestamp
updated_attimestamp
Eloquent: CityhasMany(Place), hasMany(Event), morphMany(Image, 'imageable')
Used to classify places (e.g. museum, park, restaurant).
ColumnTypeConstraints
idbigint unsignedPK, auto-increment
namevarchar
descriptiontextnullable
created_attimestamp
updated_attimestamp
Eloquent: CategoryhasMany(Place)
A point of interest within a city, classified by a category.
ColumnTypeConstraints
idbigint unsignedPK, auto-increment
city_idbigint unsignedFK → cities.id, cascade delete
category_idbigint unsignedFK → categories.id, cascade delete
namevarchar
descriptiontext
addressvarchar
latitudedecimal(10,7)nullable
longitudedecimal(10,7)nullable
created_attimestamp
updated_attimestamp
Eloquent: PlacebelongsTo(City), belongsTo(Category), hasMany(Event), morphMany(Image, 'imageable'), morphMany(Review, 'reviewable'), morphMany(Favorite, 'favorable')
A time-bound event anchored to a city. Optionally linked to a specific place — if the place is deleted the FK is set to null rather than cascading.
ColumnTypeConstraints
idbigint unsignedPK, auto-increment
city_idbigint unsignedFK → cities.id, cascade delete
place_idbigint unsignedFK → places.id, nullable, set null on delete
titlevarchar
descriptiontext
datetimestamp
created_attimestamp
updated_attimestamp
Eloquent: EventbelongsTo(City), belongsTo(Place), hasMany(EventRegistration), morphMany(Image, 'imageable'), morphMany(Review, 'reviewable'), morphMany(Favorite, 'favorable')
Join table between users and events. A unique constraint on (user_id, event_id) prevents duplicate registrations.
ColumnTypeConstraints
idbigint unsignedPK, auto-increment
user_idbigint unsignedFK → users.id, cascade delete
event_idbigint unsignedFK → events.id, cascade delete
created_attimestamp
updated_attimestamp
Unique index: (user_id, event_id)Eloquent: EventRegistrationbelongsTo(User), belongsTo(Event)
Stores any favorited item for a user. The favorable_type / favorable_id pair resolves to a Place, Event, or City. A unique constraint prevents saving the same item twice.
ColumnTypeConstraints
idbigint unsignedPK, auto-increment
user_idbigint unsignedFK → users.id, cascade delete
favorable_typevarcharEloquent morph type (e.g. App\Models\Place)
favorable_idbigint unsignedPK of the related model
created_attimestamp
updated_attimestamp
Unique index: (user_id, favorable_id, favorable_type)Eloquent: FavoritebelongsTo(User), morphTo('favorable')
User ratings and optional comments attached to places or events.
ColumnTypeConstraints
idbigint unsignedPK, auto-increment
user_idbigint unsignedFK → users.id, cascade delete
reviewable_typevarcharEloquent morph type
reviewable_idbigint unsignedPK of the related model
ratingtinyint unsigned1–5
commenttextnullable
created_attimestamp
updated_attimestamp
Eloquent: ReviewbelongsTo(User), morphTo('reviewable')
In-app notifications delivered to a specific user. Optionally linked to a source entity via nullable morphs (notifiable_type / notifiable_id). The is_read flag is a boolean cast.
ColumnTypeConstraints
idbigint unsignedPK, auto-increment
user_idbigint unsignedFK → users.id, cascade delete
notifiable_typevarcharnullable morph type
notifiable_idbigint unsignednullable morph PK
titlevarchar
messagetextnullable
is_readbooleandefault false
created_attimestamp
updated_attimestamp
Eloquent: NotificationbelongsTo(User), morphTo('notifiable')
One or more images attached to a city, place, or event via standard (non-nullable) morphs.
ColumnTypeConstraints
idbigint unsignedPK, auto-increment
urlvarchar
imageable_typevarcharEloquent morph type
imageable_idbigint unsignedPK of the related model
created_attimestamp
updated_attimestamp
Eloquent: ImagemorphTo('imageable')

Polymorphic relationships

Laravel’s polymorphic relationships allow a single table to belong to multiple model types using a _type / _id column pair. Tourify uses three:

Images (imageable)

Table: images
Columns: imageable_type, imageable_id
Targets: City, Place, Event

Favorites (favorable)

Table: favorites
Columns: favorable_type, favorable_id
Targets: Place, Event, City

Reviews (reviewable)

Table: reviews
Columns: reviewable_type, reviewable_id
Targets: Place, Event
The _type column stores the fully-qualified Eloquent class name (e.g. App\Models\Place). When loading a polymorphic relation, Laravel uses this string to determine which table to join. Example — querying a place’s reviews:
$place = Place::with('reviews.user')->find($id);

foreach ($place->reviews as $review) {
    // $review->reviewable_type === 'App\Models\Place'
    // $review->reviewable_id  === $place->id
    echo "{$review->user->name}: {$review->rating}/5";
}
Example — adding a favorite from the API:
POST /api/favorites
Authorization: Bearer <token>
Content-Type: application/json

{
  "favorable_type": "App\\Models\\Event",
  "favorable_id": 3
}

Entity relationship diagram

roles ──────< users >──────< favorites >── [Place|Event|City]
                │                │
                │                └──── [polymorphic: favorable]

                ├──< event_registrations >── events

                ├──< reviews >─── [polymorphic: reviewable]
                │                 targets: Place, Event

                └──< notifications

cities ────< places ──────< events
  │            │               │
  │            │               └── event_registrations
  │            │
  └── [images] └── [images, reviews, favorites]
  └── [images]     [polymorphic: imageable]
Cascade delete behavior:
Deleting a City cascades to all its Places and Events.
Deleting a Place cascades to its Reviews, Favorites, and Images (via ON DELETE CASCADE on the polymorphic FKs at the application level), and sets place_id to null on any associated Events rather than deleting them.
Deleting a User cascades to their Favorites, Reviews, Notifications, and EventRegistrations.

Build docs developers (and LLMs) love