I have implemented the logic of adding likes to articles:
html
<a href="/article/{{ $article->id }}?type=heart" class="comments-sub-header__item like-button {{ $article->hasLikedToday('heart') ? 'active' : '' }}">
<div class="comments-sub-header__item-icon-count"> {{ $article->getLikeHeartTotal() }} </div>
</a>
<a href="/article/{{ $article->id }}?type=finger" class="comments-sub-header__item like-button {{ $article->hasLikedToday('finger') ? 'active' : '' }}">
<div class="comments-sub-header__item-icon-count"> {{ $article->getLikeFingerTotal() }} </div>
</a>
php
model
public function hasLikedToday(string $type)
{
$articleLikesJson = Cookie::get('article_likes', '{}');
$articleLikes = json_decode($articleLikesJson, true);
if (!array_key_exists($this->id, $articleLikes)) {
return false;
}
if (!array_key_exists($type, $articleLikes[$this->id])) {
return false;
}
$likeDatetime = Carbon::createFromFormat('Y-m-d H:i:s', $articleLikes[$this->id][$type]);
return !$likeDatetime->addDay()->lt(now());
}
public function setLikeCookie(string $type)
{
$articleLikesJson = Cookie::get('article_likes', '[]');
$articleLikes = json_decode($articleLikesJson, true);
$articleLikes[$this->id][$type] = now()->format('Y-m-d H:i:s');
$articleLikesJson = json_encode($articleLikes);
return cookie()->forever('article_likes', $articleLikesJson);
}
controller
public function postLike($id, Request $request)
{
$article = Article::find($id);
if (!$article) {
return abort(404);
}
$type = $request->input('type');
if ($article->hasLikedToday($type)) {
return response()
->json(
[
'message' => 'You have already liked the Article ' . $article->id . ' with ' . $type . '.',
]
);
}
$cookie = $article->setLikeCookie($type);
$article->increment("like_{$type}");
return response()
->json(
[
'message' => 'Liked the Article ' . $article->id . ' with ' . $type . '.',
'cookie_json' => $cookie->getValue(),
]
)
->withCookie($cookie);
}
js
$(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
},
});
$('.like-button').on('click', function(event) {
event.preventDefault();
var targetElement=$(this);
let href = $(this).attr('href');
$.ajax({
url: href,
type: 'POST',
success: function() {
if (targetElement.hasClass('active')) {
return false;
}
else {
var counter = targetElement.find('.comments-sub-header__item-icon-count');
var current = parseInt(counter.html());
counter .html(current + 1)
targetElement.addClass('active');
}
},
});
});
});
Now it turns out that both types of likes have a separate html page like /article/11?type=heart
and /article/11?type=finger
Because of these links to the page, Google software swears, and gives such an error
the server returned a 405 method not allowed
Can I somehow keep all this functionality in a simple way, but make it so that the like request is not a POST and does not have a link so as not to receive such an error?
If you don't need <a>
tag then you change that to span
or button
and then use data-attr
for setting value of $article->id
& type
. Then, use this data-attr
to fetch value in ajax and pass it your server .
Changes you can do in your code :
HTML :
<!--added span tag and use data-attr-->
<span data-id="{{ $article->id }}" data-type="heart" class="comments-sub-header__item like-button {{ $article->hasLikedToday('heart') ? 'active' : '' }}">
<div class="comments-sub-header__item-icon-count"> {{ $article->getLikeHeartTotal() }} </div>
</span>
<span data-id="{{ $article->id }}" data-type="finger" class="comments-sub-header__item like-button {{ $article->hasLikedToday('finger') ? 'active' : '' }}">
<div class="comments-sub-header__item-icon-count"> {{ $article->getLikeFingerTotal() }} </div>
</span>
AJAX:
$('.like-button').on('click', function(event) {
var targetElement=$(this);
let article_id = targetElement.data('id');
let type = targetElement.data('type');
let href = `/article/${article_id}?type=${type}`
//your ajax call change type:"POST" to type:"GET"
});
Code Demo :
$('.like-button').on('click', function(event) {
var targetElement = $(this);
let article_id = targetElement.data('id');
let type = targetElement.data('type');
let href = `/article/${article_id}?type=${type}`
console.log(href)
//..your ajax call change type:"POST" to type:"GET"
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span data-id="1" data-type="heart" class="comments-sub-header__item like-button active">
<div class="comments-sub-header__item-icon-count"> 1</div>
</span>
<span data-id="2" data-type="finger" class="comments-sub-header__item like-button active">
<div class="comments-sub-header__item-icon-count"> 2 </div>
</span>
Basically, you need to make sure that you decide whether you want your request to be GET and POST as well as making sure that the routes are set correctly. If you want to have a GET route, then you will need something like
Route::get('/article/{id}', function (string $id) {
$type = $request->type; //getting the type
//your code here
return 'success';
});
or, if you want a post, you can have something like
Route::post('/article/{id}', function (string $id) {
$type = $request->type; //getting the type
//your code here
return 'success';
});
Of course, you will need to make sure that your AJAX request has type: 'POST',
if it's a POST request and type: 'GET',
, if it's a GET request, respectively.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With