CREATE TABLE users ( id_user INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, psw VARCHAR(255) NOT NULL, role_id INT DEFAULT NULL, employee_id INT NULL UNIQUE, is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (role_id) REFERENCES roles(id_role) ON DELETE SET NULL, FOREIGN KEY (employee_id) REFERENCES employees(id_employee) ON DELETE SET NULL);
Key Fields:
psw: Hashed password (use password_hash() in PHP)
is_active: Enable/disable accounts without deletion
role_id: Links to roles table
employee_id: Optional link to employee data
employees - Employee Information
Stores detailed employee personal information.
CREATE TABLE employees ( id_employee INT AUTO_INCREMENT PRIMARY KEY, first_name VARCHAR(50) NOT NULL, last_name VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL UNIQUE, birthdate DATE NOT NULL, phone VARCHAR(15) NOT NULL, address VARCHAR(255) NOT NULL, city VARCHAR(100) NOT NULL, country VARCHAR(100) NOT NULL, zip_code VARCHAR(10) NOT NULL, gender ENUM('male', 'female') NOT NULL, marital_status ENUM('single', 'married', 'divorced', 'widowed') NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
Separation of Concerns: Employee data is separate from user accounts to allow:
CREATE TABLE specie ( id_specie INT AUTO_INCREMENT PRIMARY KEY, category_id INT NOT NULL, specie_name VARCHAR(200) NOT NULL, FOREIGN KEY (category_id) REFERENCES category(id_category) ON DELETE CASCADE);
Examples:
Panthera leo melanochaita (African Lion)
Acinonyx jubatus raineyi (Cheetah)
Ailuropoda melanoleuca (Giant Panda)
animal_general - Basic Animal Info
Individual animal records.
CREATE TABLE animal_general ( id_animal_g INT AUTO_INCREMENT PRIMARY KEY, animal_name VARCHAR(50) NOT NULL, gender ENUM('male', 'female') NOT NULL, specie_id INT NOT NULL, FOREIGN KEY (specie_id) REFERENCES specie(id_specie) ON DELETE RESTRICT);
Design Note: ON DELETE RESTRICT prevents deleting a species if animals exist.
animal_full - Complete Animal Profile
Links animal to habitat, nutrition, and health.
CREATE TABLE animal_full ( id_full_animal INT AUTO_INCREMENT PRIMARY KEY, animal_g_id INT NOT NULL, habitat_id INT NULL, nutrition_id INT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (animal_g_id) REFERENCES animal_general(id_animal_g) ON DELETE CASCADE, FOREIGN KEY (habitat_id) REFERENCES habitats(id_habitat) ON DELETE SET NULL, FOREIGN KEY (nutrition_id) REFERENCES nutrition(id_nutrition) ON DELETE SET NULL);
Relationships:
One-to-one with animal_general
Many-to-one with habitats
Many-to-one with nutrition
animal_clicks - View Statistics
Tracks animal page views for analytics.
CREATE TABLE animal_clicks ( id_click INT AUTO_INCREMENT PRIMARY KEY, animal_g_id INT NOT NULL, year SMALLINT NOT NULL, month TINYINT NOT NULL CHECK (month BETWEEN 1 AND 12), click_count INT NOT NULL DEFAULT 0, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (animal_g_id) REFERENCES animal_general(id_animal_g) ON DELETE CASCADE, UNIQUE INDEX idx_animal_month_year (animal_g_id, year, month));
Usage: Increment click_count when an animal’s detail page is viewed.Cleanup: The 07_cleanup.sql script removes data older than 12 months.
CREATE TABLE service_logs ( id_service_log INT AUTO_INCREMENT PRIMARY KEY, service_id INT NOT NULL, changed_by INT NOT NULL, action ENUM('create', 'update', 'delete') NOT NULL, field_name VARCHAR(50) NULL, previous_value TEXT NULL, new_value TEXT NULL, change_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (service_id) REFERENCES services(id_service) ON DELETE CASCADE, FOREIGN KEY (changed_by) REFERENCES users(id_user) ON DELETE CASCADE);
opening - Opening Hours
Zoo schedule configuration.
CREATE TABLE opening ( id_opening INT AUTO_INCREMENT PRIMARY KEY, time_slot ENUM('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday') NOT NULL, opening_time TIME NOT NULL, closing_time TIME NOT NULL, status ENUM('open', 'closed') NOT NULL DEFAULT 'open', updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE media ( id_media INT AUTO_INCREMENT PRIMARY KEY, media_path VARCHAR(2048) NOT NULL, -- Mobile media_path_medium VARCHAR(2048), -- Tablet media_path_large VARCHAR(2048), -- Desktop media_type ENUM('image', 'video', 'audio') NOT NULL, description VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
Responsive Images: Three sizes for optimal performance on all devices.
media_relations - Polymorphic Relationships
Links media to any table using a polymorphic pattern.
CREATE TABLE media_relations ( id_relation INT AUTO_INCREMENT PRIMARY KEY, media_id INT NOT NULL, related_table VARCHAR(50) NOT NULL, -- 'services', 'habitats', 'heroes', etc. related_id INT NOT NULL, -- ID in the related table usage_type VARCHAR(100), -- 'main', 'thumbnail', 'gallery', etc. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (media_id) REFERENCES media(id_media) ON DELETE CASCADE);
Example Query:
-- Get all images for a serviceSELECT m.* FROM media mJOIN media_relations mr ON m.id_media = mr.media_idWHERE mr.related_table = 'services' AND mr.related_id = 103;
heroes - Page Heroes
Hero sections for pages.
CREATE TABLE heroes ( id_hero INT AUTO_INCREMENT PRIMARY KEY, hero_title VARCHAR(100) NOT NULL, hero_subtitle VARCHAR(100), page_name ENUM('home', 'about', 'services', 'habitats', 'animals') NOT NULL, habitat_id INT NULL, has_sliders BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY unique_page_hero (page_name, habitat_id), FOREIGN KEY (habitat_id) REFERENCES habitats(id_habitat) ON DELETE CASCADE);
Flexible Design: Can be page-specific or habitat-specific.
slides - Carousel Slides
Carousel content for heroes.
CREATE TABLE slides ( id_slide INT AUTO_INCREMENT PRIMARY KEY, hero_id INT NOT NULL, title_caption VARCHAR(255) NOT NULL, description_caption TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (hero_id) REFERENCES heroes(id_hero) ON DELETE CASCADE);
bricks - Content Blocks
Reusable content sections.
CREATE TABLE bricks ( id_brick INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(100) NOT NULL, description TEXT NOT NULL, link VARCHAR(255), page_name ENUM('home', 'about', 'services', 'habitats', 'animals', 'contact') NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE testimonials ( id_testimonial INT AUTO_INCREMENT PRIMARY KEY, pseudo VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, message TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, rating TINYINT UNSIGNED NOT NULL CHECK (rating BETWEEN 1 AND 5), status ENUM('pending', 'validated', 'rejected') DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, validated_at TIMESTAMP NULL DEFAULT NULL, validated_by INT DEFAULT NULL, FOREIGN KEY (validated_by) REFERENCES users(id_user) ON DELETE SET NULL) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Moderation Workflow:
Visitor submits testimonial (status: pending)
Employee reviews and validates/rejects
Only validated testimonials appear publicly
form_contact - Contact Form Submissions
Contact form messages.
CREATE TABLE form_contact ( id_form INT AUTO_INCREMENT PRIMARY KEY, ff_name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, fl_name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, f_email VARCHAR(100) NOT NULL, f_subject VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, f_message TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, f_sent_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, email_sent BOOLEAN DEFAULT FALSE) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Email Queue: email_sent flag tracks if the message was emailed to the zoo.Indexes:
Optimization indexes defined in 03_constraints.sql:
-- Prevent duplicate click recordsCREATE UNIQUE INDEX idx_animal_month_year ON animal_clicks (animal_g_id, year, month);-- Speed up date range queriesCREATE INDEX idx_year_month ON animal_clicks (year, month);-- Contact form queriesCREATE INDEX idx_sent_date ON form_contact (f_sent_date);CREATE INDEX idx_email ON form_contact (f_email);