Страница 1 из 1

Веб-сокеты

Добавлено: 21 май 2025, 13:10
ya
Список доступных версий веб-сокетов:

Код: Выделить всё

composer show beyondcode/laravel-websockets --all
Поменять "minimum-stability": "stable" на "minimum-stability": "beta"
composer.json

Код: Выделить всё

{
  "minimum-stability": "beta",
  "prefer-stable": true
}
Очистить кэш композера

Код: Выделить всё

composer clear-cache
Обновить композер

Код: Выделить всё

composer update
Установка веб-сокета

Код: Выделить всё

composer require beyondcode/laravel-websockets:^2.0 --with-all-dependencies

Re: Веб-сокеты

Добавлено: 22 май 2025, 04:16
ya
https://www.youtube.com/watch?v=rmlGQagOmck

Стартовые компоненты
https://laravel.com/docs/12.x/starter-kits

Код: Выделить всё

composer require laravel/breeze --dev
php artisan breeze/install vue
php artisan migrate
Подключение сокета на бэкэнд
https://pusher.com
https://packagist.org/packages/pusher/pusher-php-server

Код: Выделить всё

composer require pusher/pusher-php-server
https://stackoverflow.com/questions/45052853/class-pusher-not-found
config/app.php

Код: Выделить всё

...
'Pusher' => Pusher\Pusher::class,
...
./env

Код: Выделить всё

...
BROADCAST_DRIVER=pusher
...
Подключение сокета на фронтэнд
https://laravel.com/docs/12.x/broadcasting

Код: Выделить всё

npm install --save-dev laravel-echo pusher-js
Для того чтобы работать с веб-сокетом, нужно создать событие с суффиксом Event
Создадим контроллер MessageController.php и событие StoreMessageEvent

Код: Выделить всё

php artisan make:controller MessageController
php artisan make:event StoreMessageEvent
В контроллер добавить событие класса StoreMessageEvent в метод store:
app/Http/Controllers/MessageController.php

Код: Выделить всё

class MessageController extends Controller
{
	public function index()
	{
		$messages = Message::latest()->get();
		$messages = MessageResource::collection($messages)->resolve();
		return intertia(component: 'Message/Index', compact(var_mane: 'messages'));
	}
	public function store(StoreRequest $request)
	{
		$data = $request->validated();
		message = Message::create($data);
		
		broadcast(new StoreMessageEvent($message))->toOthers();
		
		return MessageResource::make($message)->resolve();
	}
}
Для класса события StoreMessageEvent добавить интерфейс ShouldBroadcast
app/Events/StoreMessageEvent.php

Код: Выделить всё

...
class StoreMessageEvent implements ShouldBroadcast
{
...
	private message;
	public function __construct(Message $message)
	{
		$this->message=$message;
	}
...
метод broadcastOn создаёт каналы: приватный или публичный
app/Events/StoreMessageEvent.php

Код: Выделить всё

public function broadcastOn(): array
{
	return [new PrivateChannel(name: 'store_message'), new Channel(name: 'channel_name2')];
} 
добавить метод именования каналов для передачи сообщений через сокет
app/Events/StoreMessageEvent.php

Код: Выделить всё

...
public function broadcastAs(): string
{
    return 'store_message';
}
public function broadcastWith(): array
{
    //return ['id' => $this->user->id];
    return ['message' => MessageResource::make($this->message)->resolve()];
}
...
resources/js/Pages/Message/index.vue

Код: Выделить всё

...
created()
{
	window.Echo.channel('store_message')
	.listen('.store_message', res=> { this.messages.unshift(res.data) })
},
...
Маршруты:
routes/web.php

Код: Выделить всё

...
Route::get(uri: '/dashboard', function())
{
	return Intertia::render(component: 'Dashboard');
})->middleware(['auth', 'verifed'])->name(name: 'dashboard');

Route::middleware(midleware: 'auth')->group(function () {
	Route::get(uri: 'messages', [\App\Http\Controllers\MessageController::class, 'index']);
	Route::post(uri: 'messages', [\App\Http\Controllers\MessageController::class, 'store']);
	
	Route::get(uri: '/users/{user}', [\App\Http\Controllers\UserController::class, 'show']);
	
	Route::get(uri: '/profile', [ProfileController::class, 'edit'])->name(name: 'profile.edit');
	Route::patch(uri: '/profile', [ProfileController::class, 'update'])->name(name: 'profile.update');
	Route::delete(uri: '/profile', [ProfileController::class, 'destroy'])->name(name: 'profile.destroy');
});

require __DIR__.'/auth.php';

Re: Веб-сокеты

Добавлено: 22 май 2025, 07:10
ya
Адресный канал сокета (от конкретного пользователя, к конкретному пользователю)

Создадим контроллер UserController

Код: Выделить всё

php artisan make:controller UrerController
Добавим соответствующий маршрут
routes/web.php

Код: Выделить всё

...
Route::get(uri: '/users/{user}', [\App\Http\Controllers\UserController::class, 'show']);
...
app/Http/Controllers/UserController.php

Код: Выделить всё

<?php
namespace App\Http\Controllers
class UserController extends Controller
{
	public function show(User $user)
	{
		return inertia(component: 'User/Show', compact(var_name: 'user'));
	}
	public function sendLike(User $user, SendLikeRequest $request)
	{
		$data = $request->validated();
		$likeStr = 'Your like from user with id ' . $data['from_id'];
		
		broadcast(new SendLikeEvent($likeStr, $user->id))->toOthers();
		
		return response()->json([
			'like str' => $likeStr
		]);
	}
resources/js/Pages/User/Show.vue

Код: Выделить всё

<templates>
	<div class="p-6 w-1/3 mx-auto">
		<div class="mb-4">
			User {{ user.name }}
		</div>
		<div class="mb-4">
			<a @click.prevent="sendLike" href="#" class="rounded-gl block w-48 bg-sky-400 text-white text-center py-2">Send Like</a>
		</div>
		<div v-if="like_str">
			{{ like_str }}
		</div>
	</div>
</templates>

<script>
	export default
	{
		name: "Show" ,
		props: [
			'user'
		],
		data() {
			return {
				like_str: ''
			}
		},
		//created() {
		//	console.log(this.$page.props.auth.user.id);
		//},
		created() {
			window.Echo.channel(`send_like_${this.$page.props.auth.user.id}`)
			.listen('.send_like', res => {
		//		console.log(res);
				this.like_str = res.like_str
			})
		},
		methods: {
			sendLike(){
				axios.post(`/users/${this.user.id}`, {from_id: this.$page.props.auth.user.id})
				.then(res => {
					this.like_str = res.data.like_str
				})
			}
		}
	}
</script>

<style scoped>
</style>
Маршруты:
routes/web.php

Код: Выделить всё

...
Route::get(uri: '/dashboard', function())
{
	return Intertia::render(component: 'Dashboard');
})->middleware(['auth', 'verifed'])->name(name: 'dashboard');

Route::middleware(midleware: 'auth')->group(function () {
	Route::get(uri: 'messages', [\App\Http\Controllers\MessageController::class, 'index']);
	Route::post(uri: 'messages', [\App\Http\Controllers\MessageController::class, 'store']);
	
	Route::get(uri: '/users/{user}', [\App\Http\Controllers\UserController::class, 'show']);
	Route::post(uri: '/users/{user}', [\App\Http\Controllers\UserController::class, 'sendLike']);
	
	Route::get(uri: '/profile', [ProfileController::class, 'edit'])->name(name: 'profile.edit');
	Route::patch(uri: '/profile', [ProfileController::class, 'update'])->name(name: 'profile.update');
	Route::delete(uri: '/profile', [ProfileController::class, 'destroy'])->name(name: 'profile.destroy');
});

require __DIR__.'/auth.php';
routes/channels.php

Код: Выделить всё

...
Broadcast::channel(channel: 'App.Models.User.{id}', function ($user, $id) {
	return (int) $user->$id === (int) $id;
});
создаём метод запроса User/SendLikeRequest для контроллера UserController

Код: Выделить всё

php artisan make:request User/SendLikeRequest
app/Http/Requests/User/SendLikeRequest

Код: Выделить всё

<?php
namespace App\Http\Requests\User;
use Illuminate\Foundation\Http\FormRequest;
class SendLikeRequest extends FormRequest
{
	public function authorize():bool
	{
		return true;
	}
	public function rules(): array
	{
		return [
			'from_id' => 'required|integer|exists:users,id'
		];
	}
}
создадим событие SendLikeEvent

Код: Выделить всё

php artisan make:event SendLikeEvent
Добавляем интерфейс ShouldBroadcast для класса SendLikeEvent
app/Events/SendLikeEvents.php

Код: Выделить всё

<?php
namespace App\Events;
use ...
class SendLikeEvents implements ShouldBroadcast
{
	use Dispatchable, InteractsWithSockets, SerializesModels;
	private string $likeStr;
	private int $userId;
	public function __construct(string $likeStr, int $userId)
	{
		$this->likeStr = $likeStr;
		$this->userId = $userId;
	}
	public function broacastOn(): array
	{
		return [new Channel(name: 'send_like_' . $this->userId)];
	}
	public function broadcastAs(): string
	{
    		return 'send_like';
	}
	public function broadcastWith(): array
	{
    		return ['like_str' => $this->likeStr];
	}
}

Re: Веб-сокеты

Добавлено: 22 май 2025, 09:02
ya
Приватный адресный канал сокета

раскомментировать
config/app.php

Код: Выделить всё

...
App\Providers\EventServiceProvider::class,
...
Заменить Channel на PrivateChannel
app/Events/SendLikeEvents.php

Код: Выделить всё

<?php
...
	public function broacastOn(): array
	{
		return [new Channel(name: 'send_like_' . $this->userId)];
	}
...
Заменить channel на private
resources/js/Pages/User/Show.vue

Код: Выделить всё

...
		created() {
			window.Echo.channel(`send_like_${this.$page.props.auth.user.id}`)
			.listen('.send_like', res => {
		//		console.log(res);
				this.like_str = res.like_str
			})
		},
		...
		

добавляем канал send_like_{id}
routes/channels.php

Код: Выделить всё

...
Broadcast::channel(channel: 'App.Models.User.{id}', function ($user, $id) {
	return (int) $user->$id === (int) $id;
});
Broadcast::channel(channel: 'send_like_{id}', function ($user, $id) {
	return (int) $user->$id === (int) $id;
});

Re: Веб-сокеты

Добавлено: 22 май 2025, 09:17
ya
https://beyondco.de/docs/laravel-websockets/getting-started/introduction
Установка:
https://beyondco.de/docs/laravel-websockets/getting-started/installation

.env

Код: Выделить всё

...
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=1
PUSHER_APP_KEY=some
PUSHER_APP_SECRET=some
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=eu
PUSHER_HOST=127.0.0.1
...
config/broadcasting.php

Код: Выделить всё

<?php

return [

    'default' => env('BROADCAST_DRIVER', 'pusher'),

    'connections' => [

        'pusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'useTLS' => false,
            ],
        ],

        // Другие драйверы, если нужно
        'redis' => [
            'driver' => 'redis',
        ],

        'log' => [
            'driver' => 'log',
        ],

        'null' => [
            'driver' => 'null',
        ],

    ],

];
После создания файлов конфигурации, очистить кэш конфигурации

Код: Выделить всё

composer dump-autoload
php artisan config:cache
Использование очередей и всё это писать в таблицы базы данных MySQL

Код: Выделить всё

php artisan queue --help
php artisan queue:table
php artisan migrate
.env

Код: Выделить всё

...
QUEUE_CONNECTION=database
...
Заменить интерфейс для события. Вместо ShouldBroadcast , заменить на ShouldBroadcastNow
app/Events/SendLikeEvent.php

Код: Выделить всё

...
class SendLikeEvent implements ShouldBroadcastNow
...