02 β Birinchi bot: /start va echo¶
β¬ οΈ Oldingi: 01 β Telegram bot va Nutgram bilan tanishuv Β· π README Β· Keyingi: 03 β Handlerlar va routing β‘οΈ
Bu bobda: birinchi ishlaydigan botni noldan yig'amiz. Loyiha papkasini ochamiz,
composer require nutgram/nutgrambilan kutubxonani o'rnatamiz vaindex.phpyozamiz:new Nutgram($token),/startbuyrug'iga javob (onCommand), istalgan matnni qaytaradigan echo (onMessage), va botni ishga tushiradigan$bot->run()(long-polling). Tokenni kodga yozmaymiz β uni.envfaylidan (yokigetenv) o'qiymiz va.gitignore'ga qo'shamiz. Bob oxirida β mashqlar va yechimlar.Halollik eslatmasi: botning mantig'i (handlerlar to'g'ri ulanishi va to'g'ri javob qaytarishi) shu yerda OFFLINE β
Nutgram::fake()(FakeNutgram) bilan, haqiqatan ishga tushirib tekshirildi (PHP 8.4, Nutgram 4.46, PHPUnit 12.5:/start,/helpva echo β hammasi PASS). Jonli$bot->run()esa real Telegram token va internet talab qiladi β uni siz o'z botingizda ishga tushirasiz; bu qism bu yerda illustrativ deb belgilanadi (soxta "xabar yetdi" yozilmaydi).
Tayyorgarlik: nima kerak?¶
Birinchi botni qurishdan oldin uchta narsa kerak:
- PHP 8.2+ (bu kitobda 8.4). Tekshirish: terminalda
php -v. - Composer β PHP'ning paket menejeri (
composer -Vbilan tekshiring). Agar yo'q bo'lsa: getcomposer.org. - Bot tokeni β buni 01-bobda @BotFather'dan
/newbotorqali oldingiz. Token shunday ko'rinishda bo'ladi:8123456789:AAH-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
PHP, composer, sinf, namespace va closure tushunchalari sizga tanish deb faraz qilamiz. Agar eslatish kerak bo'lsa β PHP qo'llanmasiga qarang. Bu yerda biz faqat Telegram/Nutgram'ga xos qismni batafsil tushuntiramiz.
Loyiha papkasini tayyorlash¶
Bo'sh papka ochamiz va Nutgram'ni o'rnatamiz. Terminalda (PowerShell yoki bash β farqi yo'q):
composer require ikki ishni qiladi:
composer.jsonfaylini yaratadi (loyihangizning bog'liqliklari ro'yxati);vendor/papkasini yaratib, unga Nutgram va uning bog'liqliklarini yuklab oladi.vendor/autoload.phpβ bu sinflarni avtomatik yuklaydigan fayl, uni har doim ulaymiz.
Natijada composer.json taxminan shunday bo'ladi:
Loyiha tuzilishi quyidagicha bo'ladi:
| Fayl/papka | Vazifasi |
|---|---|
composer.json |
Bog'liqliklar ro'yxati (Nutgram) |
index.php |
Bot kodi β biz yozamiz |
.env |
Maxfiy token (kodga emas, shu yerga) |
vendor/ |
Composer o'rnatgan kutubxonalar (git'ga kiritilmaydi) |
.gitignore |
vendor/ va .env'ni git'dan yashiradi |
Tokenni xavfsiz saqlash (.env)¶
Tokenni hech qachon kod ichiga yozmang. Token β bu botingizning paroli: uni qo'lga kiritgan har kim sizning botingiz nomidan xabar yubora oladi. Agar token kodda bo'lsa va siz kodni GitHub'ga yuborsangiz β token ochiq qoladi.
Yechim: tokenni alohida .env fayliga yozamiz va uni .gitignore'ga qo'shamiz.
.env faylini yarating:
.gitignore faylini yarating (token va kutubxonalar git'ga tushmasligi uchun):
.env faylini PHP'da o'qishning ikki yo'li bor:
1-usul β vlucas/phpdotenv paketi (tavsiya etiladi). Bu paket .env faylini o'qib, qiymatlarni getenv() orqali kirish mumkin qiladi:
2-usul β operatsion tizim muhit o'zgaruvchisi. Agar .env paketi ishlatmasangiz, tokenni terminalda muhit o'zgaruvchisi sifatida o'rnatib, getenv() bilan o'qiysiz:
# PowerShell:
$env:BOT_TOKEN = "8123456789:AAH-..."
# bash / Linux:
export BOT_TOKEN="8123456789:AAH-..."
Bu bobda biz getenv()'ni ishlatamiz (qo'shimcha paketsiz). Kod token yo'qligini ham xushmuomalalik bilan tekshiradi.
new Nutgram($token) β bot obyekti¶
Endi index.php yozamiz. Eng birinchi qadam β Nutgram obyektini yaratish. Bu obyekt β butun botning markazi: handlerlarni ro'yxatga olamiz va u orqali Telegram'ga xabar yuboramiz.
<?php
require __DIR__ . '/vendor/autoload.php';
use SergiX44\Nutgram\Nutgram;
$token = getenv('BOT_TOKEN');
if (!$token) {
exit("Xato: BOT_TOKEN o'rnatilmagan. Avval tokenni muhit o'zgaruvchisiga qo'ying.\n");
}
$bot = new Nutgram($token);
Bu yerda:
require __DIR__ . '/vendor/autoload.php'β Composer autoloaderini ulaydi (sinflar avtomatik yuklanadi).use SergiX44\Nutgram\Nutgramβ Nutgram sinfining to'liq nomi (namespace). Endi qisqaNutgramdeb yozsak bo'ladi.new Nutgram($token)β bot obyektini yaratadi. Token noto'g'ri bo'lsa ham bu qator xato bermaydi (token faqat birinchi so'rovda Telegram'ga yuboriladi); shuning uchun token bor-yo'qligini o'zimiz tekshiramiz.
/start buyrug'iga javob β onCommand¶
Telegram'da / bilan boshlanadigan so'zlar β buyruqlar (commands). Eng muhimi /start: foydalanuvchi botni birinchi marta ochganda Telegram avtomatik shu buyruqni yuboradi.
Buyruqni qayta ishlash uchun onCommand ishlatamiz:
$bot->onCommand('start', function (Nutgram $bot) {
$bot->sendMessage('Salom! Men sizning birinchi botingizman. Menga istalgan matn yozing β qaytarib beraman.');
});
Tushuntirib o'tamiz:
onCommand('start', ...)β/startbuyrug'i kelganda ikkinchi argumentdagi closure (anonim funksiya) ishlaydi. Diqqat:/belgisini yozmaymiz β faqat'start'.- Closure'ga
Nutgram $botkeladi. Bu β o'sha bot obyekti; handler ichida u orqali javob yuboramiz. $bot->sendMessage('...')β joriy suhbatga matn yuboradi. Nutgram qaysi chatga yuborishni o'zi biladi (kelgan xabardan oladi), shuning uchunchat_idyozish shart emas.
Bir-ikkita buyruq ko'p uchraydi. Keling, /help ham qo'shamiz:
$bot->onCommand('help', function (Nutgram $bot) {
$bot->sendMessage("Buyruqlar:\n/start β boshlash\n/help β yordam\n\nIstalgan matn yozsangiz, men uni takrorlayman (echo).");
});
\n β yangi qator. Telegram xabarida bir nechta qator chiqarish uchun shunday yozamiz (qo'sh tirnoq "..." ichida \n ishlaydi, bir tirnoq '...' ichida β yo'q).
Echo β istalgan matnni qaytarish (onMessage)¶
Endi botimizni "echo" qilamiz: foydalanuvchi nima yozsa β botimiz o'shani qaytaradi. Buning uchun onMessage ishlatamiz β u istalgan xabar kelganda ishlaydi (matn, rasm, stiker β hammasi).
$bot->onMessage(function (Nutgram $bot) {
$text = $bot->message()?->text;
if ($text === null) {
$bot->sendMessage('Men hozircha faqat matnni qaytara olaman.');
return;
}
$bot->sendMessage("Siz yozdingiz: {$text}");
});
Bu yerda eng muhim narsa:
$bot->message()β kelgan xabar obyektini (Message) qaytaradi. Handler ichida$botorqali kontekstga (kim, qaysi chat, qanaqa xabar) kirasiz:$bot->message(),$bot->user(),$bot->chatId(),$bot->userId().$bot->message()?->textβ xabardagi matn. Null-safe operator?->muhim: agar foydalanuvchi rasm yoki stiker yuborsa,textnullbo'ladi (matn yo'q). Shuni tekshirib, xushmuomalalik bilan javob beramiz."Siz yozdingiz: {$text}"β qo'sh tirnoq ichida o'zgaruvchini{$text}deb joylash β bu string interpolation.
Tartib muhim: onCommand onMessagedan oldin¶
Nutgram handlerlarni ro'yxatga olingan tartibda tekshiradi va birinchi mosini ishga tushiradi (3-bobda routing'ni chuqurroq o'rganamiz). Shuning uchun onCommand('start')'ni onMessage'dan oldin yozamiz. Aks holda /start ham oddiy matn sifatida echo bo'lib qaytadi.
Mana to'liq oqim:
$bot->run() β botni ishga tushirish (long-polling)¶
Hamma handlerlar ulangach, eng oxirida botni ishga tushiramiz:
$bot->run() β bu long-polling rejimida ishlaydi: bot doimiy ravishda Telegram serveridan "menga yangi xabar bormi?" deb so'rab turadi (getUpdates), kelgan har bir yangilanishni mos handlerga uzatadi va yana so'raydi. Bu β cheksiz tsikl; dastur to'xtamaguncha ishlaydi (Ctrl+C bilan to'xtatasiz).
Long-polling β rivojlanish (dev) uchun eng oson usul: public server ham, HTTPS ham, domen ham kerak emas. Faqat internet va token kifoya. (Production uchun ko'pincha webhook ishlatiladi β buni 13-bobda ko'ramiz.)
To'liq index.php¶
Hamma qismni birlashtiramiz. Bu β to'liq, ishlaydigan birinchi botingiz:
<?php
require __DIR__ . '/vendor/autoload.php';
use SergiX44\Nutgram\Nutgram;
$token = getenv('BOT_TOKEN');
if (!$token) {
exit("Xato: BOT_TOKEN o'rnatilmagan.\n");
}
$bot = new Nutgram($token);
// 1) /start buyrug'i
$bot->onCommand('start', function (Nutgram $bot) {
$bot->sendMessage('Salom! Men sizning birinchi botingizman. Menga istalgan matn yozing β qaytarib beraman.');
});
// 2) /help buyrug'i
$bot->onCommand('help', function (Nutgram $bot) {
$bot->sendMessage("Buyruqlar:\n/start β boshlash\n/help β yordam\n\nIstalgan matn yozsangiz, men uni takrorlayman (echo).");
});
// 3) Echo β buyruq bo'lmagan istalgan matnni qaytaradi
$bot->onMessage(function (Nutgram $bot) {
$text = $bot->message()?->text;
if ($text === null) {
$bot->sendMessage('Men hozircha faqat matnni qaytara olaman.');
return;
}
$bot->sendMessage("Siz yozdingiz: {$text}");
});
// 4) Botni ishga tushirish (long-polling)
$bot->run();
Ishga tushirish:
# Avval tokenni muhit o'zgaruvchisiga qo'ying:
# PowerShell: $env:BOT_TOKEN = "..."
# bash: export BOT_TOKEN="..."
php index.php
Endi Telegram'da botingizga /start yoki istalgan matn yuboring β javob kelishi kerak. To'xtatish: Ctrl+C.
Halollik: yuqoridagi
php index.phpqadami illustrativ β u haqiqiy token va internet talab qiladi, shuning uchun bu kitobni yozish jarayonida jonli ishga tushirilmadi. Ammo botning mantig'i quyida ko'rsatilganidek OFFLINE haqiqatan tekshirildi va o'tdi.
Tekshirish: botni internet va tokensiz sinash (FakeNutgram)¶
Bizga savol tug'iladi: handlerlar to'g'ri ulanganini, /start to'g'ri javob qaytarishini β token va internetsiz, telefonni qo'lga olmasdan qanday tekshiramiz?
Javob: Nutgram'da Nutgram::fake() bor β bu soxta bot (FakeNutgram). U Telegram'ga umuman ulanmaydi; o'rniga siz "kelgan xabar"ni qo'lda beraysiz va bot qanday javob qaytarganini tekshirasiz. Internet ham, token ham kerak emas β bu sof mantiq sinovi.
Buning uchun test kutubxonasi kerak:
Mantiqni qayta ishlatish uchun handlerlarni alohida funksiyaga ajratamiz (bot_logic.php):
<?php
declare(strict_types=1);
use SergiX44\Nutgram\Nutgram;
function registerHandlers(Nutgram $bot): void
{
$bot->onCommand('start', function (Nutgram $bot) {
$bot->sendMessage('Salom! Men sizning birinchi botingizman. Menga istalgan matn yozing β qaytarib beraman.');
});
$bot->onMessage(function (Nutgram $bot) {
$text = $bot->message()?->text;
if ($text === null) {
$bot->sendMessage('Men hozircha faqat matnni qaytara olaman.');
return;
}
$bot->sendMessage("Siz yozdingiz: {$text}");
});
}
index.php esa shu funksiyani chaqiradi: registerHandlers($bot); $bot->run();.
Endi test (EchoBotTest.php):
<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use SergiX44\Nutgram\Nutgram;
require_once __DIR__ . '/bot_logic.php';
final class EchoBotTest extends TestCase
{
private function makeBot(): Nutgram
{
$bot = Nutgram::fake(); // soxta bot β internet/token kerak emas
registerHandlers($bot); // o'sha haqiqiy handlerlar
return $bot;
}
public function test_start_javob_beradi(): void
{
$bot = $this->makeBot();
$bot->hearText('/start')->reply(); // "/start" kelgandek qil
$bot->assertReplyText('Salom! Men sizning birinchi botingizman. Menga istalgan matn yozing β qaytarib beraman.');
}
public function test_echo_matnni_qaytaradi(): void
{
$bot = $this->makeBot();
$bot->hearText('Salom dunyo')->reply();
$bot->assertReplyText('Siz yozdingiz: Salom dunyo');
}
}
Tushuntirib o'tamiz:
Nutgram::fake()β soxta bot obyekti. Telegram'ga so'rov yubormaydi; barcha "yuborilgan" xabarlarni xotirada saqlaydi.$bot->hearText('/start')β go'yo foydalanuvchi/startyozgandek qilib soxta yangilanish yaratadi;->reply()esa botga uni qayta ishlatadi (mos handlerni ishga tushiradi).$bot->assertReplyText('...')β bot oxirgi qanaqa matn yuborganini tekshiradi. Mos kelmasa β test FAIL. (Boshqa foydali tekshiruvlar:assertReplyMessage,assertCalled,assertRaw.)
Ishga tushirish:
Natija (haqiqatan ishlatib ko'rildi β PHP 8.4, Nutgram 4.46.0, PHPUnit 12.5):
PHPUnit 12.5.29 by Sebastian Bergmann and contributors.
.. 2 / 2 (100%)
Time: 00:00.075, Memory: 8.00 MB
OK (2 tests, 4 assertions)
Demak handlerlar to'g'ri ulangan va to'g'ri javob qaytaradi β buni Telegram'ga ulanmasdan ham aniq bilamiz. Testlash mavzusiga 16-bobda batafsil qaytamiz.
Mashqlar¶
Oson¶
- Yangi
my-botpapkasini oching vacomposer require nutgram/nutgrambilan Nutgram'ni o'rnating.vendor/papkasi vacomposer.jsonpaydo bo'lganini tasdiqlang. .envfayli va.gitignoreyarating..gitignore'ga/vendor/va.envqo'shing. Nega tokenni.gitignore'ga qo'shish muhimligini bir jumlada yozing.- Yuqoridagi
index.php'ga/aboutbuyrug'ini qo'shing: u bot haqida qisqa ma'lumot yuborsin (masalan bot nomi va muallifi). - Echo javobini o'zgartiring: matn oldidan emoji qo'shing β
"π {$text}". /helpjavobini\nbilan uch qatorli qilib yozing: birinchi qator β sarlavha, keyin ikkita buyruq.getenv('BOT_TOKEN')nullqaytarsa, kod qanday xabar chiqarishini tushuntiring. Tokenni o'rnatmasdanphp index.phpishlatib, natijani ko'ring.
O'rta¶
onMessageichida: agar matnsalom(kichik harf) bo'lsa β"Va alaykum salom!"deb javob bering; aks holda odatdagi echo qiling. (Maslahat:strtolower($text)bilan solishtiring.)- Echo javobiga matn uzunligini qo'shing:
"Siz yozdingiz: {$text} ({mb_strlen($text)} ta belgi)".mb_strlen'dan negastrleno'rniga foydalanish kerakligini izohlang (o'zbek/kirill harflari). - Handlerlarni
index.php'danbot_logic.phpdagiregisterHandlers()funksiyasiga ko'chiring.index.phpfaqat tokenni o'qib,registerHandlers($bot)va$bot->run()chaqirsin. - FakeNutgram bilan yangi test yozing:
/helpyuborilganda javob ichida/startmatni borligini tekshiring. (Maslahat:assertReplyTextto'liq mos kelishni talab qiladi β to'liq matnni yozing yokiassertReplyMessagebilan qisman tekshiring.) - Foydalanuvchi rasm yuborganda (matn yo'q) bot
"Men hozircha faqat matnni qaytara olaman."deyishini ta'minlang.$bot->message()?->text === nullshartini tekshiruvchi test yozishga harakat qiling. composer.json'da"scripts"bo'limi qo'shing:"start": "php index.php"va"test": "phpunit". Endicomposer startvacomposer testishlashini tekshiring.
Qiyin¶
- Handlerlar tartibini ataylab buzing:
onMessage'nionCommand('start')dan oldin qo'ying./startyuborganda nima bo'ladi? Nega? FakeNutgram testi bilan bu xatti-harakatni isbotlang, so'ng to'g'rilang. - Echo botni "aks-sado kuchaytirgich"ga aylantiring: foydalanuvchi
3| Salomdeb yozsa (raqam,|, matn), botSalomni 3 marta yangi qatordan yuborsin. Noto'g'ri formatga (|yo'q yoki raqam emas) xushmuomala xato javob bering. MantiqniregisterHandlersichiga joylang va kamida 3 ta FakeNutgram testi bilan qoplang (to'g'ri format, raqamsiz,|siz).
Yechimlar
Oson 3 β /about buyrug'i:
$bot->onCommand('about', function (Nutgram $bot) {
$bot->sendMessage("Echo bot v1.0\nMuallif: Oqil Imomnazarov\nNutgram bilan qurilgan.");
});
Oson 4 β emojili echo:
$bot->onMessage(function (Nutgram $bot) {
$text = $bot->message()?->text;
if ($text === null) return;
$bot->sendMessage("π {$text}");
});
Oson 6 β token yo'qligi: getenv('BOT_TOKEN') token o'rnatilmagan bo'lsa false qaytaradi. if (!$token) sharti false'ni ushlaydi va exit(...) xabar chiqarib dasturni to'xtatadi β bu new Nutgram()'ga null o'tib, keyin tushunarsiz xatoga uchrashdan ko'ra ancha aniqroq.
O'rta 1 β "salom"ga maxsus javob:
$bot->onMessage(function (Nutgram $bot) {
$text = $bot->message()?->text;
if ($text === null) {
$bot->sendMessage('Men hozircha faqat matnni qaytara olaman.');
return;
}
if (strtolower(trim($text)) === 'salom') {
$bot->sendMessage('Va alaykum salom!');
return;
}
$bot->sendMessage("Siz yozdingiz: {$text}");
});
O'rta 2 β uzunlik bilan:
mb_strlen β multibayt-xabardor: o'zbek lotin diakritikasi yoki kirill/emoji belgilarini bittadan sanaydi. strlen esa baytlarni sanaydi, shuning uchun Salom bo'lmagan UTF-8 belgilar uchun noto'g'ri (kattaroq) son chiqaradi.
O'rta 6 β composer scripts:
{
"require": { "nutgram/nutgram": "^4.46" },
"require-dev": { "phpunit/phpunit": "^12.5" },
"scripts": {
"start": "php index.php",
"test": "phpunit"
}
}
Qiyin 1 β tartib muammosi: agar onMessage birinchi ro'yxatga olingan bo'lsa, Nutgram /start kelganda birinchi mos handlerni ishlatadi β bu onMessage (u istalgan xabarni ushlaydi). Natijada /start echo bo'lib "Siz yozdingiz: /start" qaytadi va onCommand('start') umuman ishlamaydi. Tekshiruvchi test:
public function test_tartib_muhim(): void
{
$bot = Nutgram::fake();
// ATAYLAB noto'g'ri tartib:
$bot->onMessage(fn(Nutgram $bot) => $bot->sendMessage('Siz yozdingiz: ' . $bot->message()?->text));
$bot->onCommand('start', fn(Nutgram $bot) => $bot->sendMessage('Salom!'));
$bot->hearText('/start')->reply();
$bot->assertReplyText('Siz yozdingiz: /start'); // echo "yutdi", start emas
}
To'g'rilash: onCommand('start')'ni onMessagedan oldin yozing.
Qiyin 2 β aks-sado kuchaytirgich:
bot_logic.php:
<?php
declare(strict_types=1);
use SergiX44\Nutgram\Nutgram;
function registerHandlers(Nutgram $bot): void
{
$bot->onMessage(function (Nutgram $bot) {
$text = $bot->message()?->text;
if ($text === null) {
$bot->sendMessage('Men hozircha faqat matnni qaytara olaman.');
return;
}
// Format: "N| matn" (masalan "3| Salom")
if (!str_contains($text, '|')) {
$bot->sendMessage("Format: <son>| <matn>\nMasalan: 3| Salom");
return;
}
[$nRaw, $msg] = explode('|', $text, 2);
$n = trim($nRaw);
$msg = trim($msg);
if (!ctype_digit($n) || (int)$n < 1 || (int)$n > 10) {
$bot->sendMessage("Birinchi qism 1 dan 10 gacha son bo'lishi kerak.");
return;
}
$lines = array_fill(0, (int)$n, $msg);
$bot->sendMessage(implode("\n", $lines));
});
}
Testlar (EchoTest.php):
<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use SergiX44\Nutgram\Nutgram;
require_once __DIR__ . '/bot_logic.php';
final class EchoTest extends TestCase
{
private function bot(): Nutgram
{
$bot = Nutgram::fake();
registerHandlers($bot);
return $bot;
}
public function test_togri_format(): void
{
$bot = $this->bot();
$bot->hearText('3| Salom')->reply();
$bot->assertReplyText("Salom\nSalom\nSalom");
}
public function test_raqamsiz(): void
{
$bot = $this->bot();
$bot->hearText('x| Salom')->reply();
$bot->assertReplyText("Birinchi qism 1 dan 10 gacha son bo'lishi kerak.");
}
public function test_quvursiz(): void
{
$bot = $this->bot();
$bot->hearText('Salom')->reply();
$bot->assertReplyText("Format: <son>| <matn>\nMasalan: 3| Salom");
}
}
Bu yechim β sof mantiq, shuning uchun FakeNutgram bilan to'liq, internet/tokensiz tekshiriladi.
β¬ οΈ Oldingi: 01 β Telegram bot va Nutgram bilan tanishuv Β· π README Β· Keyingi: 03 β Handlerlar va routing β‘οΈ