form_month()

function form_month(string $name, ?string $value = null, array $attributes = []): string

Description

Generates an HTML month input field with a native browser month picker. The input allows users to select a month and year, submitting data in YYYY-MM format.

Browser Display vs Submitted Format: Browsers display months according to user locale, but always submit in consistent YYYY-MM format that your PHP code can rely on.

Demonstration

Below is the native HTML5 month input rendered by form_month():

Parameters

ParameterTypeDescriptionDefaultRequired
$name string The name attribute for the input element N/A Yes
$value string|null The month value in YYYY-MM format (zero-padded) null No
$attributes array Additional HTML attributes as key-value pairs [] No

Return Value

TypeDescription
stringThe generated HTML month input element

Understanding the Attributes Array

The $attributes array accepts standard HTML input attributes. For month inputs, these are particularly useful:

AttributeDescriptionExample Value
min Earliest selectable month (YYYY-MM) '2025-01'
max Latest selectable month (YYYY-MM) '2025-12'
required Field must have a value true
readonly Prevent user editing true
disabled Disable the input true

Boolean Attributes: Pass true for boolean attributes like required, readonly, or disabled. This generates clean HTML5 syntax: <input required>

Month Format: Months must be zero-padded: 01 for January, 12 for December. The format is always YYYY-MM.

Example #1: Basic Month Input

PHP
public function create(): void {
    $data['form_location'] = BASE_URL . 'reports/create';
    $this->view('report_form', $data);
}

View file:

View File
<?php
echo form_open($form_location);
echo form_label('Report Month');
echo form_month('report_month');
echo form_submit('submit', 'Continue');
echo form_close();
?>

Output:

HTML
<input type="month" name="report_month">

Example #2: Month Input with Default Current Month

PHP
public function create(): void {
    $data['billing_month'] = post('billing_month', true);
    
    // Default to current month if not submitted
    if ($data['billing_month'] === '') {
        $data['billing_month'] = date('Y-m');
    }
    
    $data['form_location'] = BASE_URL . 'invoices/create';
    $this->view('invoice_form', $data);
}

View file:

View File
<?php
echo form_open($form_location);
echo form_label('Billing Month');
echo form_month('billing_month', $billing_month);
echo form_submit('submit', 'Create Invoice');
echo form_close();
?>

The example above shows setting the current month as a default value using date('Y-m') which automatically zero-pads the month.

Form Repopulation: After validation errors, use post('field_name', true) in the controller to fetch the submitted value. This returns an empty string if no value was submitted.

Example #3: Financial Reporting System

PHP
public function generate_report(): void {
    $data['report_month'] = post('report_month', true);
    
    // Set constraints: can only generate reports for past 12 months
    $current_date = new DateTime();
    $data['max_month'] = $current_date->format('Y-m');
    
    $min_date = clone $current_date;
    $min_date->modify('-12 months');
    $data['min_month'] = $min_date->format('Y-m');
    
    $data['form_location'] = BASE_URL . 'reports/submit';
    $this->view('report_form', $data);
}

public function submit(): void {
    $this->validation->set_rules('report_month', 'report month', 'required|valid_month');
    
    if ($this->validation->run() === true) {
        $report_month = post('report_month', true);
        
        // Generate report for selected month
        $report_data = $this->generate_monthly_data($report_month);
        
        set_flashdata('Report generated for ' . $report_month);
        redirect('reports/view/' . $report_month);
    } else {
        $this->generate_report();
    }
}

private function generate_monthly_data(string $month): array {
    // Parse month: 2025-12 becomes year=2025, month=12
    list($year, $month_num) = explode('-', $month);
    
    $sql = "SELECT * FROM sales 
            WHERE YEAR(sale_date) = :year 
            AND MONTH(sale_date) = :month";
    
    return $this->db->query_bind($sql, [
        'year' => $year,
        'month' => $month_num
    ], 'array');
}

View file:

View File
<?php
echo form_open($form_location);

echo form_label('Report Month');
$attrs = [
    'min' => $min_month,
    'max' => $max_month,
    'required' => true
];
echo form_month('report_month', $report_month, $attrs);

echo form_submit('submit', 'Generate Report');
echo form_close();
?>

The example above demonstrates a financial reporting system where users can only generate reports for the past 12 months. The DateTime object makes month calculations clean and reliable.

Example #4: Create/Update Pattern for Subscriptions

PHP
public function create(): void {
    $update_id = segment(3, 'int');
    
    if ($update_id > 0 && REQUEST_TYPE === 'GET') {
        // Editing existing record
        $record = $this->db->get_where($update_id, 'subscriptions');
        $data['customer_name'] = $record->customer_name;
        $data['billing_month'] = $record->billing_month; // Already in YYYY-MM format
    } else {
        // New record or validation error
        $data['customer_name'] = post('customer_name', true);
        $data['billing_month'] = post('billing_month', true);
    }
    
    $data['form_location'] = BASE_URL . 'subscriptions/submit/' . $update_id;
    $this->view('subscription_form', $data);
}

public function submit(): void {
    $update_id = segment(3, 'int');
    
    $this->validation->set_rules('customer_name', 'customer name', 'required');
    $this->validation->set_rules('billing_month', 'billing month', 'required|valid_month');
    
    if ($this->validation->run() === true) {
        $data['customer_name'] = post('customer_name', true);
        $data['billing_month'] = post('billing_month', true);
        
        if ($update_id > 0) {
            $this->db->update($update_id, $data, 'subscriptions');
            set_flashdata('Subscription updated successfully');
        } else {
            $this->db->insert($data, 'subscriptions');
            set_flashdata('Subscription created successfully');
        }
        
        redirect('subscriptions/manage');
    } else {
        $this->create();
    }
}

View file:

View File
<?php
echo form_open($form_location);

echo form_label('Customer Name');
echo form_input('customer_name', $customer_name, ['required' => true]);

echo form_label('Billing Month');
echo form_month('billing_month', $billing_month, ['required' => true]);

echo form_submit('submit', 'Save Subscription');
echo form_close();
?>

The example above demonstrates the standard create/update pattern with a month field. No conversion is needed between the form and database because the YYYY-MM format can be stored directly in a VARCHAR column.

Type-Casting Segments: Always use segment(3, 'int') when expecting numeric IDs. This prevents type-related bugs and improves code clarity.

Example #5: Budget Planning with Future Months

PHP
public function plan_budget(): void {
    $data['budget_month'] = post('budget_month', true);
    
    // Allow planning for next 12 months
    $current_date = new DateTime();
    $data['min_month'] = $current_date->format('Y-m');
    
    $max_date = clone $current_date;
    $max_date->modify('+12 months');
    $data['max_month'] = $max_date->format('Y-m');
    
    $data['form_location'] = BASE_URL . 'budgets/submit';
    $this->view('budget_form', $data);
}

View file:

View File
<?php
echo form_open($form_location);

echo form_label('Budget Month');
$attrs = [
    'min' => $min_month,
    'max' => $max_month,
    'required' => true
];
echo form_month('budget_month', $budget_month, $attrs);

echo form_label('Budget Amount');
echo form_number('budget_amount', $budget_amount, ['required' => true, 'min' => 0, 'step' => 0.01]);

echo form_submit('submit', 'Save Budget');
echo form_close();
?>

The example above demonstrates budget planning where users can create budgets for the next 12 months. The DateTime object makes month calculations straightforward.

Database Storage: Store month values in a VARCHAR(7) column in YYYY-MM format. This keeps the data human-readable and makes it easy to query by year or month using string functions or database date functions.