Laravel / AJAX Like Button Error: Request failed with status code 404 - ajax

I'm very new to Laravel, AJAX etc. I am a student working on a Twitter type project and this is my first stack question ever made. I've tried to look for answers but the code that my teacher has helped me with is very different from other examples. I'm pretty sure that my problem is with the unlike method inside of my "Tweet Controller"... Any help is greatly appreciated! Hopefully I have provided enough information and hopefully this can help others in the future :)
This is my error:[1]: https://i.stack.imgur.com/zkxsd.png
POST http://localhost:8000/tweets/19/unlike 404 (Not Found)
Uncaught (in promise) Error: Request failed with status code 404
at createError (app.js:14253)
at settle (app.js:35706)
at XMLHttpRequest.handleLoad (app.js:14127)
This is my likes table / migration
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateLikesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('likes', function (Blueprint $table) {
$table->increments('id');
$table->integer('tweet_id');
$table->integer('user_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('likes');
}
}
This is my Tweet Controller
public function like($id){
$like = Like::create([
'user_id'=>auth()->id(),
'tweet_id'=> $id
]);
if($like){
return json_encode(array('status' => 'success'));
}
return json_encode(array('status' => 'failed'));
}
public function unlike($id){
$like = Like::delete([
'user_id'=>auth()->id(),
'tweet_id'=> $id
]);
if($like){
return json_encode(array('status' => 'success'));
}
}
This is my Web Routes
Route::post('tweets/{tweet}/like', 'TweetController#like');
Route::delete('tweets/{tweet}/like', 'TweetController#unlike');
This is my Model
public function likes(){
return $this->hasMany(Like::class);
}
public function likedByCurrentUser(){
$userId=auth()->id();
//like boolean
$like = $this->likes->first(function($v) use ($userId){
//$v is a reference to the single like
return $v->user_id == $userId;
});
//if the user has liked a post
if($like){
return true;
}
return false;
}
This is my Vue Component:
<script>
export default {
name: 'likeButton',
props: ['likeCount','hasLiked','tweetId','csrf'],
mounted(){
this.dataLikeCount = this.likeCount;
this.dataHasLiked = this.hasLiked;
},
data(){
return{
dataLikeCount:0,
dataHasLiked:false
}
},
methods:{
doLike(){
var type='like';
if(this.dataHasLiked){
type='unlike'
}
axios({
method:'POST',
url:'/tweets/' + this.tweetId + '/'+ type,
headers:{
'X-CSRFToken':this.csrf
},
json: true
}).then((response) => {
if(response.data.status == 'success'){
// response was successful (regardless of type)
return true
// if type is like
// add one to like count, set hasLiked to true
if(type == 'like'){
this.dataLikeCount++
}
// if type is unlike
// deduct one from like count, set hasLiked to false
if(type =='unlike'){
return false
this.dataLikeCount--
}
}
});
}
}
}
</script>
<template>
<div>
<button type="submit"
:class="{'btn btn-link':dataHasLiked}"
#click="doLike">
<i class="star"></i>
Like {{ dataLikeCount }}
</button>
</div>
</template>

You dont have a matching route for unlike.
Change
Route::delete('tweets/{tweet}/like', 'TweetController#unlike');
To
Route::delete('tweets/{tweet}/unlike', 'TweetController#unlike');

Use this
Route::delete('tweets/{tweet}/unlike', 'TweetController#unlike');

As said by #DigitalDrifter you doesn't have route for unlike. so need to change that.
Your routes is like
Route::delete('tweets/{tweet}/unlike', 'TweetController#unlike');
So have to call this route with DELETE method using ajax. you have ajax call with post method.it will also give method not allowed error.
So change your web route,
From
Route::delete('tweets/{tweet}/unlike', 'TweetController#unlike');
To
Route::post('tweets/{tweet}/unlike', 'TweetController#unlike');
And change return response in your controller methods, It will look like below
Tweet Controller
public function like($id){
$like = Like::create([
'user_id'=>auth()->id(),
'tweet_id'=> $id
]);
if($like){
return response()->json(['status' => 'success']);
}
return response()->json(['status' => 'failed']);
}
public function unlike($id){
$like = Like::delete([
'user_id'=>auth()->id(),
'tweet_id'=> $id
]);
if($like){
return response()->json(['status' => 'success']);
}
}
Hope it helps now!!

Related

DB::table('table')->select returning empty string Laravel 6

I am using Laravel 6 with Vue axios, I want to populate a form-select with what I have in my "fjl_groups" table. But everytime I check the console for the result it is returning me an empty string, any idea why is this? My Laravel logs aren't returning any error either, so I have no idea what's going on.
Vue's part
<b-col cols="4">
<label for="editorial">Group</label>
<b-form-select v-model="group" :options="groups" id="groups" name="groups"></b-form-select>
</b-col>
<script>
export default {
data() {
return {
group: null,
groups: [{
value: null,
text: 'Select'
}]
}
},
created(){
axios.get('/clubs/create')
.then(res => {
this.groups = res.data;
console.log(this.groups);
}).catch(e => {
console.log(e);
})
},
}
}
</script>
I have a club and I want to assign a group for it from the ones I have added in my database, this is why I have it like that.
My controller (ClubsController)
use Illuminate\Support\Facades\DB;
use App\Models\Club;
use App\Models\Group;
public function create(Request $request)
{
if($request->ajax()){
DB::table('fjl_groups')->select('id as value', 'nom as text')->get();
}
else{
return view('clubs.create');
}
}
Group Model
class Group extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'fjl_groups';
public $timestamps = false;
}
You are not returning a value. You're just performing the select.
Try returning it:
return response()->json([
'data' => DB::table('fjl_groups')->select('id as value', 'nom as text')->get()
]);

Create new Post with default Category belongsToMany

I have a Post/Category manyToMany relations and would like to be able to attach a default category named "Uncategorised" to each new post that is created. How can I do that? A BelongsToMany method only works on the Details page, not on Create page.
BelongsToMany::make(__('Categories'), 'categories', Category::class),
You can also set default value to your database field so that you can omit passing category and will be taken default to Uncategorised like if you are using MySQL you can do it this way by creating migration
$table->text('category')->default(0);
Because the BelongsToMany not show on mode create in Post Nova model. So we have to make our custom Select, by add this code to your fields:
public function fields(Request $request)
{
if($request->editMode=="create"){
$categories = \App\Category::get(['id','name']);
$options = [];
foreach($categories as $value){
$options[$value->id] = $value->name;
}
return [
ID::make()->sortable(),
Text::make('Title'),
Text::make('Summary'),
Textarea::make('Content'),
Select::make('Categories', 'category_id')
->options($options)
->displayUsingLabels()
->withMeta(['value' => 1]) // 1 = id of Uncategorised in categories table
];
}
return [
ID::make()->sortable(),
Text::make('Title'),
Text::make('Summary'),
Textarea::make('Content'),
BelongsToMany::make('Categories','categories')->display('name'),
];
}
Don’t forget relationship function in both, Post and Category model:
class Post extends Model
{
public function categories(){
return $this->belongsToMany(Category::class, 'category_post', 'post_id', 'category_id');
}
}
And:
class Category extends Model
{
public function posts(){
return $this->belongsToMany(Post::class,'category_post', 'category_id', 'post_id');
}
}
Then, custom the function process the data on mode Create of Post resource page, it’s at nova\src\Http\Controllers\ResourceStoreController.php, change function handle to this:
public function handle(CreateResourceRequest $request)
{
$resource = $request->resource();
$resource::authorizeToCreate($request);
$resource::validateForCreation($request);
$model = DB::transaction(function () use ($request, $resource) {
[$model, $callbacks] = $resource::fill(
$request, $resource::newModel()
);
if ($request->viaRelationship()) {
$request->findParentModelOrFail()
->{$request->viaRelationship}()
->save($model);
} else {
$model->save();
// your code to save to pivot category_post here
if(isset($request->category_id)&&($resource=='App\Nova\Post')){
$category_id = $request->category_id;
$post_id = $model->id;
\App\Post::find($post_id)->categories()->attach($category_id);
}
}
ActionEvent::forResourceCreate($request->user(), $model)->save();
collect($callbacks)->each->__invoke();
return $model;
});
return response()->json([
'id' => $model->getKey(),
'resource' => $model->attributesToArray(),
'redirect' => $resource::redirectAfterCreate($request, $request->newResourceWith($model)),
], 201);
}
}
All runs well on my computer. A fun question with me! Hope best to you, and ask me if you need!
What I ended up doing was saving the data on Post Model in boot().
public static function boot()
{
parent::boot();
static::created(function (Post $post) {
$post->categories()->attach([1]);
});
}

How to call a function in one controller to the other controller in laravel

I want to call a function in another controller. when i call this gives me an error.
Call to undefined method Illuminate\Database\Query\Builder::defaultBuckets()
I dont know why it gives me this error. I don't know i am calling this function rightly in another controller. Here is my code. Please Help.
Here is my function i created in my BucketController:
public function defaultBuckets()
{
$buckets = Bucket::where('bucket_type', 'default')->get();
}
And here is my Profile controller function Where i call this function:
public function show(User $user)
{
$authUser = JWTAuth::parseToken()->toUser();
if (! $user->isBlocking($authUser) && ! $user->isBlockedBy($authUser)) {
if($authUser->id == $user->id){
$profile = $user->where('id', $user->id)->defaultBuckets()->with([
'posts', 'likes', 'followers', 'following'])->first();
} else{
$profile = $user->where('id', $user->id)->with([
'posts' => function ($query) {
$query->where('post_type', 'public');
},
'buckets' => function ($query) {
$query->where('bucket_type', 'public');
},
'likes' => function ($query) {
$query->where('post_type', 'public');
},
'followers', 'following'])->first();
}
return response()->json(['profile'=> $profile], 200);
}
return response()->json(['message'=> 'Your are not able to open profile of this user'], 200);
}
I Think there is mistake. You said you have this function in your BucketController
public function defaultBuckets()
{
$buckets = Bucket::where('bucket_type', 'default')->get();
}
and then you are firing the function from user model in your ProfileController
$profile = $user->where('id', $user->id)->defaultBuckets()->with([
'posts', 'likes', 'followers', 'following'])->first();
That is the reason it says that there is no function named "defaultBuckets".
You have to put this function in your User model and everything will work fine.
Also don't forget to return the buckets as well like this:
To return all buckets
public function defaultBuckets()
{
$buckets = Bucket::where('bucket_type', 'default')->get();
return $buckets; // all buckets
}
To return a user's buckets only
public function defaultBuckets()
{
return $this->hasMany(Bucket::class)->where('bucket_type', 'default');
}
Make sure to accept the relationship from user in bucket model like this:
public function user(){
return $this->hasOne(User::class, 'bucket_id' , 'user_id');
}
You can replace column names (bucket_id,user_id) according to your database.
Let me know if this fixes your problem

Laravel - return variable from Form Requests to Controller

How can I return a variable from Form Requests (App\Http\Requests) to Controller (App\Http\Controllers)?
I am saving a record on function persist() on Form Requests.
My goal is to pass the generated id so that I can redirect the page on edit mode for the user. For some reason, the Controller cannot receive the id from Form Requests.
App\Http\Requests\MyFormRequests.php:
function persist()
{
$business = Business::create([
'cart_name' => $this['cart_name'],
'product' => $this['product']
]);
return $myid = $business->id;
}
App\Http\Controllers\MyControllers.php:
public function store(MyFormRequests $request)
{
$request->persist();
return redirect()->route('mypage.edit.get', $request->persist()->$myid);
}
Important
I must add that this is not the recommended way. Your FormRequest should only be responsible for validating the request, while your Controller does the storing part. However, this will work:
App\Http\Requests\MyFormRequests.php:
function persist()
{
return Business::create([
'business_name' => $this['business_name'],
'nationality' => $this['nationality']
])->id;
}
App\Http\Controllers\MyControllers.php:
public function store(MyFormRequests $request)
{
$id = $request->persist();
return redirect()->route('register.edit.get', $id);
}
A guy name Snapey helped me:
public function store(MyFormRequests $request)
{
$business = $this->persist($request);
return redirect()->route('register.edit.get', $business->id);
}
private function persist($request)
{
....
return $business;
}
hope this could help someone in the future.

How can i create dynamic delete method in laravel?

in codeigniter i can set method for dynamic delete like this code.in laravel how can i set this method for dynamic delete method.Thanks
in controller function
public function Delete($id)
{
if ($this->process_model->DynamicDelete($id, "interest_statement")) {
//
}
}
in model function
public function DynamicDelete($id, $table)
{
$this->db->delete($table, ['id' => $id]);
return TRUE;
}
you can use route as like below:
Route::get('yourroute/{info}','Yourcontrolller#Yourmethod');
and use this route in view page where from request get:
{{ URL::to('/yourroute/'.$id.'&your_table')}}
and finally you write a function in your controller
public function Yourmethod($info){
$explode=explode('&',$info);
DB::table($explode[1])->where('id',$explode[0])->delete();
Session::flash('flash_message', 'Your Data Delete Successfully');
return back();
}
Thank you
In Laravel, you can use Raw Query (Database: Query Builder)
Example:
Table: users
Condition: votes > 100
DB::table('users')->where('votes', '>', 100)->delete();
In your case:
public function DynamicDelete($id, $table) {
return DB::table($table)->where('id', '=', $id)->delete();
}

Resources