toSenior PHP
Видео номер 26
Телеграм бот на Laravel 10 и пакете Telegraph. Фреймворк Ларавел и библиотека Телеграф. Webhook

В видео подробно рассказывается об основных возможностях пакета Telegraph на котором создают ботов для Telegram в фреймворке Laravel. Сначала установим фреймворк на WSL, настроим подключение к базе SQLite, подключим на локалку домен DDNS через SSH, и создадим Webhook на Telegram. Далее будем создавать команды для телеграмм бота, пересылать и получать с сохранением фото, видео и файлы, создавать кнопки, клавиатуры и пр.



Использовано в видео:
===========================================================
composer create-project laravel/laravel:^10.0 bot  // устанавливаем фреймворк Ларавел 10
php artisan serve  // запускаем пхп сервер
-----------------------------------------------------------
sudo chown -R www-data:www-data /var/www  // даем доступы
-----------------------------------------------------------
sudo chmod -R 777 /var/www  // даем права
-----------------------------------------------------------
apt-get install libapache2-mod-php -y  // установленные ПХП библиотеки
apt-get install php-mysqli -y
apt-get install php-pdo php-sqlite3
apt-get install php-cli -y
apt-get install php-common -y
apt-get install php-zip -y
apt-get install php-gd -y
apt-get install php-mbstring -y
apt-get install php-curl -y
apt-get install php-xml -y
apt-get install php-bcmath -y
apt-get install php-dom -y
-----------------------------------------------------------
composer require defstudio/telegraph  // устанавливаем телеграфф установил в папку с фремворком
php artisan vendor:publish --tag="telegraph-migrations"  // установил миграции
php artisan migrate  // накатываем миграции
php artisan vendor:publish --tag="telegraph-config" // создаем конфиг 
php artisan telegraph:new-bot  // далее вводим токен , потом имя бота 
ssh -R youruniquesubdomain:80:localhost:8000 serveo.net   // запускаем в отдельной консоли для получения адреса в сети дднс
php artisan telegraph:set-webhook  // запускаем вебхук в консоли 
===========================================================
Создаем свой обработчик и прокидывае путь в конфиге
-----------------------------------------------------------
<?php
namespace App\Http\Telegraph;
use DefStudio\Telegraph\Handlers\WebhookHandler;
use DefStudio\Telegraph\Facades\Telegraph;
use DefStudio\Telegraph\Keyboard\ReplyButton;
use DefStudio\Telegraph\Keyboard\ReplyKeyboard;
use DefStudio\Telegraph\Keyboard\Keyboard;
use DefStudio\Telegraph\Keyboard\Button;
use Illuminate\Support\Facades\Storage;
class Handler extends WebhookHandler
{
    public function start()  // название фунции соответствует команде в телеге /start
    {
		$this->reply("Привет новому пользователю");  // отправка текста
		//$this->chat->html("<i>Курсив</i>")->send();  //отправляем html
    }
}
----------------------------------------------------------
Отвечаем на неизвестную команду
----------------------------------------------------------
    protected function handleUnknownCommand($text): void
    {
        $this->chat->html("Я не понял команды: $text")->send();
    }
----------------------------------------------------------
Получаем текст и возвращаем обратно
----------------------------------------------------------
    protected function handleChatMessage($text): void
    {
        $this->chat->html($text)->send();
    }
----------------------------------------------------------
Создаем и убираем меню с командами
----------------------------------------------------------
    public function com()
    {
         Telegraph::registerBotCommands([
             'help' => 'вызов описания',
             'fas' => 'пожаловатся'
         ])->send();
       // Telegraph::unregisterBotCommands()->send();  // убираем меню
    }
    public function help()  
    {
        $this->reply('Описание команд...');  
    }
    public function fas()  
    {
        $this->reply("Жалоба принята!"); 
    }
---------------------------------------------------------
Создаем клавиатуру
---------------------------------------------------------
	    public function com()
    {
        Telegraph::message('Клавиатура')
            ->replyKeyboard(ReplyKeyboard::make()->buttons([
                ReplyButton::make('Текст'),
                ReplyButton::make('Отправить контакт')->requestContact(),
                ReplyButton::make('Отправить местоположение')->requestLocation(),
                ReplyButton::make('Создать опрос')->requestPoll(),
                ReplyButton::make('Создать тест')->requestQuiz(),
                ReplyButton::make('Запустить веб-приложение')->webApp('https://www.google.kz/'),
            ]))->send();
    }
    protected function handleChatMessage($text): void
    {
        if($text == 'Текст') $this->chat->html('Текст пришел')->send();
    }
---------------------------------------------------------
Убираем клавиатуру
---------------------------------------------------------
    public function com()
    {
        Telegraph::message('command received')
        ->removeReplyKeyboard()
        ->send();
    }
--------------------------------------------------------
Создаем кнопки которые вызывают фото, видео, файл
--------------------------------------------------------
	   public function but()
    {
        $this->chat
            ->message('сообщение с кнопками')
            ->keyboard(
                Keyboard::make()->buttons([
                    Button::make( 'Получаем фото  ')->action( 'feedback')->param('value', 1),
                    Button::make( 'Получаем фото 2')->action( 'feedback')->param('value', 2),
                    Button::make( 'Получаем видео ')->action( 'feedback')->param('value', 3),
                    Button::make( 'Получаем файл  ')->action( 'feedback')->param('value', 4),
                ])
            )->send();
    }
    public function feedback()   
    {
        $data = $this->data->get('value'); 
        if($data == 1)Telegraph::photo('data/foto.jpg')->send();   
        if($data == 2)Telegraph::photo(Storage::path('public/foto.jpg'))->send();  
        if($data == 3)Telegraph::video('data/video.mp4')->send(); 
        if($data == 4)Telegraph::document('data/file.txt')->send();  
    }
--------------------------------------------------------------------------	
Опрос, отвечает на /com
--------------------------------------------------------------------------
    public function com()
    {
        Telegraph::poll("На каком языке программируете")
    ->option('php')
    ->option('typescript')
    ->option('rust')
    ->validUntil(now()->addMinutes(5))
    ->send();
    }
--------------------------------------------------------------------------
Викторина , нужно угадать правильный ответ
--------------------------------------------------------------------------
    public function com()
    {
        Telegraph::quiz("Какой ваш любимый язык программирования?")
        ->option('php', correct: true)
        ->option('typescript')
        ->option('rust')
        ->explanation('Мы все любим php, не так ли?')
        ->validUntil(now()->addMinutes(5))
        ->send();
    }
======================================================	
Получаем фото, видео и файлы, сохраняем их
======================================================
Получаем всё сообщение в жсон файл который удобно форматировать
------------------------------------------------------
    protected function handleChatMessage($text): void
    {
        $photo = $this->message->toArray();
        file_put_contents('1.json', json_encode($photo));
        $this->chat->html($text)->send();
    }
------------------------------------------------------
Получаем файл
------------------------------------------------------
    protected function handleChatMessage($text): void
    {
        $id_document = $this->message->document()->id();
        $this->bot->store($id_document, 'bot');  
    }
------------------------------------------------------
Получаем видео
------------------------------------------------------
    protected function handleChatMessage($text): void
    {
        $id_video = $this->message->video()->id();
        $this->bot->store($id_video, 'bot');  // сохраняем на локалке,
    }
------------------------------------------------------
Сохраняем последнее (более качественное) фото из массива вариантов
------------------------------------------------------
    protected function handleChatMessage($text): void // метод приема всех сообщений
    {
         $photo = $this->message->photos()->toArray();  // получаем  в массив инфу о фото в с разными вариантами размеров
         $data = count($photo) - 1;   // считаем количество элементов массива
         $id_foto = $photo[$data]['id'];  // берем последнее айди фото из массива
         $this->bot->store($id_foto, Storage::path('bot/images'), 'name3-foto.jpg');  // сохраняем на локалке,
    }
------------------------------------------------------

Видео номер 25
Телеграм бот PHP + JS простые примеры, отправка и прием текста, фото, файлов, кнопок, клавиатуры.

В видео собрана коллекция простых примеров работы с телеграм ботом, сначала примеры выполненны в адресной строке браузера, то есть просто ссылкой будем получать и отправлять текст, файлы, фото и видео. Примеры даются на двух языках PHP и JS, сначала будем отправлять текст, кнопки, клавиатуру, фото, видео и файлы. Затем будем получать из бота текст, фото, видео, файлы. ВНИМАНИЕ, ПРИ РАБОТЕ В JS ВЫ ДЕЛАЕТЕ ДОСТУПНЫМ ТОКЕН БОТА И ПР., ПРИМЕРЫ ДАНЫ ДЛЯ ОБЩЕГО ПОНИМАНИЯ ПРИНЦИПОВ РАБОТЫ.



Использовано в видео:
===========================================================
Получаем и отправляем GET запросами
===========================================================
https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/getUpdates  // GET получение сообщений
-----------------------------------------------------------
https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/SendMessage?chat_id=7124124425&text=Hello, bot! // GET отправка текста боту
-----------------------------------------------------------
https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/sendPhoto?chat_id=7124124425&photo=https://proza.ru/pics/2021/09/03/24.jpg // GET отправка фото боту
-----------------------------------------------------------
https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/sendVideo?chat_id=7124124425&video=https://indeedphp.github.io/arduino/video/can_lin_test_9.mp4 // GET отправка видео боту
-----------------------------------------------------------
https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/sendDocument?chat_id=7124124425&document=https://indeedphp.github.io/arduino/files/kontrolka9_9.zip // GET отправка файла боту
-----------------------------------------------------------
https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/sendMessage?chat_id=-4512927034&text=Hello, clear_cod_php!  // Отправляем сообщение в группу (id с минусом)
-----------------------------------------------------------
========================================================================================================
ОТПРАВКА ТЕКСТОВОГО СООБЩЕНИЯ В КОДЕ
========================================================================================================
ПХП отправка сообщения гет запросом
--------------------------------------------------------------------------------------------------------
<?php
 file_get_contents("https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/SendMessage?chat_id=7124124425&text=Hello, php");
?>
--------------------------------------------------------------------------------------------------------
ЖС отправка сообщения гет запросом
--------------------------------------------------------------------------------------------------------
<script>
 fetch('https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/SendMessage?chat_id=7124124425&text=123'); 
</script>
--------------------------------------------------------------------------------------------------------
ПХП отправка пост запросом сообщения в бота
--------------------------------------------------------------------------------------------------------
<?php
    $tg_user = '7124124425';
    $bot_token = '7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw'; 
    
    $text = "Пост сообщение PHP";
    
    $params = array( 
        'chat_id' => $tg_user, 
        'text' => $text, 
        'parse_mode' => 'html', 
    );
    
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'https://api.telegram.org/bot' . $bot_token . '/sendMessage');
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($curl, CURLOPT_TIMEOUT, 10); 
    curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
    $result = curl_exec($curl); // запрос к api
    curl_close($curl);
 ?>
 -------------------------------------------------------------------------------------------------------
 ЖС отправка пост текста в бота
 -------------------------------------------------------------------------------------------------------
 <script>
fetch('https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/SendMessage', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({chat_id: 7124124425, text: 'Пост сообщение JS'})
  });
</script>
--------------------------------------------------------------------------------------------------------
ПХП отправка пост запросом сообщения в бота из инпута
--------------------------------------------------------------------------------------------------------
<form action="" method="POST">
<p> 
<input type="text" name="text" >
</p>
<input type="submit" name="formS" value="Отправить">
</form>

<?php
if(!empty($_POST ["text"])) { $text = $_POST ["text"];

    $tg_user = '7124124425'; // id пользователя, которому отправиться сообщения
    $bot_token = '7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw'; // токен бота
    
    $params = array(  // параметры, которые отправятся в api телеграмм
        'chat_id' => $tg_user, // id получателя сообщения
        'text' => $text, // текст сообщения
        'parse_mode' => 'html', // режим отображения сообщения, не обязательный параметр
    );
    
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'https://api.telegram.org/bot' . $bot_token . '/sendMessage'); // адрес api телеграмм
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // отправка данных  
    curl_setopt($curl, CURLOPT_TIMEOUT, 10); // максимальное время выполнения запроса
    curl_setopt($curl, CURLOPT_POSTFIELDS, $params); // параметр используемый для установки тела POST-запроса.
    $result = curl_exec($curl); // запрос к api
    curl_close($curl);
  }
 ?>
 --------------------------------------------------------------------------------------------------------
 ЖС отправляем методом пост из инпута текст в бота
 --------------------------------------------------------------------------------------------------------
 <input id="input-id"><br><br>
<input type="submit" id="submit">

<script>
let input = document.getElementById('input-id'); // Извлекаем элемент input
let submit = document.getElementById('submit');  // Извлекаем элемент submit
submit.addEventListener('click', function () {  // ждем клика по кнопке отправить
    let value = input.value; // заберем значение из инпута
    fetch('https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/SendMessage', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({chat_id: 7124124425, text: value})
  })});
</script>
 ===============================================================================================================
 ОТПРАВКА КНОПОК В ТЕКСТОВОЕ ПОЛЕ БОТА
 ===============================================================================================================
 ПХП отправляем кнопки на бота 
 ---------------------------------------------------------------------------------------------------------------
 <?php
    $tg_user = '7124124425'; // id пользователя, которому отправиться сообщения
    $bot_token = '7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw'; // токен бота
    
    $text = "Отправляем кнопки PHP";
    
    $params = array(  // параметры, которые отправятся в api телеграмм
        'chat_id' => $tg_user, // id получателя сообщения
        'text' => $text, // текст сообщения
        
        'reply_markup' => json_encode(array(
    'inline_keyboard' => array(
	    array(
	        array(
		        'text' => 'Кнопка 1',  // название кнопки отобразится в телеграмм
		        'callback_data' => '123',  // значение кнопки вернется по апи на сервер
	        ),
            array(
		        'text' => 'Button 2',
		        'callback_data' => '456',  
	        ),
	    )),
    )),
    );
    
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'https://api.telegram.org/bot' . $bot_token . '/sendMessage'); // адрес api телеграмм
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // отправка данных 
    curl_setopt($curl, CURLOPT_TIMEOUT, 10); // максимальное время выполнения запроса
    curl_setopt($curl, CURLOPT_POSTFIELDS, $params); // параметры запроса
    $result = curl_exec($curl); // запрос к api
    curl_close($curl);
 ?>
 -----------------------------------------------------------------------------------------------------------------
 ЖС отправка кнопок в текстовое поле бота
 -----------------------------------------------------------------------------------------------------------------
 <script>
  var post = {
    chat_id: '7124124425',
    text: 'Отправляем кнопки JS',
    reply_markup: {
      inline_keyboard: [
        [{
          text: 'Кнопка номер один',
          callback_data: '1'
        }],
        [{
          text: 'Some button text 2',
          callback_data: '2'
        }],
        [{
          text: 'Some button text 3',
          callback_data: '3'
        }]
      ]
    }
  };

  fetch('https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/SendMessage', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(post)
  });
</script>
 ================================================================================================================
 ОТПРАВКА КЛАВИАТУРЫ БОТУ, НИЖЕ ПОЛЯ ВВОДА
 ================================================================================================================
 ПХП выводим сообщение и клавиатуру с двумя кнопками
 ----------------------------------------------------------------------------------------------------------------
<?php
$tg_user = '7124124425'; // id пользователя, которому отправиться сообщения
$bot_token = '7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw'; // токен бота

$text = "Клавиатура для бота на PHP";

// параметры, которые отправятся в api телеграмм
$params = [
  'chat_id' => $tg_user, // id получателя сообщения
  'text' => $text, // текст сообщения

  'reply_markup' => json_encode([
    'keyboard' => [
      [
        [
          'text' => 'кнопка 124',
        ],
        [
          'text' => "кнопка 224",
        ],
      ]
    ],
    'one_time_keyboard' => TRUE,  // появление сокрытие клавиатуры
    'resize_keyboard' => TRUE,  // растягивать клавиатуру
  ]),
];

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://api.telegram.org/bot' . $bot_token . '/sendMessage'); // адрес api телеграмм
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // отправка данных методом POST
curl_setopt($curl, CURLOPT_TIMEOUT, 10); // максимальное время выполнения запроса
curl_setopt($curl, CURLOPT_POSTFIELDS, $params); // параметры запроса
$result = curl_exec($curl); // запрос к api
curl_close($curl);
?>
-------------------------------------------------------------------------------------------------------------------
ПХП Удаление клавиатуры
-------------------------------------------------------------------------------------------------------------------
<?php
$tg_user = '7124124425'; // id пользователя, которому отправиться сообщения
$bot_token = '7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw'; // токен бота

$text = "бот убрал клавиатуру PHP";

// параметры, которые отправятся в api телеграмм
$params = [
  'chat_id' => $tg_user, // id получателя сообщения
  'text' => $text, // текст сообщения
  'reply_markup' => json_encode([
    'remove_keyboard' => true,
  ]),
];

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://api.telegram.org/bot' . $bot_token . '/sendMessage'); // адрес api телеграмм
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // отправка данных методом POST
curl_setopt($curl, CURLOPT_TIMEOUT, 10); // максимальное время выполнения запроса
curl_setopt($curl, CURLOPT_POSTFIELDS, $params); // параметры запроса
$result = curl_exec($curl); // запрос к api
curl_close($curl);
?>
--------------------------------------------------------------------------------------------------------------------
ЖС сообщение и 3 кнопки ниже поля ввода в ряд
--------------------------------------------------------------------------------------------------------------------
<script>
  var post = {
    chat_id: '7124124425',
    text: 'Клавиатура для бота на JS',
    reply_markup: {
      keyboard: [
        [{text: 'Кнопка номер один 1'}],
        [{text: 'Some button text 2'}],
        [{text: 'Some button text 3'}]
      ],
      one_time_keyboard: true,  
      resize_keyboard: true, 
    }
  };

  fetch('https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/SendMessage', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(post)
  });
</script>
-----------------------------------------------------------------------------------------------------------------------
ЖС бот убрал клавиатуру
-----------------------------------------------------------------------------------------------------------------------
<script>
  var post = {
    chat_id: '7124124425',
    text: 'бот убрал клавиатуру JS',
    reply_markup: {
      remove_keyboard: true
    }
  };

  fetch('https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/SendMessage', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(post)
  });
</script>
========================================================================================================================
ОТПРАВКА ФОТО В ТЕЛЕГРАММ БОТА
========================================================================================================================
ПХП отпавляем фото с текстом
------------------------------------------------------------------------------------------------------------------------
<?php
$tg_user = '7124124425'; // id пользователя, которому отправиться сообщения
$bot_token = '7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw'; // токен бота

$response = array(
	'chat_id' => $tg_user,
	'caption' => 'text',  // можно вставить капчу подпись под фото
	'photo' => curl_file_create('1.jpg')  // берем фото из корневой директории 
);	

$ch = curl_init('https://api.telegram.org/bot' . $bot_token . '/sendPhoto');  
curl_setopt($ch, CURLOPT_POST, 1);  
curl_setopt($ch, CURLOPT_POSTFIELDS, $response);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
curl_close($ch);
 ?>
 -----------------------------------------------------------------------------------------------------------------------
 ЖС отправляем фото из инпута в бот
 -----------------------------------------------------------------------------------------------------------------------
<input type="file" id="input-id"><br><br>
<input type="submit" id="submit">

<script>
let submit = document.getElementById('submit');  // Извлекаем элемент submit

submit.addEventListener('click', function() { // ждем клика по кнопке отправить
const fileInput = document.getElementById('input-id'); // получаем элемент input для загрузки файла
const file2 = fileInput.files[0]; // получаем выбранный файл
const formData = new FormData(); // создаем объект FormData для передачи файла
formData.append('photo', file2); // добавляем файл в объект FormData

var requestOptions = {
 method: 'POST',
 body: formData,
};

fetch("https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/sendPhoto?chat_id=7124124425", requestOptions)
});
 </script>
========================================================================================================================
ОТПРАВЛЯЕМ ВИДЕО В ТЕЛЕГРАММ БОТА
========================================================================================================================
ПХП отправляем видео с текстом
------------------------------------------------------------------------------------------------------------------------
 <?php
$tg_user = '7124124425'; // id пользователя, которому отправиться сообщения
$bot_token = '7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw'; // токен бота

$response = array(
	'chat_id' => $tg_user,
	'caption' => 'text',  // можно вставить капчу подпись под фото
	'video' => curl_file_create('2.mp4')  // берем фото из корневой директории 
);	

$ch = curl_init('https://api.telegram.org/bot' . $bot_token . '/sendVideo');  
curl_setopt($ch, CURLOPT_POST, 1);  
curl_setopt($ch, CURLOPT_POSTFIELDS, $response);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
curl_close($ch);
 ?>
 -----------------------------------------------------------------------------------------------------------------------
ЖС отправляем видео из инпута без текста
 -----------------------------------------------------------------------------------------------------------------------
 <input type="file" id="input-id"><br><br>
<input type="submit" id="submit">

<script>
let submit = document.getElementById('submit');  // Извлекаем элемент submit

submit.addEventListener('click', function() { // ждем клика по кнопке отправить
const fileInput = document.getElementById('input-id'); // получаем элемент input для загрузки файла
const file2 = fileInput.files[0]; // получаем выбранный файл
const formData = new FormData(); // создаем объект FormData для передачи файла
formData.append('video', file2); // добавляем файл в объект FormData

var requestOptions = {
 method: 'POST',
 body: formData,
};

fetch("https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/sendVideo?chat_id=7124124425", requestOptions)
});
</script>
 =======================================================================================================================
 ОТПРАВЛЯЕМ ФАЙЛ В БОТА
 =======================================================================================================================
 ПХП отправяляем файл в бота
 -----------------------------------------------------------------------------------------------------------------------
<?php
$tg_user = '7124124425'; // id пользователя, которому отправиться сообщения
$bot_token = '7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw'; // токен бота

$response = array(
	'chat_id' => $tg_user,
	'caption' => 'text',  // можно вставить капчу подпись под фото
	'document' => curl_file_create('index1.php')  // берем фото из корневой директории 
);	

$ch = curl_init('https://api.telegram.org/bot' . $bot_token . '/sendDocument');  
curl_setopt($ch, CURLOPT_POST, 1);  
curl_setopt($ch, CURLOPT_POSTFIELDS, $response);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
curl_close($ch);
 ?>
 -----------------------------------------------------------------------------------------------------------------------
 ЖС отправляем файл в телеграм бота
 -----------------------------------------------------------------------------------------------------------------------
 <input type="file" id="input-id"><br><br>
<input type="submit" id="submit">

<script>
let submit = document.getElementById('submit');  // Извлекаем элемент submit

submit.addEventListener('click', function() { // ждем клика по кнопке отправить
const fileInput = document.getElementById('input-id'); // получаем элемент input для загрузки файла
const file2 = fileInput.files[0]; // получаем выбранный файл
const formData = new FormData(); // создаем объект FormData для передачи файла
formData.append('document', file2); // добавляем файл в объект FormData

var requestOptions = {
 method: 'POST',
 body: formData,
};

fetch("https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/sendDocument?chat_id=7124124425", requestOptions)
});
</script>
=========================================================================================================================
ПОЛУЧЕНИЕ ДАННЫХ
=========================================================================================================================
ПОЛУЧЕНИЕ СООБЩЕНИЙ В КОДЕ
=========================================================================================================================
пхп получаем все сообщения из бота и выводим на страницу
-------------------------------------------------------------------------------------------------------------------------
<?php
$data = file_get_contents('https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/getUpdates');
$data2 = json_decode($data, true);
echo '<pre>';
print_r($data2);
echo '</pre>';
?>
-------------------------------------------------------------------------------------------------------------------------
ЖС получаем все сообщения и выводим в консоль
-------------------------------------------------------------------------------------------------------------------------
<script>
fetch("https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/getUpdates")
.then( (response) => response.json())
.then((data) => console.log(data))
</script>
=========================================================================================================================
ПОЛУЧАЕМ ФОТО ИЗ ТЕЛЕГРАММ БОТА
=========================================================================================================================
 Получаем фото из телеграмм бота, сначала запрос приходит ответ потом из ответа берем путь и еще запрос на файл который сразу закачивается
 ------------------------------------------------------------------------------------------------------
 https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/getFile?file_id=AgACAgIAAxkBAAMhZ0dbPPzPuaVDPqbMfDrAbgw7MrYAAgHpMRs9XTlKuoZqmmCIAiIBAAMCAAN4AAM2BA
-------------------
{"ok":true,"result":{"file_id":"AgACAgIAAxkBAAIE3Wc8ryycickfqDb8kwPDigH04ymxAAI56jEbBW_oSR8IsoToQNJuAQADAgADeAADNgQ","file_unique_id":"AQADOeoxGwVv6El9","file_size":40816,"file_path":"photos/file_96.jpg"}}
-------------------------------------
 https://api.telegram.org/file/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/photos/file_0.jpg
 ------------------------------------------------------------------------------------------------------------------------
 ПХП получаем фото и сохраняем на сервер (файл и видео тоже так сохраняются)
 ------------------------------------------------------------------------------------------------------------------------
 <?php
$file = 'AgACAgIAAxkBAAMhZ0dbPPzPuaVDPqbMfDrAbgw7MrYAAgHpMRs9XTlKuoZqmmCIAiIBAAMCAAN4AAM2BA';
$data = file_get_contents('https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/getFile?file_id='. $file);
$data2 = json_decode($data, true);
$data3 = $data2['result']['file_path'];

$papex_url = 'https://api.telegram.org/file/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/'.$data3;
$lastPart = basename($papex_url);  // берем из ссылки имя файла с расширением

$ch = curl_init();  // Инициализация сеанса cURL
curl_setopt($ch, CURLOPT_URL, $papex_url); // URL файла для загрузки
$fp = fopen($lastPart, 'w');   // создаем файл (имя, код параметра файла)
curl_setopt($ch, CURLOPT_FILE, $fp); // Запрос cURL на запись содержимого в файл
curl_exec ($ch);  // Выполнение сеанса cURL
curl_close ($ch); // Закрытие сеанса cURL 
fclose($fp); // закрытие файла
?>
------------------------------------------------------------------------------------------------------------------------
ЖС получаем фото и выводим на страницу
------------------------------------------------------------------------------------------------------------------------
<div id="image-container"></div>
<script>
let file = 'AgACAgIAAxkBAAMhZ0dbPPzPuaVDPqbMfDrAbgw7MrYAAgHpMRs9XTlKuoZqmmCIAiIBAAMCAAN4AAM2BA';
  fetch('https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/getFile?file_id='+ file)
    .then((response) => response.json())
    .then((data) => {
      let tenp = data.result.file_path;
      console.log(tenp);
      let image = document.createElement('img');
      image.src = 'https://api.telegram.org/file/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/' + tenp;
      document.getElementById('image-container').append(image);
    });
</script>
------------------------------------------------------------------------------------------------------------------------
ЖС получаем видео и выводим на страницу с элементами управления
------------------------------------------------------------------------------------------------------------------------
    <div id="video-container"></div>
    <script>
        let file = 'BAACAgIAAxkBAAMiZ0dqaqYDdq_1LoIcz81hIAAB7ti4AAKkZAACPV05SgGZlzr_Nv2ZNgQ';
        fetch('https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/getFile?file_id=' + file)
            .then((response) => response.json())
            .then((data) => {
                let tenp = data.result.file_path;
                console.log(tenp);
                let video = document.createElement('video'); video.autoplay = false;
                video.controls = true;
                video.muted = false;
                video.height = 340; 
                video.src = 'https://api.telegram.org/file/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/' + tenp;
                document.getElementById('video-container').append(video);
            });
    </script>
========================================================================================================================
ТО ЧТО НЕ БЫЛО В ВИДЕО НО ПУСТЬ ТУТ ПОЛЕЖИТ
========================================================================================================================
ПХП Отправка сообщения в ответ на другое сообщение
------------------------------------------------------------------------------------------------------------------------
<?php
    $tg_user = '7124124425';
    $bot_token = '7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw'; 
    
    $text = "Пост сообщение PHP";
    
    $params = array( 
        'chat_id' => $tg_user, 
        'text' => $text, 
        'parse_mode' => 'html', 
        "reply_to_message_id" => 44,  // отвечаем на сообщение 44
    );
    
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'https://api.telegram.org/bot' . $bot_token . '/sendMessage');
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($curl, CURLOPT_TIMEOUT, 10); 
    curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
    $result = curl_exec($curl); // запрос к api
    curl_close($curl);
 ?>
------------------------------------------------------------------------------------------------------------------------
ПХП веб хук для бота, нужно https, и конкретный домен сервера в сети, передается один раз
------------------------------------------------------------------------------------------------------------------------
<?php
   $token = "7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw";

   $getQuery = array(
        "url" => "https://..домен../index.php",
   );
   $ch = curl_init("https://api.telegram.org/bot". $token ."/setWebhook?" . http_build_query($getQuery));
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
   curl_setopt($ch, CURLOPT_HEADER, false);
   
   $resultQuery = curl_exec($ch);
   curl_close($ch);
   
   echo $resultQuery;
 php?>
 ------------------------------------------------------------------------------------------------------------------------
ПХП получаем с вебхука сообщение и сохраняем в файл
------------------------------------------------------------------------------------------------------------------------
 <?php
$data = file_get_contents('php://input');
file_put_contents('message.txt', $data);
 ?>
------------------------------------------------------------------------------------------------------------------------
ПХП зеркальный ответ на сообщение
------------------------------------------------------------------------------------------------------------------------
 <?php
$json = file_get_contents('php://input');
$arr = json_decode($json, TRUE);
$text = $arr['message']['text'];
$id = $arr['message']['chat']['id'];
file_get_contents('https://api.telegram.org/bot7753367910:AAEQfKZ7dZ23Jgn32ly1snQv-l8qaxXSNdw/SendMessage?chat_id='.$id.'&text='.$text);
 ?>
------------------------------------------------------------------------------------------------------------------------

Видео номер 24
Докер & Ларавел 10 WSL Windows & Docker Desktop пошагово создадим image, контейнер и dockerfile

В видео подробно показана установка Докера в систему виндовс на WSL , так же пошагово через dockerfile создадим image а затем запустим контейнер. Сделаем постепенно сначала просто html страничку, потом подключим php, затем поработаем с базой данных и фреймворком ларавел.



Использовано в видео:
============================================================
https://docs.docker.com/desktop/install/windows-install/  // Ссылка на докер
docker -v  // версия докера
docker-compose -v  // версия докер компосе
docker run -d -p 8888:80 docker/welcome-to-docker  // Запускаем контейнер (сайт с анимацией открывается по адресу http://localhost:8888/
===========================================================
Dockerfile // создаем файл с названием и без расширения
-----------------------------------------------------------
FROM ubuntu:24.04
RUN apt-get update
RUN apt-get install apache2 -y
RUN apt-get install php8.1 -y
RUN apt-get install libapache2-mod-php -y
RUN apt-get install php-mysqli -y
RUN apt-get install mysql-server-8.0 -y
RUN apt-get install php-cli -y
RUN apt-get install php-common -y
RUN apt-get install php-zip -y
RUN apt-get install php-gd -y
RUN apt-get install php-mbstring -y
RUN apt-get install php-curl -y
RUN apt-get install php-xml -y
RUN apt-get install php-bcmath -y
RUN apt-get install php-dom -y
WORKDIR /etc/apache2/sites-available
COPY 000-default.conf .
WORKDIR /var/www
COPY example ./example 
CMD service mysql start && apachectl -D FOREGROUND
=================================================
docker build . -t // Строим имадж
docker run -d -it -p 80:80 start1 // Сщздаем контейнер из имаджа
/bin/bash // в консоли контейнера переходим к root
apachectl -D FOREGROUND  // запускаем апач в консоли контейнера
pwd // узнаем где находимся
cd var/www //рабочая папка апач
mkdir test  //создает папку с названием «test» там, где вы находитесь
touch index.php  //команда создаст пустой файл с названием index.php
phpinfo(); // функция для вывода данных по php
=================================================
Работаем с базой в консоли контейнера
-------------------------------------------------
service mysql status  // проверяем статус
service mysql start  // запускаем базу
mysql  // входим в настройки базы
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '12345678';  // настраиваем пароль 12345678 для юзера root для phpmyadmin
mysql -u root -p  // вход в базу с вводом пароля, пароль предлагают ввести ниже
exit  // выход из настроек базы
SHOW DATABASES;  // показать все базы
CREATE DATABASE test;  // создаем базу тест
USE test;  // выбрать базу данных для последующей работы с ней
SHOW TABLES;  // показать таблицы
CREATE TABLE `users` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT , `name` VARCHAR(64) NOT NULL , PRIMARY KEY (`id`)); //создаем таблицу и две колонки
INSERT `users` SET `name` = 'Elena Ivanova';  // вставляем данные в таблицу
SELECT * FROM `users`; // получаем данные из таблицы
UPDATE `users` SET `name` = 'Elena Popova' WHERE `id` = 1; // меняем данные
DELETE FROM `users` WHERE `id` = 1;  // удаляем данные 
DROP TABLE `users`; // удаляем таблицу
DROP DATABASE `test`;  // удаляем базу
============================================================
Подключаемся к базе и читаем все
------------------------------------------------------------
<?php
$server = "127.0.0.1";
$login = "root";
$pass = "12345678";
$name_bd = "test";
$link = mysqli_connect($server, $login, $pass, $name_bd);
if ($link == false){
echo "disconect bd";
}

$q = mysqli_query($link, "SELECT * FROM `users`");
for ($data = []; $row = mysqli_fetch_assoc($q ); $data[] = $row);
var_dump($data); 
mysqli_close($link);
?>
==================================================================
C:\Windows\System32\drivers\etc  // папка где лежит хост файл для локального домена
Видео номер 23
Линукс на Виндовс 10 WSL, Сервер Apache, Виртуальный хост, База, PhpMyAdmin, Composer, Ларавел 10

В видео пошагово установим WSL на Виндовс 10, при установке произойдет установка Ubuntu, далее поставим сервер Apache, сделаем свою страничку html, далее настроим виртуальный хостинг. Произведем установку базы данных MySQL и веб-интерфейс для администрирования базы PhpMyAdmin, установим пакетный менеджер Composer через который поставим фреймворк Ларавел 10, настроим работу с базой данных.



Использовано в видео:
============================================================
wsl --uninstall
wsl --install // в повер шелл виндовс вводим команду под админом для установки wsl и Ubuntu
apt-get update  // обязательно обновить а то не встанут другие пакеты
pwd  // узнать в какой директории находимся
cd /   // перейдем в корень
cd home  // перейдем в папку(директорию) home
sudo -s  // переход к суперпользователю (потребуется ввести пароль)
apt-get install apache2  // устанавливаем сервер Apache сразу будет доступен по http://localhost
apt install apache2 -y // или так если не ставится, также вместо локалхост http://172.25.140.69/
chmod -R 777 test // все что в папке test будет доступным для изменения
systemctl restart apache2 // перезапуск Apache
a2ensite test.conf  // через обращение к файлу test.conf активируем домен testexample
a2ensite example.conf  // через обращение к файлу test.conf активируем домен example
apt install net-tools  // пакет для работы с настройками аппаратного обеспечения (для ifconfig)
ifconfig // узнать адрес в сети
ip a // ип адреса в отметке inet , или так без установки пакета 
C:\Windows\System32\drivers\etc  // папка где лежит хост файл для локального домена
apt install php  // устанавливаем PHP
apt install libapache2-mod-php  // устанавливаем поддержку пхп в апач 
apt install mysql-server // установка базы
apt install php-mysqli -y  // устанавливаем поддержку базы данных в пхп
apt install phpmyadmin -y  // установка веб интерфейса базы phpmyadmin
mysql  // входим в настройки базы
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '12345678';  // настраиваем пароль 12345678 для юзера root для phpmyadmin
mysql -u root -p  // вход в базу с вводом пароля, пароль предлагают ввести ниже
exit  // выход из настроек базы
apt install composer // устанавливаем пакетный менеджер Composer
composer create-project laravel/laravel:^10.0 example  // через Composer устанавливаем Ларавел 10 в папку example
php artisan serve  // запустить ларавел через встроенный сервер
https://selectel.ru/blog/tutorials/how-to-install-and-configure-phpmyadmin-on-ubuntu-20-04/  // инфа по установке phpmyadmin и MySQL
============================================================
Видео номер 22
Exception PHP & Laravel 10 Try Catch Исключения в PHP коде и фреймворке Ларавел 10

В видео подробно рассказано об исключениях (ошибках) которые появляются при различных проблемах в коде и отображаются с помощью PHP . С помощью многочисленных примеров из жизни посмотрим для чего нужны ошибки и как они способны уберечь нас от различных проблем. Рассмотрим такую модель PHP как Try Catch которая способна отлавливать ошибки и исключения и выполнять различные действия, например менять текст ошибки, записывать в лог и так далее. Поработаем с фреймворком Ларавел 10 и создадим свой класс ошибок, а так же разберем некоторые проблемы.



Использовано в видео:
============================================================
В консоли
------------------------------------------------------------
cd domains\exception
php artisan make:exception EndPipeException
php artisan make:controller ViewsController
============================================================
В роуте web
------------------------------------------------------------
use App\Http\Controllers\ViewsController;;
------------------------------------------------------------
Route::get('/', [ViewsController::class, 'view']);
============================================================
В контроллере ViewsController
------------------------------------------------------------
use App\Exceptions\EndPipeException;

class ViewsController extends Controller
{
public function view()
{
try {
$int = 1 / 0;
} catch (\Throwable $e) {
throw new endPipeException('Труба все');
}
return view('welcome');
}
}
============================================================
В app\Exceptions\EndPipeException
------------------------------------------------------------
use App\Models\User;
class EndPipeException extends Exception
{
public function context()
{
return ['лог' => 'Закончилась шланга3'];
}
public function render()
{
return 'Внимание: Закончилась шланга3';
}
// public function report() : void
// {
//     User::create(['email'=>'email','password'=>'password','name'=>'name']);
// }
}
============================================================
Разное
------------------------------------------------------------
https://www.php.net/manual/ru/reserved.exceptions.php  // классы ошибок
https://www.php.net/manual/ru/errorfunc.constants.php#constant.e-error // ошибки уровня
error_reporting(E_ERROR);  // отключение уровня ошибок
file_get_contents('https://catfact.ninja/fact');
------------------------------------------------------------
try {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://catfact.ninja/fact'); // адрес api телеграмм
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
curl_close($curl);
print_r($result);
if($result == false )throw new Throwable();
} catch (\Throwable $e){
echo 'нет интернета';
}
try {
} catch (\Exception $e){
}
-----------------------------------------------------------
abort(404);  // вызываем ошибку из файла блейд и файл можно изменить
------------------------------------------------------------
php artisan vendor:publish --tag=laravel-errors  // вытаскиваем в шаблоны свои страницы с ошибками
------------------------------------------------------------
report($e);  // если нужно писать в лог то ставим хелпера
============================================================
Видео номер 21
Laravel 10 & Rabbit MQ брокер сообщений и два микросервиса. установка. биндинг. обменник. очередь

В видео подробно описывается работа брокера сообщений Rabbit MQ, Сначала мы установим Rabbit MQ в Windows затем создадим с помощью графического интерфейса обменник и очередь и свяжем их с помощью связей, далее создадим два микросервиса на Laravel 10 и будем на одном создавать юзера, а на втором входить в приложение.



Использовано в видео:
============================================================
В консоли
------------------------------------------------------------
rabbitmq-plugins.bat enable rabbitmq_management  // графический интерфейс
------------------------------------------------------------
cd domains\publisher //переходим в проект
cd domains\consumer //переходим в проект
composer require php-amqplib/php-amqplib // устанавливаем библиотеку для раббит
php artisan make:command ConsumerRabbitCommand  // создаем команду для консоли
php artisan make:controller LoginController // создаем контроллер
php artisan make:controller RabbitController // создаем контроллер
php artisan migrate // накатываем миграции
php artisan app:consumer-rabbit-command // открываем канал приема сообщений
============================================================
В роуте web \\ publisher
------------------------------------------------------------
use App\Http\Controllers\RabbitController;
------------------------------------------------------------
Route::post('/', [RabbitController::class, 'rabbit'])->name('rabbit');
============================================================
Во вьюхе welcome.blade \\ publisher
------------------------------------------------------------
<form method="POST"  action="{{ route('rabbit') }}">
@csrf
<input type="text" name="name" placeholder="name" >
<input type="text" name="email" placeholder="email">
<input type="text" name="password" placeholder="password">
<input type="submit">
</form>
============================================================
В контроллере RabbitController \\ publisher
------------------------------------------------------------
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

class RabbitController extends Controller
{
public function rabbit(Request $request)
{
$array = $request->only(['email','password','name']);
$json_array = json_encode ($array );

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

$msg = new AMQPMessage($json_array);
$channel->basic_publish($msg,'rabbit');

$channel->close();
$connection->close();
return view('welcome');
}
}
============================================================
============================================================
Во вьюхе welcome.blade \\ consumer
------------------------------------------------------------
@auth
<p>Привествуем! {{ Auth::user()->name }}
@else
<p>Приветствуем гость!</p>
@endauth

<form method="POST" action="{{ route('login') }}">
@csrf
<input type="email" name="email" placeholder="email">
<input type="password" name="password" placeholder="password">
<button type="submit">отправить</button>
</form>
============================================================
В app\Console\Commands\ConsumerRabbitCommand \\ consumer
------------------------------------------------------------
use PhpAmqpLib\Connection\AMQPStreamConnection;
use App\Models\User;
class ConsumerRabbitCommand extends Command
{
protected $signature = 'app:consumer-rabbit-command';
protected $description = 'Command description';
public function handle()
{
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
echo " [*] Waiting for messages. To exit press CTRL+C\n";
$callback = function ($msg) {
echo ' [x] Received ', $msg->body, "\n";
$body = json_decode($msg->body, true);
User::create(['email'=>$body['email'],'password'=>$body['password'],'name'=>$body['name']]);
};
// (Queue, consume_tag, no_local, no_ask, exclusive, nowait, callback)
$channel->basic_consume('office', '', false, true, false, false, $callback);
try {
$channel->consume();
} catch (\Throwable $exception) {
echo $exception->getMessage();
}
}
}
============================================================
В роуте web \\ consumer
------------------------------------------------------------
use App\Http\Controllers\LoginController;
------------------------------------------------------------
Route::post('/', [LoginController::class, 'login'])->name('login');
============================================================
В контроллере RabbitController \\ consumer
------------------------------------------------------------
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
public function login(Request $request)
{
$arr = $request->only(['email','password']);
Auth::attempt($arr);
return view('welcome');
}
}
============================================================
Разное
------------------------------------------------------------
https://www.rabbitmq.com/  // официальный сайт брокера
http://localhost:15672  // адрес сервера раббит
guest  guest  // юзернейм и пароль раббита по умолчанию
https://www.rabbitmq.com/docs/install-windows // установочный файл раббита
https://www.erlang.org/ // язык для раббит
https://www.rabbitmq.com/docs/plugins  // плагины раббит
============================================================
Видео номер 20
Laravel 10 Validation & FormRequest валидация данных в Ларавел 10.

В видео рассказывается о валидации входящих данных, работаем с данными из формы ввода, работаем с асинхронным запросом, а так же запросом из Постмана. Пошагово рассмотрим валидацию сначала просто в контроллере, а потом с помощью класса FormRequest. Будем выводить ошибки валидации, русифицируем их и изменим под себя. Так же поговорим о различных методах класса FormRequest.



Использовано в видео:
============================================================
В консоли
------------------------------------------------------------
cd domains\request //переходим в проект
php artisan make:controller ValidationController // создаем контроллер
php artisan lang:publish  // выводим директорию под тексты ошибок
php artisan make:request ValidationRequest  // создаем FormRequest
============================================================
В роуте web
------------------------------------------------------------
use App\Http\Controllers\ValidationController;  // подключаем контроллер
------------------------------------------------------------
Route::post('/', [ValidationController::class, 'valid'])->name('valid');
------------------------------------------------------------
Route::post('/query', [ValidationController::class, 'query'])->name('query');
============================================================
Во вьюхе welcome.blade
------------------------------------------------------------
@if ($errors->any())
<div>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif

<form method="POST" action="{{ route('valid') }}">

@csrf

@error('text')
<div>ошибка {{ $message }}</div>
@enderror

<input type="text" name="text" placeholder="Введите текст" value="{{ old('text') }}"><br><br>

@error('int')
<div>ошибка {{ $message }}</div>
@enderror

<input type="text" name="int" placeholder="Введите число" value="{{ old('int') }}"><br><br>

<input type="submit">
</form>

@if (isset($validated))
@json($validated)
@endif

<script>
fetch('http://request/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-CSRF-TOKEN': '{{csrf_token()}}'
},
body: JSON.stringify({
text: 'Lorem Ipsum',
int: '88888',
})
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Fetch error:', error));
</script>
============================================================
В контроллере ValidationController без FormRequest
------------------------------------------------------------
public function valid(Request $request)
{
$validated = $request->validate([
'text' => ['required', 'string', 'min:5'],
'int' => ['nullable', 'integer', 'min:500'],
]);
return view('welcome', compact('validated'));
}

public function query(Request $request)
{
$validated = $request->validate([
'text' => ['required', 'string', 'min:5'],
'int' => ['nullable', 'integer', 'min:500'],
]);
return $validated;
}
============================================================
В контроллере ValidationController с FormRequest
------------------------------------------------------------
use App\Http\Requests\ValidationRequest;

public function valid(ValidationRequest $request)
{
$validated = $request->all();
return view('welcome', compact('validated'));
}

public function query(ValidationRequest $request)
{
$validated = $request->validated();
return $validated;
}
============================================================
В ValidationRequest
------------------------------------------------------------
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ValidationRequest extends FormRequest
{
// protected $redirect = 'https://indeedphp.github.io/toSenior_PHP/';
// protected $redirectRoute = 'welcome';
// protected $stopOnFirstFailure = true;

public function authorize(): bool
{
return 1 == 1;
}

// protected function prepareForValidation(): void
// {
//     $this->merge([
//         'text' => 'hello user',
//     ]);
// }

public function rules(): array
{
return [
'text' => ['required', 'string', 'min:5'],
'int' => ['nullable', 'integer', 'min:500'],
];
}

// public function passedValidation()
// {
//     $this->merge([
//         'text' => 'Goodbye user',
//     ]);
// }

public function attributes(): array
{
return [
'text' => 'для ввода текста',
'int' => 'для ввода чисел',
];
}

// public function messages(): array
// {
//     return [
//         'text.required' => 'Обязательно!!!',
//         'int.min' => 'Минимум 500!!!',
//     ];
// }
}
============================================================
Разное
------------------------------------------------------------
'locale' => 'ru',  // в config\app.php меняем на ru для русификации
-----------------------------------------------------------
protected $except = ['/query']; // в Http\Middleware\VerifyCsrfToken разрешаем маршрут без Csrf
-----------------------------------------------------------
https://github.com/Laravel-Lang/lang/tree/main // для русиикации перевод
-----------------------------------------------------------
https://www.coderstool.com/convert-json-to-php-array // онлайн конвертор
-----------------------------------------------------------
https://laravel.su/docs/10.x/validation  // документация ларавел на русском
-----------------------------------------------------------
https://laravel.com/docs/10.x/validation  // документация ларавел на английском
============================================================
Видео номер 19
Pusher & Laravel 10 разбираем работу официальных пакетов PUSHER PHP SERVER, LARAVEL ECHO, PUSHER JS.

В видео подробно рассказывается о работе Laravel 10 и сервиса сообщений в реальном времени Pusher, разберем работу двух пакетов которые предлагает документация. Разбирать будем пошагово сначала поработаем с одним пакетом PUSHER PHP SERVER и будем отправлять сообщения на Pusher где примем их в консоли. Далее второй шаг установим в новый проект LARAVEL ECHO совмещенный с PUSHER JS и будем принимать сообщения из консоли Pusher. И наконец третий шаг соединим оба пакета в одном проекте, поработаем с приватными и обычными каналами и пр.



Использовано в видео:
============================================================
В консоли
------------------------------------------------------------
cd domains\pusher2 //переходим в проект
composer require pusher/pusher-php-server  // устанавливаем пакет пушер сервер
php artisan make:event CommentEvent  // создаем событие для отправки сообщений
php artisan make:controller PusherController // создаем контроллер
php artisan migrate // накатываем миграции
php artisan db:seed // накатываем сидеры
npm install --save-dev laravel-echo pusher-js // пакет ларавел эхо
npm i @vitejs/plugin-vue  // пакет VUE
npm run dev  // постоянная сборка
npm run build  // проводим сборку однократно
============================================================
В роуте web
------------------------------------------------------------
use App\Http\Controllers\PusherController;  // подключаем контроллер
------------------------------------------------------------
Route::get('/', function () {
return view('welcome');
});

Route::get('/mes', [PusherController::class, 'message']);
Route::post('/mes', [PusherController::class, 'message']);

Route::get('/bob', function () {  // мини регистрация
auth()->loginUsingId(1);
return view('welcome');
});

Route::get('/ted', function () {
auth()->loginUsingId(2);
return view('welcome');
});
============================================================
Во вьюхе welcome.blade получаем сообщения через JS файл
------------------------------------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="shortcut icon"href="favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocketPusher</title>
<script src="https://js.pusher.com/8.2.0/pusher.min.js"></script>
</head>
<body>

<script>
var pusher = new Pusher("{{env('PUSHER_APP_KEY')}}", {
cluster: "{{env('PUSHER_APP_CLUSTER')}}",
});
var channel = pusher.subscribe("message");
channel.bind("text", (data) => {
console.log(data)
});
</script>

</body>
</html>
============================================================
В контроллере PusherController
------------------------------------------------------------
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Events\CommentEvent; // подключаем событие

class PusherController extends Controller
{
public function message(Request $request)
{
$data = $request->book;
event(new CommentEvent($data));  // создаем событие
}
}
============================================================
В событии CommentEvent
------------------------------------------------------------
<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class CommentEvent implements ShouldBroadcast  // подключаем интерфейс
{
use Dispatchable, InteractsWithSockets, SerializesModels;

public $data;

public function __construct($data)
{
$this->data = $data;
}

public function broadcastWhen()  // проверяем условие
{
return 1 === 1;
}

public function broadcastOn(): array // создаем канал
{
return [
new PrivateChannel('message'.auth()->id()),
// new Channel('message')
];
}
public function broadcastAs(): string  // создаем событие
{
return 'text';
}
public function broadcastWith(): array  // сообщение
{
return ['data' => $this->data ];
}
}
============================================================
В vite.config.js делаем настройку для VUE
------------------------------------------------------------
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [
vue(),
laravel({
input: [
'resources/css/app.css',
'resources/js/app.js',
],
refresh: true,
}),
],
});
============================================================
В welcome.blade после установки laravel-echo
------------------------------------------------------------
@vite(['resources/css/app.css', 'resources/js/app.js'])

<script>
window.userID = {{ auth() -> id() }};
</script>

@auth
<p>Привествуем! {{ Auth::user()->name }}</p>
@else
Приветствуем гость
@endauth

<div id="app"></div>
============================================================
В test.vue
------------------------------------------------------------
<template>
<h1>Hello Vue!</h1>
<input type="text" v-model="input" name="name">
<button type="button" @click="buttonClick()">Отправить</button>

<div v-for="(el) in list">
<p>{{ el }}</p>
</div>
</template>

<script>
export default {
data() {
return {
list: [],
input: "Hello User",
}
},
methods: {
buttonClick() {
axios.post('/mes', { book: this.input });
}
},
created: function () {
window.Echo.private('message' + window.userID)
.listen('.text', res => {
this.list.push(res.data);
console.log(res);
});
window.Pusher.logToConsole = true;  // получаем техсообщения
}
}
</script>
<style scoped>
</style>
============================================================
В app.js
------------------------------------------------------------
import './bootstrap';
import { createApp } from 'vue/dist/vue.esm-bundler';
import test from './test.vue';
createApp(test).mount('#app');
============================================================
В роуте channel
------------------------------------------------------------
Broadcast::channel('message{id}', function ($id) {
return $id->id === auth()->id();
});
============================================================
В config\app.php раскомментируем строку (внизу файла)
------------------------------------------------------------
App\Providers\BroadcastServiceProvider::class,
============================================================
Разное
------------------------------------------------------------
https://pusher.com/  Сайт Pusher
============================================================
Видео номер 18
Laravel 10 & Pusher websocket , создаем чат без Node, Vue, Vite и прочего. Ларавел 10 и Пушер

В видео простой способ работы фреймворка Laravel 10 и сервиса Pusher без различных пакетов которые не позволяют разобраться в работе WebSocket, поэтому упростим и будем внедрять :)



Использовано в видео:
============================================================
В консоли
------------------------------------------------------------
cd domains\pusher //переходим в проект
php artisan migrate // накатываем миграции
php artisan db:seed // накатываем сидеры
php artisan make:view chat  // создаем страничку
php artisan make:model Chat --migration  // создаем модель и миграцию для таблицы чат
php artisan make:controller ChatController  // создаем контроллер
============================================================
В роуте
------------------------------------------------------------
use App\Http\Controllers\ChatController;
------------------------------------------------------------
Route::get('/', function () {
return view('welcome');
});
Route::get('/chat', [ChatController::class, 'chat'])->name('chat');
Route::get('/api', [ChatController::class, 'api_pusher']);
Route::get('/bob', function () {
auth()->loginUsingId(1);
return redirect()->route('chat');
});
Route::get('/ben', function () {
auth()->loginUsingId(2);
return redirect()->route('chat');
});
Route::get('/ken', function () {
auth()->loginUsingId(3);
return redirect()->route('chat');
});
============================================================
Во вьюхе
------------------------------------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocketPusher</title>
<script src="https://js.pusher.com/8.2.0/pusher.min.js"></script>
</head>
<body>
@auth
<p>Привествуем! {{ Auth::user()->name }}</p>
@endauth
<input id="message">
<button name="button" id="button">Отправить</button>
<p>Все сообщения</p>
@isset($arr)
@foreach ($arr as $el)
<li>{{ $el['name']}}: {{ $el['data'] }}</li>
@endforeach
@endisset
<p>Новые сообщения</p>
<div id="list"></div>
<script>
let message = document.querySelector('#message');
let button = document.querySelector('#button');
let list = document.querySelector('#list');

var pusher = new Pusher("{{env('PUSHER_APP_KEY')}}", {
cluster: "{{env('PUSHER_APP_CLUSTER')}}",
});
var channel = pusher.subscribe("{{env('PUSHER_CHANEL')}}");
channel.bind("{{env('PUSHER_EVENT')}}", function (data) {
let li = document.createElement('li');
li.textContent = data;
list.appendChild(li);
});

button.addEventListener('click', function () {
fetch('/api/?data=' + message.value)
});
</script>
</body>
</html>
============================================================
В контроллере
------------------------------------------------------------
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\Chat;
use App\Services\PusherServise;

class ChatController extends Controller
{
public function chat()
{
$arr = Chat::all();
return view('chat', compact('arr'));
}
public  function api_pusher(Request $request)
{
$name = Auth::user()->name;
$data = $request->data;
Chat::create(['name' => $name, 'data' => $data]);
(new PusherServise)->api_pusher_query($name, $data);
}
}
============================================================
В сервисе
------------------------------------------------------------
<?php
namespace App\Services;
class PusherServise
{
public  function api_pusher_query($name, $data)
{
$body = '{"name":"' . env('PUSHER_EVENT') . '","channels":["' . env('PUSHER_CHANEL') . '"],"data":"' . $name . ': ' . $data . '"}';
$auth_timestamp = time();
$auth_version = '1.0';
$body_md5 = md5($body);
$string_to_sign =
"POST\n/apps/" . env('PUSHER_APP_ID') .
"/events\nauth_key=" . env('PUSHER_APP_KEY') .
"&auth_timestamp=" . $auth_timestamp .
"&auth_version=" . $auth_version .
"&body_md5=" . $body_md5;
$auth_signature = hash_hmac('sha256', $string_to_sign, env('PUSHER_APP_SECRET'));
$opts = array(
'http' =>
array(
'method'  => 'POST',
'header'  => "Content-Type: application/json\r\n",
'content' => $body,
)
);
$context  = stream_context_create($opts);
$url = 'http://api-' . env('PUSHER_APP_CLUSTER') .
'.pusher.com/apps/' . env('PUSHER_APP_ID') .
'/events?auth_key=' . env('PUSHER_APP_KEY') .
'&auth_timestamp=' . $auth_timestamp .
'&auth_version=1.0&body_md5=' . $body_md5 .
'&auth_signature=' . $auth_signature;
file_get_contents($url, false, $context);
}
}
============================================================
Разное
------------------------------------------------------------
https://pusher.com/  Сайт Pusher
============================================================
Видео номер 17
WebSocket. Отправляем из консоли Pusher сообщения, получаем на сайте, отправляем с сайта и Postman

В данном видео с простыми примерами знакомимся с веб сокетом, регистрируемся на Pusher , создаем канал, отправляем и принимаем сообщения в консоль Pusher , получаем сообщения на простой страничке с тремя строками JavaScript, далее отправляем сообщения на сайте написанном на PHP с 10 строками кода, так же разберемся немного с документацией и консолью WebSocket, ну и напишем немного говнокода :)



Использовано в видео:
============================================================
В index.html JS код
------------------------------------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web</title>
<script src="https://js.pusher.com/8.0.1/pusher.min.js"></script>
</head>
<body>
<script>
var pusher = new Pusher("Введите key", { cluster: "Введите cluster", });
var channel = pusher.subscribe("Введите название канала");
channel.bind("Введите название события", (data) => { console.log(data) });
</script>
</body>
</html>
============================================================
В файле index.php PHP код
------------------------------------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="shortcut icon"href="favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>pusherApiTest</title>
</head>
<body>
<form action="" method="POST">
<p> Введите cluster </p>
<input type="text" name="cluster" value="<?php if (isset($_POST['cluster'])) echo $_POST['cluster'] ?>">
<p> Введите app_id </p>
<input type="text" name="app_id" value="<?php if (isset($_POST['app_id'])) echo $_POST['app_id'] ?>">
<p> Введите key </p>
<input type="text" name="key" value="<?php if (isset($_POST['key'])) echo $_POST['key'] ?>">
<p> Введите secret </p>
<input type="text" name="secret" value="<?php if (isset($_POST['secret'])) echo $_POST['secret'] ?>">
<p> Введите название события </p>
<input type="text" name="event" value="<?php if (isset($_POST['event'])) echo $_POST['event'] ?>">
<p> Введите название канала </p>
<input type="text" name="channels" value="<?php if (isset($_POST['channels'])) echo $_POST['channels'] ?>">
<p> Введите сообщение </p>
<input type="text" name="data" value="<?php if (isset($_POST['data'])) echo $_POST['data'] ?>">
<p>
<select name="choice">
<option value="1">Создать запрос с отправкой</option>
<option value="2">Создать запрос без отправки</option>
</select>
</p>
<input type="submit" name="formS" value="Выполнить">
</form>
<?php
if(!empty($_POST ["cluster"])){    $cluster = $_POST ["cluster"];
if(!empty($_POST ["app_id"])){     $app_id = $_POST ["app_id"];
if(!empty($_POST ["key"])){        $key = $_POST ["key"];
if(!empty($_POST ["secret"])){     $secret = $_POST ["secret"];
if(!empty($_POST ["event"])){      $event = $_POST ["event"];
if(!empty($_POST ["channels"])){   $channels = $_POST ["channels"];
if(!empty($_POST ["data"])){       $data = $_POST ["data"];
if(!empty($_POST ["choice"])){     $choice = $_POST ["choice"];}
$body = '{"name":"'.$event.'","channels":["'.$channels.'"],"data":"'.$data.'"}';
$auth_timestamp = time();
$auth_version = '1.0';
$body_md5 = md5($body);
$string_to_sign =
"POST\n/apps/" . $app_id .
"/events\nauth_key=" . $key .
"&auth_timestamp=". $auth_timestamp .
"&auth_version=" . $auth_version .
"&body_md5=" . $body_md5;
$auth_signature = hash_hmac('sha256', $string_to_sign, $secret);
if($choice == 1){
$opts = array('http' =>
array(
'method'  => 'POST',
'header'  => "Content-Type: application/json\r\n",
'content' => $body,
)
);
$context  = stream_context_create($opts);
$url = 'http://api-'.$cluster.
'.pusher.com/apps/'.$app_id.
'/events?auth_key='.$key.
'&auth_timestamp='.$auth_timestamp.
'&auth_version=1.0&body_md5='.$body_md5.
'&auth_signature='.$auth_signature;
$result = file_get_contents($url, false, $context);
}
echo '<br>';
echo '<b>POST</b>';
echo '<br>';
echo 'url '.'http://api-'.$cluster.'.pusher.com/apps/'.$app_id.'/events';
echo '<br>';
echo '<b>Params</b>';
echo '<br>';
echo 'auth_key '.$key;
echo '<br>';
echo 'auth_timestamp '.$auth_timestamp;
echo '<br>';
echo 'auth_version '.$auth_version;
echo '<br>';
echo 'body_md5 '.$body_md5;
echo '<br>';
echo 'auth_signature '.$auth_signature;
echo '<br>';
echo '<b>Headers</b>';
echo '<br>';
echo 'Content-Type application/json';
echo '<br>';
echo '<b>Body</b>';
echo '<br>';
echo $body;
}}}}}}}
?>
</body>
</html>
============================================================
Разное
------------------------------------------------------------
https://pusher.com/  Сайт Pusher
https://github.com/indeedphp/pusherApiTest/blob/main/index.php Тест Pusher
============================================================
Видео номер 16
Laravel 10 + VUE.JS, подключаем, разбираемся, пробуем основы. Ларавел10 + ВЬЮ

В видео к фреймворку Ларавел 10 подключаем фреймворк для фронтэнда VUE.JS. Смотрим как работает сборщик VITE как сделать настройки, и произвести базовые действия такие как вывод, перебор, условие и AJAX запрос с сохранением в базу. Также минимально поработаем с CSS.



Использовано в видео:
============================================================
В консоли
------------------------------------------------------------
cd domains\vue //переходим в проект
node --version  // проверяем версию ноды, если нет то устанавливаем
npm --version  // проверяем версию npm
npm install   // проводим активацию, в проекте появляется папка ноды
npm i @vitejs/plugin-vue  // устанавливаем VUI
npm run build  // проводим сборку
npm run dev  // запускаем сборщика
npm i axios  // установка библиотеки axios
php artisan migrate // накатываем миграции
php artisan make:controller IndexController  // создаем контроллер
============================================================
В файле vite.config.js
------------------------------------------------------------
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [
vue(),
laravel({
input: [
'resources/css/app.css',
'resources/js/app.js',
],
refresh: true,
}),
],
});
============================================================
В файле app.js
------------------------------------------------------------
import './bootstrap';
import { createApp } from 'vue/dist/vue.esm-bundler';
import test from './test.vue';
createApp(test).mount('#app');
============================================================
В файле welcome.blade.php
------------------------------------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>vue</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
<div id="app"></div>
</body>
</html>
============================================================
В файле test.vue
------------------------------------------------------------
<template>
<h1 className="text">hello</h1>
<h1>{{text}}</h1>
<button type="button" @click="this.text = 'текст для заливки в переменную'" >Кнопка</button>
<button type="button" @click="getStart()" >Кнопка2</button>
<input type="text" v-model="text" name="name">
<h1 v-if="false">1 Выводим получая true</h1>
<h1 v-else-if="1==3">2 Выводим если это true</h1>
<h1 v-else>3 Выводим если не true</h1>
<div v-for="(el) in users">
<p>{{el}}</p>
</div>
</template>

<script>
export default {
data() {
return {
text: "текст из перемен",
users: ['1user', '2user', '3user']
}
},
methods: {
inputText() {
this.text = "через функцию меняем текст"
},
getStart() {
axios.post('/base', { email: 'bob2@bob.bob', password: '12345678', name: 'bob' });
}
}
}
</script>

<style scoped>
h1{
color:rgb(23, 1, 250)
}
.text{
color:rgb(231, 27, 37)
}
</style>
------------------------------------------------------------
axios.get('https://api.nationalize.io/?name=nathaniel', { headers: {'Access-Control-Allow-Origin': null,  // обходим CORS
'Access-Control-Allow-Headers': null, 'x-requested-with': null,} } ).then(function (response) {console.log(response);});
------------------------------------------------------------
axios.get('https://catfact.ninja/fact').then(response => (this.ax = response));  // работаем с апи
------------------------------------------------------------
axios.get('/base/?email=bob@bob.bob&password=12345678&name=bob'); // отправляем гет запрос с данными
============================================================
В роуте
------------------------------------------------------------
use App\Http\Controllers\IndexController;  // подключаем контроллер
------------------------------------------------------------
Route::get('/base', [IndexController::class, 'base']);
Route::post('/base', [IndexController::class, 'base2']);
============================================================
В контроллере
------------------------------------------------------------
use App\Models\User; // подключаем модель
------------------------------------------------------------
class IndexController extends Controller
{
public static function base(Request $request)
{
User::create($request->only(['email','password','name']));
return view('welcome');
}
public static function base2(Request $request)
{
User::create($request->only(['email','password','name']));
return view('welcome');
}
}
============================================================
В файле app.css
------------------------------------------------------------
body{ background: rgb(3, 71, 44);}
============================================================
Разное
------------------------------------------------------------
https://catfact.ninja/fact  // апи простой для тестов
https://www.youtube.com/@onecode_blog  // информация о подключении NODE.JS
============================================================
Видео номер 15
API на Ларавел 10 + ресурс, API & Resourse Laravel 10

В видео сделаем самое простое API на Ларавел 10, затем усложним, поработаем с базой данных, а так же с Ресурсом (очень удобный обработчик апи).



Использовано в видео:
============================================================
В консоли
------------------------------------------------------------
cd domains\resourse // переходим в проект
php artisan migrate // накатываем миграции
php artisan db:seed  // накатываем сиды (заполняем базу фейковыми данными)
php artisan make:resource UserResource  // создаем ресурс
php artisan make:resource UserResourceCollection // ресурс работающий с метаданными
php artisan make:controller ApiController  // создаем контроллер
============================================================
В API роутах
------------------------------------------------------------
Route::get('/', function () { // простешее апи из массива
return ['user' => 'bob'];
});
------------------------------------------------------------
Route::get('/', function () {  // апи, из базы берем все
return App\Models\User::all();
});
------------------------------------------------------------
Route::get('/{id}', function (string $id) {  // апи берем выборочно из базы
return App\Models\User::find($id);
});
------------------------------------------------------------
use App\Http\Controllers\ApiController;  // подключаем контроллер
Route::get('/', [ApiController::class, 'api']); // работаем через контроллер
============================================================
В контроллере
------------------------------------------------------------
use App\Models\User;
use App\Http\Resources\UserResource;
use App\Http\Resources\UserResourceCollection;
------------------------------------------------------------
public function api()  // выводим всех юзеров но только с колонками name email
{
$user = User::all('name', 'email');
return $user;
}
------------------------------------------------------------
public function api()  // обрабатываем ответ апи в цикле
{
$users = User::all();
foreach ($users as $user) {
$arr[$user->id] = [$user->name,$user->email];
}
return $arr;
}
------------------------------------------------------------
public function api()  // Работаем через ресурс без обработки или с отдельным обЪектом
{
return new UserResource(User::all());
}
------------------------------------------------------------
public function api()  // работаем через ресурс где обрабатываем коллекцию
{
return UserResource::collection(User::all());
}
------------------------------------------------------------
public function api()  // работаем с UserResourceCollection для мета данных
{
return new UserResourceCollection(User::all());
}
============================================================
В ресурсах UserResource
------------------------------------------------------------
public function toArray(Request $request): array
{
return [
'idNew' => $this->id,  // выбираем какие колонки нужны имя ключей и пр.
'nameText' => $this->name,
'emailMail' => $this->email,
];
}
============================================================
В ресурсах UserResourceCollection
------------------------------------------------------------
public function toArray(Request $request): array
{
return [
'meta' => [  // ставим метаданные различные
'if' => $this->when(1 == 1, function(){return 'ok';}),  // работаем с условием
'time' => now(),  // время
'test' => 'prived medved',  // текст
],
'data' => $this->collection,  // выводим коллекцию можно снизу или сверху
];
}
============================================================
разное
------------------------------------------------------------
use Illuminate\Http\Resources\Json\JsonResource; // в AppServiceProvider поключаем для работы с апи
JsonResource::withoutWrapping(); // удаляем обертку апи
JsonResource::wrap('test');  // делаем глобальную обертку
------------------------------------------------------------
public static $wrap = 'user';  // если необходимо переименовать обертку в ресурсе
============================================================
Видео номер 14
Уведомления в Ларавел 10, notification Laravel 10

Максимально быстро и доступно поработаем с нотификациями в Ларавел 10. Будем сохранять нотификации в базу, помечать просмотренные, выводить и удалять из базы.



Использовано в видео:
============================================================
В консоли
------------------------------------------------------------
cd domains\notification // переходим в проект
php artisan make:notification UserNotification  // команда создание нотификации
php artisan notifications:table  // создаем таблицу в базе для нотификации
php artisan migrate  // накатываем миграции
php artisan make:controller UserController  // создаем контроллер
------------------------------------------------------------
php artisan tinker   // запускаем тинкер
User::factory()->count(2)->create()  // создаем 2 фейковых юзера
exit  // выход из тинкера
==================================================
В файле нотификации UserNotification до работы с контроллером
------------------------------------------------------------
public function via(object $notifiable): array   {  // в методе указываем что работаем с базой данных
return ['database'];
}
------------------------------------------------------------
public function toArray(): array {  // то что полетит в базу
return [  'message'   =>  'prived medved'  ];
}
------------------------------------------------------------
В файле нотификации UserNotification работаем с контроллером
------------------------------------------------------------
public $text;
public function __construct($textController)
{
$this->text = $textController;
}
public function via(): array
{
return ['database'];
}
public function toArray(): array
{
return ['message'   =>  $this->text ];
}
============================================================
В роуте работаем без контроллера
------------------------------------------------------------
Route::get('/not', function () {
$user = App\Models\User::find(2);
$user->notify(new App\Notifications\UserNotification());
return view('welcome');
});
------------------------------------------------------------
В роуте работаем с контроллером
------------------------------------------------------------
use App\Http\Controllers\UserController;  // подключаем контроллер
Route::get('/not', [UserController::class, 'not']);  // создаем нотификации
Route::get('/notv', [UserController::class, 'notView']);  // показываем нотификации
Route::get('/notd', [UserController::class, 'notDel']);  // удаляем нотификации
============================================================
В контроллере
------------------------------------------------------------
use Illuminate\Support\Facades\Notification; // подключаем фасад нотификаций
use App\Notifications\UserNotification;  // подключаем нотификацию
use App\Models\User;  // подключаем модель

public function not()  // юзеру с ид 2 создаем нотификацию
{
$user = User::find(2);
Notification::send($user, new UserNotification('privet user'));
return view('welcome');
}
public function notView()  // выводим все новые нотификации
{
$user = User::find(2);
foreach ($user->unreadNotifications as $notification) {
print_r($notification->data);
$notification->markAsRead();  // помечаем нотификации что они просмотрены
echo '<br>';
}
return view('welcome');
}
public function notDel()  // удаляем все нотификации
{
$user = User::find(2);
$user->notifications()->delete();
return view('welcome');
}
============================================================
разное
------------------------------------------------------------
foreach ($user->notifications as $notification) // перебираем все нотификации, а не только просмотренные
use Notifiable;  // в модели должен быть подключен трейт
$user->unreadNotifications->markAsRead();  // помечаем всех кто есть в базе как обработанных
$user->unreadNotifications()->update(['read_at' => now()]);  // то же только запросов меньше в базу
============================================================
Видео номер 13
Простая регистрация, вход и выход в Laravel 10, аутентификация, авторизация Ларавел 10

В видео сделаем простейшую регистрацию вход и выход на сайте для того чтоб разобраться с технологией и применять если необходимо в начале нового проекта.



Использовано в видео:
============================================================
В консоли
------------------------------------------------------------
cd domains\login // переходим в проект
php artisan migrate // запускаем миграции
php artisan make:view login  // создаем вьюшку для входа
php artisan make:view register // создаем вьюшку для регистрации
php artisan make:view home  // создаем вьюшку для главной страницы
php artisan make:controller LoginController  // создание контроллера
============================================================
В роутах
------------------------------------------------------------
use App\Http\Controllers\LoginController;  // подключаем контроллер

Route::get('home', function () {
return view('home');
});
Route::get('/login', [LoginController::class, 'login'])->name('login');
Route::get('/register', [LoginController::class, 'register'])->name('register');

Route::post('/login', [LoginController::class, 'authentication'])->name('authentication');
Route::post('/register', [LoginController::class, 'registerCreate'])->name('registerCreate');

Route::get('/logout', [LoginController::class, 'logout'])->name('logout');
============================================================
В контроллере
------------------------------------------------------------
use Illuminate\Support\Facades\Auth;  // подключаем фасад авторизации
use App\Models\User;  // подключаем модель

class LoginController extends Controller
{

public function register(Request $request){
return view('register');
}

public function login(Request $request){
return view('login');
}

public function registerCreate(Request $request)
{
User::create($request->only(['email','password','name']));
return redirect('login');
}

public function authentication(Request $request)
{
$arr = $request->only(['email','password']);
Auth::attempt($arr);
return redirect('home');
}

public function logout(Request $request){
Auth::logout();
return redirect('home');
}

}
============================================================
В вюшке login
------------------------------------------------------------
<form method="POST" action="{{ route('authentication') }}">
@csrf
<label>Email</label>
<input type="email" name="email" value="">
<label>Пароль</label>
<input type="password" name="password" value="">
<button type="submit">отправить</button>
</form>
============================================================
В вюшке register
------------------------------------------------------------
<form method="POST" action="{{ route('registerCreate') }}">
@csrf
<label>name</label>
<input type="text" name="name" value="">
<label>Email</label>
<input type="email" name="email" value="">
<label>Пароль</label>
<input type="password" name="password" value="">
<button type="submit">отправить</button>
</form>
============================================================
В вюшке home
------------------------------------------------------------
<p>Главная страница </p>
@auth
<p>Привествуем! {{Auth::user()->name}}</p>
<p><a href="{{ route('logout') }}" >logout</a></p>
@else
<p><a href="{{ route('login') }}" >Login</a></p>
<p><a href="{{ route('register') }}" >Register</a></p>
@endauth
============================================================
Видео номер 12
Юнит и интеграционные тесты Ларавел 10, настраиваем базу, работаем с фабрикой и сидерами.

Поговорим об юнит и интеграционных тестах в Ларавел 10, посмотрим на примерах из обычной жизни чем они отличаются, проверим метод. Затем подключим тестовую и обычную базу данных, запишем в нее данные из фабрики и сидеров.



Использовано в видео:
============================================================
В консоли
------------------------------------------------------------
cd domains\unit // переходим в проект
php artisan make:test UserTest  // создание функционального теста (Feature)
php artisan make:test UserTest --unit  // создание юнит теста
php artisan test // запуск всех тестов
php artisan make:controller UserController  // создание контроллера
php artisan migrate // запускаем миграции
============================================================
В юнит тесте
------------------------------------------------------------
use App\Http\Controllers\UserController;  // подключаем контроллер
class UserTest extends TestCase
{
public function test_example(): void
{
$expected = 15;  // ожидаемый
$number = 10;
$UserController = new UserController;
$sum = $UserController->plus($number);
$this->assertEquals($expected, $sum);  // сравниваем
}
}
============================================================
В контроллере
------------------------------------------------------------
class UserController extends Controller
{
public function plus($number)
{
$numberPlus = $number + 5;
return $numberPlus;
}
}
============================================================
В интеграционном тесте
------------------------------------------------------------
use App\Models\User;  // подключаем модель
class UserDbTest extends TestCase
{
// use RefreshDatabase; // подключаем трейт очистки базы
public function test_example(): void
{
$user = User::factory()->create([  // создаем фейковую запись через фабрику
'name'=> 'bob'
]);
$likes = User::where('name', 'bob')->first();  // берем запись из базы с именем
// file_put_contents('file.txt', $likes->name);
$this->assertEquals('bob', $likes->name) ;  // проверяем на соответствие
}
}
============================================================
Разное
------------------------------------------------------------
.env.testing  // файл с настройками для тестирования
protected $seed = true;  // добавляем свойства в класс TestCase для сидеров
Видео номер 11
Ларавел 10 и JS AJAX работаем асинхронно получаем лайки и сохраняем в базе SQlite

В данном видео продолжим работать с хранилищем Ларавел, но теперь будем сохранять файлы в облаке Amazon S3 , так же сделаем вывод файлов на сайт и скачивание файлов к себе на компьютер с сайта, все будет показано максимально просто и без воды.



Использовано в видео:
cd domains/ajax // переходим в папку фреймворка
php artisan make:model Like --migration // создаем миграцию для таблицы лайк и модель к ней
php artisan migrate  // запускаем миграции
php artisan make:controller LikeController // создаем контроллер
/////////////////////ENV файл
DB_CONNECTION=sqlite  // настраиваем подключение к базе sqlite
/////////////////////Код для блейда
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<link rel="shortcut icon"href="favicon.ico">
<title>AJAX</title>
</head>
<body>

<h1>Название поста</h1>
<hr>
<h3>Заголовок</h3>
<hr>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. </p>
<hr>
<button id=butlike>like</button> &nbsp &nbsp
<nobr id=like>4</nobr> &nbsp &nbsp
<button id=butdislike>dislike</button> &nbsp &nbsp
<nobr id=dislike>2</nobr>

<script>
let flagl = 0;
let flagd = 0;
let like = document.querySelector('#like');
let dislike = document.querySelector('#dislike');
let butlike = document.querySelector('#butlike');
butlike.addEventListener('click', function () {
switch (flagl) {
case 0:
if (flagd == 1) {
dislike.textContent--;
flagd = 0;
}
like.textContent++;
flagl = 1;
fetch('/likes/?post=25&user=bob&like=1&dislike=0');
break;

case 1:
like.textContent--;
flagl = 0;
fetch('/likes/?post=25&user=bob&like=0&dislike=0');
break;

}
});

let butdislike = document.querySelector('#butdislike');
butdislike.addEventListener('click', function () {
switch (flagd) {
case 0:
if (flagl == 1) {
like.textContent--;
flagl = 0;
}
dislike.textContent++;
flagd = 1;
fetch('/likes/?post=25&user=bob&like=0&dislike=1');
break;

case 1:
dislike.textContent--;
flagd = 0;
fetch('/likes/?post=25&user=bob&like=0&dislike=0');
break;
}
});
</script>
</body>
</html>
//////////////////////////роуты
Route::get('/', [LikeController::class, 'view'])->name('view');
Route::get('/likes', [LikeController::class, 'likes'])->name('likes');
// Route::get('/likes/{post?}/{user?}/{like?}/{dislike?}', [LikeController::class, 'likes'])->name('likes');
//////////////////////////Контроллер
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Models\Like;

class LikeController extends Controller
{
public function view(Request $request)
{
return view('index');
}
public function likes(Request $request)
{
$likes = Like::where('post', 25)->first();
// info($request->get());
if(empty($likes)){
Like::create($request->only(['post','user','like','dislike']));
}
else{
$likes->update($request->only(['like','dislike']));
}
}
}
/////////////////////////////////////////модель
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Like extends Model
{
use HasFactory;

protected $fillable = [
'post',
'like',
'dislike',
'user',
];
}
//////////////////////////////////разное
public function likes($post,$user,$like,$dislike)
Like::create([
'post' => $post,
'user' => $user,
'like' => $like,
'dislike' => $dislike,
]);
fetch("{{route('likes', ['25', '2', '5', '8'])}}");
"{{route('likes', ['post' => '25', 'user' => 'bob', 'like' => '1', 'dislike' => '0'])}}"
//////////////////////////////////
Видео номер 10
Amazon S3 AWS хранилище в Ларавел 10, Amazon S3 Laravel 10, сохраняем, выводим и скачиваем файлы

В данном видео продолжим работать с хранилищем Ларавел, но теперь будем сохранять файлы в облаке Amazon S3 , так же сделаем вывод файлов на сайт и скачивание файлов к себе на компьютер с сайта, все будет показано максимально просто и без воды.



Использовано в видео:
cd domains/storage // переходим в папку фреймворка
composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies // устанавливаем пакет для S3
/////////////////////ENV файл
FILESYSTEM_DISK=s3

AWS_ACCESS_KEY_ID=(вставляем короткий код хранилища без скобок)
AWS_SECRET_ACCESS_KEY=(вставляем длинный код хранилища без скобок)
AWS_DEFAULT_REGION=us-east-1 // сервер хранилища (регион)
AWS_BUCKET=toseniorphp  // ведро внутри хранилища
AWS_USE_PATH_STYLE_ENDPOINT=true
//////////////////////меняем в config/filesystems.php
'default' => env('FILESYSTEM_DISK', 's3'),
'visibility' => 'public',  // добавляем в массив s3 строка для публичности файлов
/////////////////////Код для блейда
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>test</title>
</head>
<body>
<form class="m-5"  action="{{route('create')}}" method="post" enctype="multipart/form-data">
@csrf
<input type="file" name="image">
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
@foreach ($files as $file)
</br>
<img src="https://toseniorphp.s3.amazonaws.com/{{$file}}" width="250" alt="lorem">
</br>
<a href="{{route('download', ['path' => $file])}}">загрузить себе</a>
@endforeach
</body>
</html>
//////////////////////////роуты
Route::get('/', [IndexController::class, 'view'])->name('view');
Route::post('/', [IndexController::class, 'create'])->name('create');
Route::get('/download', [IndexController::class, 'download'])->name('download');
//////////////////////////Контроллер
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class IndexController extends Controller
{
public function view(Request $request)
{
$files = Storage::files('/public');
return view('index',compact('files'));
}
public function create(Request $request)
{
$image = $request->file('image');
$path = Storage::putFile('public', $image);
return view('index');
}
public function download(Request $request)
{
$path = $request->get('path');
return Storage::download($path);
}
}

Видео номер 9
Файловое хранилище в Ларавел 10, File Storage Laravel 10, сохраняем, выводим и скачиваем файлы

В видео максимально просто и быстро рассказывается об способе сохранения файлов на том же сервере что и сам фреймворк Ларавел, так же выведем файл на страницу и сделаем ссылку для загрузки файла обратно на пк.



Использовано в видео:
cd domains/storage // переходим в папку фреймворка
/////////////////////Код для блейда
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>test</title>
</head>
<body>
<form class="m-5"  action="{{route('create')}}" method="post" enctype="multipart/form-data">
@csrf
<input type="file" name="image">
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
</body>
</html>
////////////////////////////Для блейда добавляем вывод и загрузку
<img src="public/Br3FzUOqtEWytgl0kIjaxXVYhBVRiZI0MaFiLsJm.jpg" width="250" alt="lorem"></br>
<a href="{{route('download')}}">загрузить себе</a>
//////////////////////////роуты
Route::get('/', [IndexController::class, 'view'])->name('view');
Route::post('/', [IndexController::class, 'create'])->name('create');
Route::get('/download', [IndexController::class, 'download'])->name('download');
//////////////////////////Контроллер
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class IndexController extends Controller
{
public function view(Request $request)
{
return view('index');
}
public function create(Request $request)
{
$image = $request->file('image');
$path = Storage::putFile('public', $image);
return view('index');
}
public function download(Request $request)
{
return Storage::download('public/Br3FzUOqtEWytgl0kIjaxXVYhBVRiZI0MaFiLsJm.jpg');
}
}

Видео номер 8
События и слушатели в Ларавел 10, Events Listeners Laravel 10

В видео рассказывается о событиях во фреймворке Ларавел 10 которые помогут при разработке сайта.



Использовано в видео:
cd domains/demo // переходим в папку фреймворка
php artisan make:event TestEvent  // создаем событие
use App\Events\TestEvent;
event(new TestEvent('привед медвед')); // в контроллере вызываем событие
////////////// в событии создаем свойство и магический метод
public $text;
public function __construct($textController)
{
$this->text = $textController;
echo $this->text;
}
//////////////
php artisan make:listener TestEventListener --event=TestEvent //создаем слушателя
////////////в провайдере прописываем событие и слушателя
TestEvent::class => [
TestEventListener::class,
],
////////////в провайдере меняем false на true
public function shouldDiscoverEvents(): bool
{
return true;
}
////////////подключаем фасад базы
use Illuminate\Support\Facades\DB;
////////////
DB::table('users')->insertOrIgnore([
'name' => 'medved',
'email' => $event->text,
'password' => '12345678',
]);

Видео номер 7
SSL сертификат на Open Server, простой сайт и фреймворк с защищенным соединением https на Опен Сервер

В видео рассказывается об установке SSL сертификата для создания защищенного соединения https на Open Server которое подойдет для тестирования работы сайтов и пр. Установим ssl сертификат на простой сайт и фреймворк Laravel 10.


Использовано в видео:
ssl // в C:\OSPanel\ создаем папку ssl
start.bat config.txt // создаем два файла в папке
///////////////////////////////////файл start.bat
@echo off
set OPENSSL_CONF=c:\OSPanel\modules\http\Apache_2.4-PHP_8.0-8.1\conf\openssl.cnf
c:\OSPanel\modules\http\Apache_2.4-PHP_8.0-8.1\bin\openssl req -x509 -sha256 -newkey rsa:2048 -nodes -days 5475 -keyout rootCA.key -out rootCA.crt -subj "/CN=OSPanel/"
c:\OSPanel\modules\http\Apache_2.4-PHP_8.0-8.1\bin\openssl req -newkey rsa:2048 -nodes -days 5475 -keyout server.key -out server.csr -subj "/CN=PhpStorm/"
c:\OSPanel\modules\http\Apache_2.4-PHP_8.0-8.1\bin\openssl x509 -req -sha256 -days 5475 -in server.csr -extfile config.txt -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt
///////////////////////////////////файл config.txt
nsComment = "OSPanel Generated Certificate"
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

subjectAltName = @alt_names
[alt_names]
DNS.1 = trash   //правим только домен (trash) если необходимо
//////////////////////////////////////////////////////
запускаем файл start.bat
появляются 5 файлов сертификатов
В папке с файлами запускаем файл rootCA.crt
жмем установить сертификат
локальный компьютер
Доверенные коренные центры сертификации.
///////////////////////////
C:\OSPanel\userdata\config  // идем в папку
Apache_2.4-PHP_8.0-8.1_vhost.conf // правим файл
//////////////////////////////Apache_2.4-PHP_8.0-8.1_vhost.conf в файле правим пути
SSLCertificateFile "%sprogdir%/ssl/server.crt"
SSLCertificateKeyFile "%sprogdir%/ssl/server.key"
/////////////////////////
Перезапускаем опен сервер и возможно браузер.
/////////////////////////
В файле config.txt можно указать несколько доменов
DNS.1 = trash
DNS.2 = trash.net
DNS.3 = demo
DNS.4 = demo.com

Видео номер 6
Laravel 10, работа с очередями за 9 минут, Ларавел Queues

В видео максимально просто и быстро рассказывается про работу с очередями в ларавел 10 , как происходит подключение и создание очереди в базе, как она выполняется с помощью воркера , и что произойдет если будет ошибка выполнения.


Использовано в видео:
QUEUE_CONNECTION=database // изменения в .env файле фреймворка

cd domains\demo // переходим в папку фреймворка php artisan queue:table // создаем миграцию для таблицы в базе (create_jobs_table) php artisan migrate // запускаем миграцию и создается таблица (jobs) php artisan make:job TestJob // создаем папку Jobs с заданием TestJob
use App\Jobs\TestJob; // подключаем очередь в контроллер TestJob::dispatch(); // в котроллере запускаем очередь
sleep(15); // создаем задание для очереди , ждем 15 секунд dump('prived medved'); // пишем в консоль prived medved
php artisan queue:work // запускаем воркера в консоли
use Illuminate\Support\Facades\DB; // подключаем фасад базы данных sleep(10); // создаем второе задание для очереди , ждем 10 секунд DB::table('users')->insertOrIgnore([ // В таблицу users вносим запись 'name' => 'medved', // имя пользователя 'email' => 'medved@mail.com', // емайл 'password' => '12345678', // пароль ]);
php artisan queue:flush // удаляем все записи из таблицы failed_jobs
Видео номер 5
Ларавел это город? Фреймворк как город. Laravel is a city?

Чем больше изучаю фреймворк тем чаще замечаю что он похож на какой то город где есть дороги(роуты), мидлвееры(полиция) и так далее. Мысли привели к созданию данного видео для этого пришлось сделать сайт, придумать на кого похожи различные элементы фреймворка в реальной жизни, озвучить все и смонтировать.


lorem

Видео номер 4
Путь запроса в Ларавел 10, Request path to Laravel 10.

Для того чтоб узнать как в реальности проходит запрос в Ларавел 10 я вставил строку в файлы фреймворка с командой "выведи в браузер название файла и переведи строку", такой эксперимент помог лучше понять как устроен фрейворк, как проходит запрос, и какие файлы задействуются. Фрейворк используется только установленный с настроенной авторизацией.


Список файлов через которые прошел запрос:

index - указатель
autoload.php - автозагрузка
bootstrap\app - самозагрузка\приложения
Http\Kernel - Http\ядро
config\app - конфигурация\приложения
config\auth - конфигурация\авторизация
config\broadcasting - конфигурация\вещания
config\cache - конфигурация\кеш
config\cors - конфигурация\Совместное использование ресурсов разных источников
config\database - конфигурация\база данных
config\filesystems - конфигурация\файловые системы
config\hashing - конфигурация\хеширование
config\logging - конфигурация\Ведение журнала
config\mail - конфигурация\почта
config\queue - конфигурация\очереди по умолчанию
config\Sanctum - конфигурация\святилище :)
config\services - конфигурация\услуги
config\session - конфигурация\сессия
config\view - конфигурация\вид
bootstrap\cache\packages - самозагрузка\кеш\пакеты
bootstrap\cache\services - самозагрузка\кеш\услуги
Providers\AppServiceProvider - Посредники\Поставщик услуг приложений
Providers\AuthServiceProvider - Посредники\Поставщик услуг аутентификации
Providers\EventServiceProvider - Посредники\Поставщик услуг событий
Providers\RouteServiceProvider - Посредники\Поставщик услуг маршрутизации
Exceptions\Handler - Обработчик
routes/api
routes/web
ConfirmPasswordController - Подтверждение пароля контроллера
Controller - Контроллер
Middleware\TrustProxies - Посредники\Доверительные прокси
Middleware\PreventRequestsDuringMaintenance - Посредники\Запретить запросы во время обслуживания
Middleware\TrimStrings - Посредники\Обрезка строк
Middleware\EncryptCookies - Посредники\Шифрование файлов cookie
Middleware\VerifyCsrfToken - Посредники\Проверить токен CSRF
resources/views/welcome.blade
Список файлов которые я изменил:

echo 'index - указатель' . "<br>";
echo 'Console\Kernel - Ядро ' . "<br>";
echo 'Handler - Обработчик' . "<br>";
echo 'ConfirmPasswordController - Подтверждение пароля контроллера' . "<br>";
echo 'ForgotPasswordController - Контроллер забытого пароля' . "<br>";
echo 'LoginController - Контроллер входа' . "<br>";
echo 'RegisterController - Контроллер регистрации' . "<br>";
echo 'ResetPasswordController - Контроллер сброса пароля' . "<br>";
echo 'VerificationController - Контроллер проверки' . "<br>";
echo 'Controller - Контроллер' . "<br>";
echo 'HomeController - Домашний контроллер' . "<br>";
echo 'Middleware\Authenticate - Посредники\Аутентификация' . "<br>";
echo 'Middleware\EncryptCookies - Посредники\Шифрование файлов cookie' . "<br>";
echo 'Middleware\PreventRequestsDuringMaintenance - Посредники\Запретить запросы во время обслуживания' . "<br>";
echo 'Middleware\RedirectIfAuthenticated - Посредники\Перенаправление при аунтетификации' . "<br>";
echo 'Middleware\TrimStrings - Посредники\Обрезка строк' . "<br>";
echo 'Middleware\TrustHosts - Посредники\Доверительные хосты' . "<br>";
echo 'Middleware\TrustProxies - Посредники\Доверительные прокси' . "<br>";
echo 'Middleware\ValidateSignature - Посредники\Подтвердить подпись' . "<br>";
echo 'Middleware\VerifyCsrfToken - Посредники\Проверить токен CSRF' . "<br>";
echo 'Http\Kernel - Http\ядро' . "<br>";
echo 'Providers\AppServiceProvider - Посредники\Поставщик услуг приложений' . "<br>";
echo 'Providers\AuthServiceProvider - Посредники\Поставщик услуг аутентификации' . "<br>";
echo 'Providers\BroadcastServiceProvider - Посредники\Поставщик услуг вещания' . "<br>";
echo 'Providers\EventServiceProvider - Посредники\Поставщик услуг событий' . "<br>";
echo 'Providers\RouteServiceProvider - Посредники\Поставщик услуг маршрутизации' . "<br>";
echo 'bootstrap\cache\packages - самозагрузка\кеш\пакеты' . "<br>";
echo 'bootstrap\cache\services - самозагрузка\кеш\услуги' . "<br>";
echo 'bootstrap\app - самозагрузка\приложения' . "<br>";
echo 'config\app - конфигурация\приложения' . "<br>";
echo 'config\auth - конфигурация\авторизация' . "<br>";
echo 'config\broadcasting - конфигурация\вещания' . "<br>";
echo 'config\cache - конфигурация\кеш' . "<br>";
echo 'config\cors - конфигурация\Совместное использование ресурсов разных источников' . "<br>";
echo 'config\database - конфигурация\база данных' . "<br>";
echo 'config\filesystems - конфигурация\файловые системы' . "<br>";
echo 'config\hashing - конфигурация\хеширование' . "<br>";
echo 'config\logging - конфигурация\Ведение журнала' . "<br>";
echo 'config\mail - конфигурация\почта' . "<br>";
echo 'config\queue - конфигурация\очереди по умолчанию' . "<br>";
echo 'config\Sanctum - конфигурация\святилище :)' . "<br>";
echo 'config\services - конфигурация\услуги' . "<br>";
echo 'config\session - конфигурация\сессия' . "<br>";
echo 'config\view - конфигурация\вид' . "<br>";
echo 'factories\UserFactory - Пользовательская фабрика' . "<br>";
echo 'seeders\DatabaseSeeder - Сеялка баз данных :)' . "<br>";
echo 'resources/views/confirm.blade' . "<br>";
echo 'resources/views/email.blade' . "<br>";
echo 'resources/views/reset.blade' . "<br>";
echo 'resources/views/login.blade' . "<br>";
echo 'resources/views/register.blade' . "<br>";
echo 'resources/views/verify.blade' . "<br>";
echo 'resources/views/app.blade' . "<br>";
echo 'resources/views/home.blade' . "<br>";
echo 'resources/views/welcome.blade' . "<br>";
echo 'routes/api' . "<br>";
echo 'routes/channels' . "<br>";
echo 'routes/console' . "<br>";
echo 'routes/web' . "<br>";
echo 'storage/framework/views/045d02fcc39734e93edab1b3c8fb77b3' . "<br>";
echo 'storage/framework/views/17e80aa32d0ee374c02b8832cdd8af36' . "<br>";
echo 'storage/framework/views/287c07017ea2567ec87ba2eb21e1f3bc' . "<br>";
echo 'storage/framework/views/3650c7f6ccad78a9d8a693949063ab1f' . "<br>";
echo 'storage/framework/views/8beaedcff1c0fc8562109791677174a0' . "<br>";
echo 'storage/framework/views/b1bc13618210fb145ee21ff8b62fb6a9' . "<br>";
echo 'storage/framework/views/b8c27f0c48b062be31d99b684996ddd8' . "<br>";
echo 'tests/Feature/ExampleTest' . "<br>";
echo 'tests/Unit/ExampleTest' . "<br>";
echo 'tests/CreatesApplication' . "<br>";
echo 'tests/TestCase' . "<br>";

Видео номер 3
Стандартная аутентификация Ларавель 10, подключение, ошибки после установки. Authentication Laravel 10.

Подключаем стандартную встроенную аунтетификацию в Ларавель 10 старым пакетом который мало весит и с ним легко разобратся, подключаем базу данных MySQL phpMyAdmin к проекту, устраняем ошибку после подключения аунтетификации.


Команды для консоли и ссылки использованные в видео:
cd domains\demo // переходим в папку фреймворка, если у вас другая папка с фреймворком то выбирайте ее
composer require laravel/ui // устанавливаем необходимые для аунтетификации плагины
php artisan ui:auth // создаем шаблон аутентификации (регистроции)
https://getbootstrap.ru/docs/5.3/getting-started/download/ // ссылка на bootstrap
href="css\bootstrap.min.css" // адрес подключения файл CSS
src="js\bootstrap.bundle.min.js"> // адрес подключения файл JS
php artisan migrate // создание минимального набора таблиц в базе

Команды для консоли актуального стартового набора аунтетефикации:
composer require laravel/breeze --dev // загрузка актуального стартового набора аутентификации
php artisan breeze:install // установка

Видео номер 2
Установка Ларавель 10 на Опен Сервер. Installation Laravel 10 on Open Server.

Часто установку Ларавель показывают с артисан сервером, но это неудобно так как необходимо каждый раз вводить команду для подключения сервера в консоли, так же у начинающих разработчиков нет понимания как ставить в последствии Ларавель на сервер. На этом видео установка идет так как бы она была на сервере в интернете, что облегчает понимание данного фреймворка.


Команды для консоли использованные в видео:
php --version // узнать в консоли версию PHP
composer --version // узнать версию Composer
https://getcomposer.org // узнать версию Composer на сайте
composer self-update // обновить Composer
cd domains // переходим в папку сервера для установки Laravel
composer create-project laravel/laravel demo // устанавливаем Laravel в папку domains
cd demo // переходим в папку demo с Laravel
cd domains\demo // сразу переходим в папку demo с Laravel
php artisan --version // проверяем версию Laravel

Видео номер 1
Саблайн текст и Ларавель 10 нагружает процессор. Laravel и Sublime Text высокая загрузка.

Данное видео связано с проблемой излишней нагрузке процессора компьютера при работе в Sublime Text Для устранения этой проблемы в настройки нужно добавить эту строку в настройку Sublime Text.


"index_files": false