Laravel Livewire Message only to a specific user - laravel

I took over a working chat application. to send a message, the original code uses a user list, which then checks whether a message exists.
In this case, it will redirect to the chat blade. If not, a new message will be created and then redirected to Chat blade.
Github to the app
https://github.com/thee-king-yodah/laravel-livewire-chat-message-application
I would like to change this and use a button on a profile page, but I'm currently working on the implementation and get stuck.
If I add the livewire into my blade it list a button for all users.
Controller: CreateChat
namespace App\Http\Livewire\Chat;
use Livewire\Component;
use App\Models\User;
use App\Models\Conversation;
use App\Models\Message;
use GuzzleHttp\Promise\Create;
use Illuminate\Support\Carbon;
use App\Http\Livewire\Chat\ChatList;
class CreateChat extends Component
{
public $users;
public $message= 'Start';
public function checkconversation($receiverId)
{
//dd($this->spieler);
$checkedConversation = Conversation::where('receiver_id', auth()->user()->id)
->where('sender_id', $receiverId)
->orWhere('receiver_id', $receiverId)
->where('sender_id', auth()->user()->id)->get();
if (count($checkedConversation) == 0) {
//dd('no conversation');
$createdConversation= Conversation::create(['receiver_id'=>$receiverId,'sender_id'=>auth()->user()->id,'last_time_message'=>Carbon::now()]);
$createdMessage= Message::create(['conversation_id'=>$createdConversation->id,'sender_id'=>auth()->user()->id,'receiver_id'=>$receiverId,'body'=>$this->message]);
$createdConversation->last_time_message= $createdMessage->created_at;
$createdConversation->save();
return redirect()->to('/chat');
//dd($createdMessage);
//dd('saved');
} else if (count($checkedConversation) >= 1) {
return redirect()->to('/chat');
//dd('conversation exists');
}
# code...
}
public function render()
{
$this->users = User::where('id','!=',auth()->user()->id)->get();
return view('livewire.chat.create-chat');
}
Create-chat.blade
<div>
<div class="flex justify-center">
<div class="bg-white rounded-lg border border-gray-200 w-96 text-gray-900">
<ul role="list" class="">
#foreach($users as $user)
<div class="flex justify-center mb-2 mt-4">
<button type="button" class="inline-block align-middle text-center select-none border font-normal whitespace-no-wrap rounded py-1 px-3 leading-normal no-underline text-blue-600 border-blue-600 hover:bg-blue-600 hover:text-white bg-white hover:bg-blue-600 ms-1"
wire:click='checkconversation({{ $user->id }})'>Nachricht</button>
</div>
#endforeach
</ul>
</div>
</div>
</div>
Controller Profile
amespace App\Http\Livewire;
use Livewire\Component;
use App\Models\User;
use Illuminate\Support\Carbon;
class Playerprofil extends Component
{
public $player;
public function render()
{
return view('livewire.playerprofile', [
'player' => $this->player,
]);
}
public function mount($id)
{
$this->player= User::find($id);
}
Profil.blade
<div>
#livewire('chat.create-chat' )
</div>
I would be very grateful if someone could help m out.

It's solved.
Controller: CreateChat
added mount
public function mount()
{
$this->users = User::find($this->user_id);
}
removed foreach in CreateChat.blade
<div>
#livewire('chat.create-chat', ['user_id' => $player->id ])
</div>

Related

Toggle switch for Model field Livewire

I'm trying to implement a slider checkbox that automatically updates a field in my Post column.
Here's my css
.toggle-checkbox:checked {
#apply: right-0 border-green-400;
right: 0;
border-color: #68D391;
}
.toggle-checkbox:checked + .toggle-label {
#apply: bg-green-400;
background-color: #68D391;
}
And this is my toggle button component
namespace App\Http\Livewire\Admin\Table;
use Illuminate\Database\Eloquent\Model;
use Livewire\Component;
class Published extends Component
{
public Model $model;
public string $field;
public bool $isPublished;
public function mount()
{
$this->isPublished = (bool) $this->model->getAttribute($this->field);
}
public function render()
{
return view('livewire.admin.table.published');
}
public function updating($field, $value)
{
$this->model->setAttribute($this->field, $value)->save();
}
}
This is my blade for the toggle button
<div>
<div class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in bg-red-300">
<input wire:model="isPublished" type="checkbox" name="toggle" id="toggle" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer" />
<label for="toggle" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
</div>
</div>
This is the parent component for the toggle button
#foreach ($values as $value)
<td class="px-4 py-3">
#livewire('admin.table.published', ['model' => $value, 'field' => 'status'], key($value->id))
</td>
#endforeach
mount method seems to work fine, but whenever I try the updating method, it updates a different ID. Can anyone help? Thanks!
I'm using Php 7.3 ; Laravel 8.75; livewire 2.10

array_merge(): Expected parameter 2 to be an array, null given pusher laravel

I'm trying to learn how to work with events and pusher, I've started with something very simple
I am working with laravel 8 livewire.
From pusher to view it works fine, but when I call the event from the component I get the error :
https://flareapp.io/share/dmkzeG65#F77
View:
<div>
<div class="mt-20 col-span-2 editor mx-auto w-10/12 flex flex-col text-gray-800 border border-gray-300 p-4 shadow-lg max-w-2xl rounded">
<textarea id="mensaje" wire:model="mensaje" class="mt-4 rounded description bg-gray-100 sec p-3 h-20 border border-gray-300 outline-none" spellcheck="false" placeholder="Aqui dispones la oportunidad de argumentar tu opiniĆ³n."></textarea>
<div class="buttons flex mt-2">
<div class="btn border border-gray-300 p-1 px-3 font-semibold cursor-pointer text-gray-500 ml-auto">
Cancel
</div>
<button wire:click="enviarMensaje" class="btn border border-indigo-500 p-1 px-3 font-semibold cursor-pointer text-gray-200 ml-2 bg-indigo-500" type="submit">
Comentar
</button>
</div>
#error('mensaje') <small class="text-red-600">{{$message}}</small> #enderror
</div>
<script>
// Enable pusher logging - don't include this in production
Pusher.logToConsole = true;
var pusher = new Pusher('d1fc007f6e1d80963c33', {
cluster: 'eu'
});
var channel = pusher.subscribe('my-channel');
channel.bind('my-event', function(data) {
alert(JSON.stringify(data));
});
</script>
</div>
LIVEWIRE COMPONENT
<?php
namespace App\Http\Livewire;
use App\Events\Mensaje;
use Livewire\Component;
use App\Events\EnviarMensaje;
use App\Events\SendMessage;
class ChatForm extends Component
{
public $mensaje;
public function mount()
{
$this->mensaje = '';
}
public function enviarMensaje()
{
event(new SendMessage($this->mensaje));
}
public function render()
{
return view('livewire.chat-form');
}
}
EVENT
<?php
namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class SendMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public function __construct($message)
{
$this->message = $message;
}
public function broadcastOn()
{
return ['my-channel'];
}
public function broadcastAs()
{
return 'my-event';
}
}
I look forward to your help. Thank you very much for your help.
This error was resolved in the pusher-http-php library v5.0.1 and Laravel v8.29.0. https://github.com/pusher/pusher-http-php/issues/288
Alternatively you can use pusher-http-php v4.1
composer require pusher/pusher-php-server ^4.1

Livewire throwing error when using paginated data

So I am being given this error when trying to paginate my data and send it in to a view through a livewire component.
I am trying to get all posts and display at max 5 posts per page using pagination in laravel.
Livewire version: 2.3.1
Laravel version: 8.13.0
Error:
Livewire\Exceptions\PublicPropertyTypeNotAllowedException
Livewire component's [user-posts] public property [posts] must be of type: [numeric, string, array, null,
or boolean]. Only protected or private properties can be set as other types because JavaScript doesn't
need to access them.
My Component:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Post;
use Livewire\WithPagination;
class UserPosts extends Component
{
use WithPagination;
public $posts;
public $type;
protected $listeners = ['refreshPosts'];
public function delete($postId)
{
$post = Post::find($postId);
$post->delete();
$this->posts = $this->posts->except($postId);
}
public function render()
{
if($this->type == 'all')
$this->posts = Post::latest()->paginate(5);
else if($this->type == 'user')
$this->posts = Post::where('user_id',Auth::id())->latest()->paginate(5);
return view('livewire.user-posts', ['posts' => $this->posts]);
}
}
My Blade:
<div wire:poll.5s>
#foreach($posts as $post)
<div style="margin-top: 10px">
<div class="post">
<div class="flex justify-between my-2">
<div class="flex">
<h1>{{ $post->title }}</h1>
<p class="mx-3 py-1 text-xs text-gray-500 font-semibold"
style="margin: 17px 0 16px 40px">{{ $post->created_at->diffForHumans() }}</p>
</div>
#if(Auth::id() == $post->user_id)
<i class="fas fa-times text-red-200 hover:text-red-600 cursor-pointer"
wire:click="delete({{$post->id}})"></i>
#endif
</div>
<img src="{{ asset('image/banner.jpg') }}" style="height:200px;"/>
<p class="text-gray-800">{{ $post->text }}</p>
#livewire('user-comments', [
'post_id' => $post->id,
'type' => 'all'
],
key($post->id)
)
</div>
</div>
#endforeach
{{ $posts->links() }}
</div>
$posts should not be declared as a property in the Livewire component class, you passed the posts with the laravel view() helpers as data.
Remove the line
public $posts;
And replace $this->posts by $posts in the render function:
public function render()
{
if($this->type == 'all')
$posts = Post::latest()->paginate(5);
else if($this->type == 'user')
$posts = Post::where('user_id',Auth::id())->latest()->paginate(5);
return view('livewire.user-posts', ['posts' => $posts]);
}
}

How to send variable from blade to controller without changing the url

In blade I have a list of books. I want to choose a specific book to show its information. And to do so I want to send with href the id of the book to my controller passing through route.
For example i have
<div class="body text-center">
<h6><b>{{($book->getName())}}</b></h6>
</div>
In href I want to add $bookId = $book->id and the route name so I can call the route with the specific name which calls a method in a controller which can use the variable $bookId
Route::get('/infromation','Books\BookController#index')->name('info');
Here's two propositions:
The first one is to use spatie/laravel-sluggable to have the book name in the URL
The second one is to access the book without changing the URL with a POST request
Using spatie/laravel-sluggable
The slug will be generated automatically from name when the book is created.
your-migration.php
Schema::create('books', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('slug')->unique()->index();
$table->string('name');
// ...
$table->timestamps();
});
web.php
// Change the URIs as you want. `{book}` is mandatory to retrieve the book though.
Route::get('/books','Books\BookController#index')->name('book.index');
Route::get('/books/{book}','Books\BookController#show')->name('book.show');
Book.php
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;
class Book extends Model
{
use HasSlug;
protected $guarded = [];
public function getSlugOptions()
{
// Adapt with what you want
return SlugOptions::create()
->generateSlugsFrom('name')
->saveSlugsTo('slug')
->doNotGenerateSlugsOnUpdate();
}
public function getRouteKeyName()
{
return 'slug';
}
}
BookController.php
class BookController extends Controller
{
public function index()
{
return view('book.index');
}
public function show(Book $book)
{
// $book is retrieving using Model Binding: https://laravel.com/docs/5.8/routing#route-model-binding
return view('book.show', compact('book'));
}
}
index.blade.php
<div class="body text-center">
<a href="{{ route('book.show', $book) }}">
<h6><b>{{ $book->getName() }}</b></h6>
</a>
</div>
Using POST request (URI does not change) and without SLUG
I wouldn't recommend using this for the user experience.
The user cannot bookmark the book or share the link with someone else
When refreshing the page, it will prompt to the user if he want to re-submit the form request
web.php
Route::get('/books','Books\BookController#index')->name('book.index');
Route::post('/books','Books\BookController#show')->name('book.show');
BookController.php
class BookController extends Controller
{
public function index()
{
return view('book.index');
}
public function show()
{
$book = Book::findOrFail(request('book_id'));
return view('book.show', compact('book'));
}
}
index.blade.php
<div class="body text-center">
<form action="{{ route('book.show') }}" method="POST">
#csrf
<input type="hidden" value="{{ $book->id }}" name="book_id">
<h6>
<button type="submit">
<b>{{ $book->getName() }}</b>
</button>
</h6>
</form>
</div>
You can remove the default button style to make it looks like a link
https://stackoverflow.com/a/45890842/8068675
You can try like this
<form action="/BookName/information/<?php echo $book->id; ?>" method="post">
<div class="body text-center">
<input type="hidden" name="book_id" value="{{ $book->id }}">
<a href="/information/<?php echo $book->id; ?>">
<button type="submit" name="book_information" class="btn btn-primary">
<h6>
<b>{{($book->getName())}}</b>
</h6>
</button>
</div>
</form>
// make route like this
Route::post('/BookName/information/{id}','Books\BookController#index');
// Access the that id in controller
public function index(Request $request)
{
echo $request->book_id;
}

Individual profile pages and searches Laravel 5.2

Having a real confusing time with this project, my issue is I'm trying to get my search working but for some reason its not pulling results from my query when there is that information in the database, also when I click on the username in the top corner of my page, it should redirect to the user page but instead I get this error "NotFoundHttpException in Application.php line 879:" with the URl looking like this "http://localhost/WorldLink/users/firstName%20=%3E%20Auth::user%28%29-%3EfirstName" and I have exhausted all other means of trying to fix it so I'm back for some help! my code is below Im using laravel 5.2:
Users.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Users extends Model
{
protected $table = 'users';
protected $fillable = [
'id', 'firstName', 'lastName', 'bio', 'homeLocation', 'currentLocation', 'email', 'password',
];
public function getName()
{
if ($this->firstName && $this->lastName) {
return "{$this->firstName} {$this->lastName}";
}
if ($this->firstName) {
return $this->firstName;
}
return null;
}
public function getNameOrLocation()
{
return $this->getName() ?: $this->currentLocation;
}
public function getFirstNameOrLocation()
{
return $this->firstName ?: $this->currentLocation;
}
public function getAllAvatarsUrl()
{
return "https://www.gravatar.com/avatar/{{ md5($this->email) }}?d=mm&s=40";
}
}
SearchController.php:
<?php
namespace App\Http\Controllers;
use DB;
use App\Users;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class SearchController extends BaseController
{
public function getResults(Request $request)
{
$query = $request->input('query');
if (!$query) {
return back();
}
$users = Users::where(DB::raw("CONCAT(firstName, ' ', lastName)"), '
LIKE', "%{$query}%")
->orWhere('currentLocation', 'LIKE', "%{$query}%")
->get();
return view('search/results')->with('users', $users);
}
ProfileController.php
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class ProfileController extends BaseController
{
public function getProfile($firstName)
{
$users = User::where('firstName', $firstName)->first();
if (!$users) {
abort(404);
}
return view('profile.index')
->with('users', $users);
}
}
userblock.blade.php
<div class="media">
<a class="pull-left" href="{{ route('profile/index', ['firstName' => $users->firstName]) }}">
<img class="media-object" alt="{{ $users-getNameOrLocation() }}" src="{{ $users->getAllAvatarsUrl() }}">
</a>
<div class="media-body">
<h4 class="media-heading">{{ $users->getNameOrLocation() }}</h4>
</div>
#if ($users->currentLocation)
<p>{{ $users->currentLocation }}</p>
#endif
results.blade.php
#extends('layouts.app')
#section('content')
<h3>Search Results for "{{ Request::input('query') }}"</h3>
#if (!$users->count())
<p>No Results Found</p>
#else
<div class="row">
<div class="col-lg-12">
#foreach ($users as $user)
#include('users/partials/userblock')
#endforeach
</div>
</div>
#endif
#endsection
And finally my two routes, the problem is connected in here somewhere I just cant find where its going wrong.
Route::get('/search', [
'uses' => '\App\Http\Controllers\SearchController#getResults',
'as' => 'search/results',
]);
Route::get('/users/{firstName}', [
'uses' => '\App\Http\Controllers\ProfileController#getProfile',
'as' => 'profile/index',
]);
The Link:
#if (Auth::guest())
<li>Login</li>
<li>Register</li>
#else
<ul class="nav navbar-nav">
<form class="navbar-form navbar-left" role="search" action="{{ route('search/results') }}">
<input type="text" class="form-control" placeholder="Search" name="query">
</form>
<li>{{ Auth::user()->firstName }}</li>
<li>Timeline</li>
<li>Link</li>
<li>Journeys <span class="journey-num">{{ Auth::user()->journeys }}</span></li>
<li>Forum</li>
</ul>
Defo quoting incorrectly
....
<li>{{ Auth::user()->firstName }}</li>
....
Note closing ' moved to after firstName array key.
That should at least fix the link

Resources