تخطَّ إلى المحتوى
PHP Ecosystem
Explore

Remote data

هذا المحتوى غير متوفر بلغتك بعد.

Select2’s full build supports AJAX searches and paginated results through clientOptions.ajax. The widget does not create an endpoint or implement authorization. The endpoint recipe provides a small read-only endpoint without a database.

In a view with $form, $model, and a validated existing city ID and label:

use yii\helpers\Url;
use yii\web\JsExpression;
use Yii2\Extensions\Select2\Select2;
echo $form
->field($model, 'city')
->widget(
Select2::class,
[
'items' => ['2' => 'Madrid'],
'options' => ['prompt' => ''],
'clientOptions' => [
'placeholder' => 'Search cities',
'allowClear' => true,
'minimumInputLength' => 1,
'ajax' => [
'url' => Url::to(['city/search']),
'dataType' => 'json',
'delay' => 250,
'data' => new JsExpression(
'function (params) { return {q: params.term || "", page: params.page || 1}; }'
),
],
],
]
);

The example ID and label must be replaced by the current model’s authorized record in an application. AJAX cannot fetch the label of an existing value merely from $model->city; include it in items on initial render and on validation failure. For multiple preselected values, include all selected IDs and labels.

Return JSON with this shape, using string IDs and plain-text labels:

{
"results": [{ "id": "2", "text": "Madrid" }],
"pagination": { "more": false }
}

Filter on the server and bound the page size. Preserve page and calculate pagination.more against the filtered dataset. Query through Yii’s parameterized query APIs; do not concatenate the search term into SQL. Apply the application’s normal authentication and access filters, and validate query types and lengths. The endpoint recipe uses fixed public sample data.

Keep CSRF enabled for POST endpoints. A GET search should only read data. Handle network errors with appropriate HTTP status codes and allow a subsequent search to retry; never return success with an empty list to hide a server failure. Select2 displays its translated loading error for a failed request.

If an API uses another JSON shape, adapt it with a JsExpression in ajax.processResults. If replacing ajax.transport, return an object with an abort method and call the success/failure callbacks correctly so stale requests can be cancelled. See the official AJAX documentation.

Place this action in an application controller with the application’s access and HTTP verb filters. The fixed public sample data needs no database; replace it with an authorized dataset in a real application.

public function actionSearch(): \yii\web\Response
{
$query = \Yii::$app->request->get('q', '');
$page = \Yii::$app->request->get('page', '1');
if (
!is_string($query)
|| strlen($query) > 100
|| !is_scalar($page)
|| !ctype_digit((string) $page)
|| (int) $page < 1
|| (int) $page > 100
) {
throw new \yii\web\BadRequestHttpException('Provide a text query and a page between 1 and 100.');
}
$cities = [
'1' => 'Barcelona',
'2' => 'Madrid',
'3' => 'Malaga',
'4' => 'Manila',
'5' => 'Montreal',
'6' => 'Monterrey',
];
$rows = [];
foreach ($cities as $id => $text) {
if ($query === '' || stripos($text, $query) !== false) {
$rows[] = ['id' => (string) $id, 'text' => $text];
}
}
$size = 2;
return $this->asJson(
[
'results' => array_slice($rows, ((int) $page - 1) * $size, $size),
'pagination' => ['more' => (int) $page * $size < count($rows)],
],
);
}

Back to documentation