Kimmer

Kimmer

Member Since 2 Years Ago

Antwerp

at These Days

Experience Points 14,570
Experience Level 3

430 experience to go until the next level!

In case you were wondering, you earn Laracasts experience when you:

  • Complete a lesson — 100pts
  • Create a forum thread — 50pts
  • Reply to a thread — 10pts
  • Leave a reply that is liked — 50pts
  • Receive a "Best Reply" award — 500pts
Lessons Completed 128
Lessons
Completed
Best Reply Awards 0
Best Reply
Awards
  • Start Your Engines Achievement

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • First Thousand Achievement

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • One Year Member Achievement

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • Two Year Member Achievement

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • Three Year Member Achievement

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • Four Year Member Achievement

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • Five Year Member Achievement

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • School In Session Achievement

    School In Session

    Earned when at least one Laracasts series has been fully completed.

  • Welcome To The Community Achievement

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • Full Time Learner Achievement

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • Pay It Forward Achievement

    Pay It Forward

    Earned once you receive your first "Best Reply" award on the Laracasts forum.

  • Subscriber Achievement

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • Lifer Achievement

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • Laracasts Evangelist Achievement

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • Chatty Cathy Achievement

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • Laracasts Veteran Achievement

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • Ten Thousand Strong Achievement

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • Laracasts Master Achievement

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • Laracasts Tutor Achievement

    Laracasts Tutor

    Earned once your "Best Reply" award count is 100 or more.

  • Laracasts Sensei Achievement

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • Top 50 Achievement

    Top 50

    Earned once your experience points ranks in the top 50 of all Laracasts users.

02 May
1 month ago

Kimmer left a reply on Use SUM Of Value In Related Table In Where Clause

Sorry, I don't think I can help you further but you might get more help if you create a new question here.

Probably you have but Have you tried havingRaw()?

Kimmer left a reply on Use SUM Of Value In Related Table In Where Clause

Hi @davidpetrov , I'm glad my question is of help to you.

I think ->havingRaw('score < ?', array(0)) does not work because "score" is not a actual column in the DB table. I don't know the exact term for it but it is created in the selectRaw clause.

I think the same goes for your paid_from_customer, I think. It seems that'ts what the error is saying. 'paid_from_customer' is not a column in the DB but created in your select().

Hope this helps

01 May
1 month ago

Kimmer left a reply on Use SUM Of Value In Related Table In Where Clause

@jlrdw, thanks for the tips.

I did some more testing and up until now the solution with havingRaw() seems to work nicely. I still need to do some testing on larger sets of tracks with more votes but I don't expect more than maybe some tweaking.

I used PDO in the past and I'll surely read up on your suggestions. I have a long way to go on the app I'm building. I'm sure it will need some optimising along the way.

30 Apr
1 month ago

Kimmer left a reply on Use SUM Of Value In Related Table In Where Clause

I really appreciate your support @jlrdw . Believe me, I spend hours searching the web and trying out numerous combinations before I posted the question.

I think I found the solution. My query worked nicely without the where clause but what I needed was to use SUM() in the where clause but, apparently, you can't do that. you can, however, in a havingRaw().

This query seems like what I was looking for.

$tracks = Track::query()->leftJoin('votes', 'tracks.id', '=', 'votes.track_id')
                ->select('tracks.*', 'votes.track_id')
                ->selectRaw('sum(votes.vote) as score')
                ->havingRaw('SUM(vote) < ?', array(0))
                ->groupby('tracks.id')
                ->get();

This seems to give me all tracks where the sum of votes.vote is smaller than 0.

This is not the complete query I need so... up to the next issue ;-)

Thanks again for your help!

Kimmer left a reply on Use SUM Of Value In Related Table In Where Clause

I adapted you example to:

$tracks = Track::query()->leftJoin('votes', 'tracks.id', '=', 'votes.track_id')
                ->select('tracks.id', 'votes.track_id')
                ->selectRaw('sum(votes.vote) as score')
                ->where('score', '<', 0)
                ->groupby('tracks.id')
                ->get();

But this gives me:

Column not found: 1054 Unknown column 'score' in 'where clause' (SQL: select tracks.id, votes.track_id, sum(votes.vote) as score from tracks left join votes on tracks.id = votes.track_id where score < 0 and tracks.deleted_at is null group by tracks.id)

I must admit that I need to learn more about aggregates. I don't really know what it means.

29 Apr
1 month ago

Kimmer left a reply on Use SUM Of Value In Related Table In Where Clause

Thanks @jlrdw , it seems to me your example searches for ownerid's smaller than 4. I would need countOfPets < 4.

I might be missing something, I'll try it out tomorrow.

Kimmer started a new conversation Use SUM Of Value In Related Table In Where Clause

Hi all,

I'm struggling with what appears to be a difficult query. I'll try to explain as simple as possible.

I have a table called "tracks" and a table called 'votes"

A track can have many votes but a vote can be 1 or -1. These values are stored in a column named "vote" in the "votes" table. So each track has a score from the sum of its votes.

I'm trying to collect tracks below or above a certain score.

So in theory I would need something like this:

Track::with('votes')
->where('sum(votes.vote)','<', 0) // for all tracks with a minus score
->get()

Obviously, this would be too easy.

Is anyone willing and able to nudge me in the right direction?

Thanks!

16 Apr
2 months ago

Kimmer left a reply on Notifications Broadcast Change Channel Name

I was looking in the wrong direction while the solution was right in front of me... yeah well... in the Laravel documentation: https://laravel.com/docs/5.8/notifications#listening-for-notifications

Added this to my User model

    public function receivesBroadcastNotificationsOn()
    {
        return 'users.'.$this->id;
    }

And adapted the return.

15 Apr
2 months ago

Kimmer left a reply on Notifications Broadcast Change Channel Name

I found that the channel name is set in the method "channelName()" "Illuminate\Notifications\Events\BroadcastNotificationCreated". However, I still don't know how to overwrite this.

14 Apr
2 months ago

Kimmer started a new conversation Notifications Broadcast Change Channel Name

Broadcasting a notification will result in a channel name like "private-App.Models.User.1".

I would prefer to not send over the users ID in the channel name so I want to change the channel name and use the users hashId instead.

Any way I can change the channel name?

22 Jan
5 months ago

Kimmer left a reply on Echo + Pusher + Vue - Listening For Event Does Not Work

Found it!

Apparently the BroadcastServiceProvider file had code which created the issues I had. The code was similar to what is in the Channels router.

This was the code in BroadcastServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Broadcast;

class BroadcastServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {

        Broadcast::routes(['middleware' => ['auth:api']]);

        /*
         * Authenticate the user's personal channel...
         */
        Broadcast::channel('App.User.*', function ($user, $userId) {
            return (int) $user->id === (int) $userId;
        });
    }
}

I don't know if it is old Laravel code or something that for some strange reason ended up in my project. I replaced the code with the default Laravel code and that solved my issue.

This is the code I used to replace my wrong code.

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Broadcast;

class BroadcastServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Broadcast::routes();

        require base_path('routes/channels.php');
    }
}

BTW: I noticed the code in my BroadcastServiceProvider was different while watching the "Get Real With Laravel Echo" lessons. If your new to Pusher/Broadcast/Echo this series explains the basic very clearly. https://laracasts.com/series/get-real-with-laravel-echo

21 Jan
5 months ago

Kimmer left a reply on Echo + Pusher + Vue - Listening For Event Does Not Work

I've been at this for days now. I updated my Laravel, (meaning started out with a fresh install and transferred all my code to the new one), read everything there is to read about this pusher:subscription_error (non of the solutions seem to work for me) and started the "Get Real With Laravel Echo" lessons here on Laracasts to end up right where I started during Episode 6 "Private Channels".

A regular channel works fine, a private channel is impossible. I've got the csrf_token meta tag on my page and all.

20 Jan
5 months ago

Kimmer left a reply on Echo + Pusher + Vue - Listening For Event Does Not Work

I added this to bootstrap.js...

Pusher.logToConsole = true;

Which made this appear in the console: "Pusher : No callbacks on private-comment for pusher:subscription_error"

I'm finding a lot of forum threads about this but non of the solutions seem to apply.

I'm also seeing "Pusher : Error : {"type":"WebSocketError","error":{"type":"PusherError","data":{"code":1006}}}" in the console. Don't know if it's related.

Kimmer left a reply on Echo + Pusher + Vue - Listening For Event Does Not Work

I did a quick test on the test project (where everything works perfectly) on the event listener on the Comments.vue components. I added a console.log() line to see if it get's triggered.

Echo.private("comment").listen("CommentSent", e => {
    console.log('Event listen CommentSent');
    this.comments.push({
        user: {
            name: e.user.name
        },
        body: e.comment.body
    });
});

There I can see ""Event listen CommentSent" appearing in the browser console.

Kimmer left a reply on Echo + Pusher + Vue - Listening For Event Does Not Work

Nope, only the console.log()'s I have created myself. I can see the messages created on the website in Pushers Debug Console.

19 Jan
5 months ago

Kimmer left a reply on Echo + Pusher + Vue - Listening For Event Does Not Work

It's in created(). This is the full code of the component

<template>
    <div class="card my-4">
        <h5 class="card-header">Leave a Comment:</h5>
        <div class="card-body">
            <form>
                <div class="form-group">
                    <textarea ref="body" class="form-control" rows="3"></textarea>
                </div>
                <button type="submit" @click.prevent="addComment" class="btn btn-primary">Submit</button>
            </form>
        </div>


        <p class="border p-3" v-for="comment in comments">
            
            {{ comment.user.name }} : &nbsp;
            {{ comment.body }}
            
        </p>

    </div>
</template>


<script>
    export default {
        props: {
            userName: {
                type: String,
                required: true
            },
            postId: {
                type: Number,
                required: true
            }
        },
        data() {
            return {
                comments: []
            };
        },
        created() {
            this.fetchComments();

            Echo.private("comment").listen("CommentSent", e => {
                console.log('Event listen CommentSent');
                this.comments.push({
                    user: {
                        name: e.user.name
                    },
                    body: e.comment.body
                });
            });

        },
        methods: {
            fetchComments() {
                console.log('fetchComments');
                axios.get("/" + this.postId + "/comments").then(response => {
                    this.comments = response.data;
                });
            },
            addComment() {
                console.log('addComment');
                let body = this.$refs.body.value;
                axios.post("/" + this.postId + "/comments", { body }).then(response => {
                    console.log(response.data);
                    this.comments.push({
                        user: {
                            name: this.userName
                        },
                        body: this.$refs.body.value
                    });
                    this.$refs.body.value = "";
                });
            }
        }
    };
</script>

Yes it is rendering. Everything else seems to work nicely.

Kimmer started a new conversation Echo + Pusher + Vue - Listening For Event Does Not Work

I followed this tutorial to create a commenting system... https://pusher.com/tutorials/cms-laravel-vue-part-6

... and got it working nicely on a fresh Laravel install.

After transporting the code to the project I'm working on new comments doen't appear real time on the front end. They are saved to the database and send to Pusher. I can see them in Pushers Debug Console.

It seems like this code in the "Comments.vue" component is not receiving an event

Echo.private("comment").listen("CommentSent", e => {
    console.log('Event listen CommentSent');
    this.comments.push({
        user: {
            name: e.user.name
        },
        body: e.comment.body
    });
});

This is in the routes/channels.php

Broadcast::channel('comment', function ($user) {
    return auth()->check();
});

This is the app/Events/CommentSent.php

<?php

namespace App\Events;

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


class CommentSent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $user;

    public $comment;

    public function __construct(User $user, Comment $comment)
    {
        $this->user = $user;

        $this->comment = $comment;
    }

    public function broadcastOn()
    {
        return new PrivateChannel('comment');
    }
}

In the bootstrap.js file

import Echo from 'laravel-echo'

window.Pusher = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    encrypted: true
});

Obviously I am willing top provide more code but I kept out the less relevant code (I think).

Does anyone see where I went wrong?

Thanks!

27 Nov
6 months ago

Kimmer left a reply on One Result From Count Distinct On Multiple Tables

I tried some combinations which resulted in MySQL errors but not the one you've suggested. Indeed this seems to work. Eventually it was a matter of brackets

Honestly, I kind-of gave on on it myself. Your patience is super natural. Thanks you so much.

26 Nov
6 months ago

Kimmer left a reply on One Result From Count Distinct On Multiple Tables

I posted it a couple of messages above but here it is again:

$query = Listing::query();

return $query
        ->leftJoin('users', 'user_id', '=', 'users.id')
        ->leftJoin('tracks', 'tracks.listing_id', '=', 'listings.id')
        ->leftJoin('votes', 'votes.listing_id', '=', 'listings.id')
        ->selectRaw('listings.*,
                    users.name,
                    count(DISTINCT tracks.id) as tracks,
                    count(DISTINCT votes.id) as votes,
                    count(DISTINCT tracks.user_id + votes.user_id) as contributors
                    ')
        ->groupBy('listings.id')
        ->orderBy($sortBy,$descending)
        ->paginate( $limit );

The line for "contributors" is the one that doesn't work. I expanded the "selectRaw" code for some more results with a couple of similar counts but nothing relevant for this issue.

25 Nov
7 months ago

Kimmer left a reply on One Result From Count Distinct On Multiple Tables

I'm sorry, I didn't realise I could test the query in PHPMyAdmin. Still learning every day. When I do that it seems to work indeed.

The link to the fiddle redirects to an empty fiddle: https://www.db-fiddle.com/

Kimmer left a reply on One Result From Count Distinct On Multiple Tables

MySQL but the problem is that I don't know how to incorporate your code in the Laravel/Eloquent code I already have working (see a couple of messages above).

BTW: I can also not see the DB-Fiddle

Kimmer left a reply on One Result From Count Distinct On Multiple Tables

Thanks! Really appreciate your time and effort but I'm unable to incorporate that into what I already have. Or even make it work on it's own in my controller

24 Nov
7 months ago

Kimmer left a reply on One Result From Count Distinct On Multiple Tables

Hehe, yeah, I only ask complex issues. I can do the simple once or find a solution for those ;-) I usually take a couple of hours of searching before I post a question.

Thanks for the link. I noticed before it might have something to do with UNION but I'm still unable to incorporate it on the flow that I have.

Not the most important part of my project. I'll come back to it later.

23 Nov
7 months ago

Kimmer left a reply on One Result From Count Distinct On Multiple Tables

BTW this is my full query at the moment

 $query = Listing::query();

return $query
        ->leftJoin('users', 'user_id', '=', 'users.id')
        ->leftJoin('tracks', 'tracks.listing_id', '=', 'listings.id')
        ->leftJoin('votes', 'votes.listing_id', '=', 'listings.id')
        // ->select('listings.*','users.name')
        ->selectRaw('listings.*,
                    users.name,
                    count(DISTINCT tracks.id) as tracks,
                    count(DISTINCT votes.id) as votes,
                    count(DISTINCT tracks.user_id + votes.user_id) as contributors
                    ')
        ->groupBy('listings.id')
        ->orderBy($sortBy,$descending)
        ->paginate( $limit );

It gives me sortable tracks and votes count but a wrong contributors count as described above

Kimmer left a reply on One Result From Count Distinct On Multiple Tables

Sorry, but could it be you're misinterpreting "contributors"? I'm looking for the amount of unique users that contributed to the list. I don't understand how that can be derived from adding tracks_count with votes_count. One user can have many tracks and votes in one list.

Otherwise I don't understand how to implement your suggestion.

Kimmer left a reply on One Result From Count Distinct On Multiple Tables

Thanks but I wanted to avoid that because in that case sorting my table on contributors will not work. If I'm not mistaken.

Kimmer left a reply on One Result From Count Distinct On Multiple Tables

Thanks a lot for your reply. I tried your suggestion but I'm getting this error:

exception: "Illuminate\Database\QueryException"
file: ".../vendor/laravel/framework/src/Illuminate/Database/Connection.php"
line: 664
message: "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'laravel_reserved_0.listing_id' in 'where clause' (SQL: select `listings`.*, (select count(distinct user_id) from `listings` as `laravel_reserved_0` where `listings`.`id` = `laravel_reserved_0`.`listing_id`) as `tracks_count`, (select count(distinct user_id) from `votes` where `listings`.`id` = `votes`.`listing_id` and `votes`.`deleted_at` is null) as `votes_count` from `listings` order by `created_at` desc limit 25 offset 0)"

I tried using the query as is and incorporating it in my own code. Both with the same results.

Kimmer started a new conversation One Result From Count Distinct On Multiple Tables

For the app I'm building I have in my database

A table named "listings"

| id | 
-------
|  1 |

A table named "tracks". Like this:


| id | listing_id | user_id |
-------------------------------------
|  1 |       1        |      1      |
|  2 |       1        |      1      |
|  3 |       1        |      1      |
|  4 |       1        |      1      |

A table named "votes". Like this:


| id | listing_id | user_id |
------------------------------------
|  1 |       1        |      1      |
|  2 |       1        |      2      |
|  3 |       1        |      2      |

For my administration page I'm creating a sortable table that should show (among other data) the number of contributors. So the number of users that have added tracks or voted. In the tables above you see that user 1 (4 tracks, 1 vote) and user 2 (2 votes) contributed to the list. The result should be 2.

This is my query now:

$query = Listing::query();

return $query
        ->leftJoin('tracks', 'tracks.listing_id', '=', 'listings.id')
        ->leftJoin('votes', 'votes.listing_id', '=', 'listings.id')
        ->selectRaw('listings.*,
                    count(DISTINCT tracks.user_id + votes.user_id) as contributors
                    ')
        ->groupBy('listings.id')
        ->orderBy($sortBy,$descending)
        ->paginate( $limit );

This results in 3 contributors. So the query is counting user_id 1 twice.

Does anyone have an idea how to solve this?

Thanks!

16 Aug
10 months ago

Kimmer left a reply on Policies Always Results In "This Action Is Unauthorized"

I read somewhere that one should not pass the items ID to the client for security reasons. That's why I started using this Hash ID component. I wouldn't know how to do this "Spot::byHashid($hashid)" but that's outside of the scope of this thread, I'll look it up. Thanks for the suggestion.

Eventually I removed the method name from $this->authorize() because it is not needed in my case.

Thanks again for your time and sharing your knowledge. Didn't progress much today but I learned something new again ;-)

Kimmer left a reply on Policies Always Results In "This Action Is Unauthorized"

Thanks for your time @crnkovic.

While waiting for a reply I figured out that the options should be an instance of the model, not an ID number. As you point out in your comment.

I updated the controller to this and now it works.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Spot;
use Vinkla\Hashids\Facades\Hashids;

use App\Policies\SpotPolicy;

class spotController extends Controller
{
    public function delete($spot)
    {
        $id = Hashids::connection('spots')->decode($spot)[0];
        
        $this->authorize('delete', Spot::find($id));

        return 'Spot gets deleted';
    }

}

Is this solution acceptable you think?

Kimmer left a reply on Policies Always Results In "This Action Is Unauthorized"

I had to update my previous comment because I'm back to square one.

With the transformed hashid I'm still getting ""This action is unauthorized".

Even when I try enter the spot's id directly as a parameter for authorize() like this...

$this->authorize('delete', 1);
```
Shouldn't that parameter be an ID number? Apparently not?

Kimmer left a reply on Policies Always Results In "This Action Is Unauthorized"

Ah, that's why I din't do this...


public function delete(Spot $spot)

but

public function delete($spot)

I forgot to turn the hashed ID to the item's real ID in the controller before calling the authorisation. This controller makes it work.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Spot;
use Vinkla\Hashids\Facades\Hashids;

use App\Policies\SpotPolicy;

class spotController extends Controller
{
    public function delete($spot)
    {

        $id = Hashids::connection('spots')->decode($spot)[0];

        $this->authorize('delete', $id);

        return 'Spot gets deleted';
    }

}

Thanks a lot!

Kimmer left a reply on Policies Always Results In "This Action Is Unauthorized"

I just don't understand why the URL with the hashed ID doesn't even reach the delete() method in the spotController.

Kimmer left a reply on Policies Always Results In "This Action Is Unauthorized"

I found what's causing the error. I was sending the item ID as a hashed id because I'm using Laravel component called "Hashids" from Vinkla. so the URL I was sending looked like

https://[domain]/spots/api/Zmr6kGzDE0xN9YeWgAXgApdvlBVyQPo5wj3nb2J4/delete

Surpassing the Hashid's component and sending...

https://[domain]/spots/api/1/delete

...makes my code reach the "delete" method in "SpotPolicy".

So the code works. I just need to make it work with hashed ids.

Kimmer left a reply on Policies Always Results In "This Action Is Unauthorized"

Thanks for your support @crnkovic.

I'm sorry but I don't know what you mean. What is a "route key in your model"?

This is the Spot model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Spot extends Model
{

    protected $fillable = [
        'map_id',
        'place_id',
        'user_id',
        'info'
    ];

    protected $hidden = [
        'id',
    ];

    public function user() {
        return $this->belongsTo('App\User');
    }

    public function map() {
        return $this->belongsTo('App\Map');
    }
    
    public function place() {
        return $this->belongsTo('App\Place');
    }

}

Kimmer left a reply on Policies Always Results In "This Action Is Unauthorized"

Thans @Cruorzy ! Corrected that.

@crnkovic : for some reason this returns "Sorry, the page you are looking for could not be found."

I have this in my routes/web.php

Route::get('spots/api/{spot}/delete', '[email protected]');

And I'm passing

https://[domain]/spots/api/[id]/delete

If I do what you suggest the "delete" method in spotController doesn't even get reached (dd()) is not triggered)

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Spot;

use App\Policies\SpotPolicy;

class spotController extends Controller
{
    public function delete(Spot $spot)
    {
        dd('Stop here');
        $this->authorize('delete', $spot);

        return 'Spot gets deleted';
    }

}
,,,

Kimmer started a new conversation Policies Always Results In "This Action Is Unauthorized"

I followed the tutorial video, read the docs and searched the web. My code should work... yeah well... it doesn't and it's driving me mad.

I'm trying g to create a simple policy in Laravel.

In the controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Spot;

use App\Policies\SpotPolicy;

class spotController extends Controller
{
   public function delete($spot)
   {
       $this->authorize('delete', $spot);

       return 'Spot gets deleted';
   }

}

In the Policy file (app\Policies\SpotPolicy.php)

<?php

namespace App\Policies;

use App\User;
use App\Spot
use Illuminate\Auth\Access\HandlesAuthorization;

class SpotPolicy
{
    use HandlesAuthorization;

    public function delete(User $user, Spot $spot) 
    {
        dd('Stop here');
        
        return true;

    }
}

In the AuthServiceProvider

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
        'App\Spot' => 'App\Policies\SpotPolicy'
    ];

    public function boot()
    {
        $this->registerPolicies();
    }
}

This always returns "Symfony \ Component \ HttpKernel \ Exception \ AccessDeniedHttpException This action is unauthorized.". The "delete" method in the SpotPolicy class is never reached.

Anyone... please?

Thanks

28 Jul
10 months ago

Kimmer left a reply on Vue.js & Google Maps Api - Button @click In Infowindow

I seems vm.$mount() was the solution to my issue. https://vuejs.org/v2/api/#vm-mount

I added this to my app.js file

var infoWindowButton = Vue.extend({
  template: '<button type="button" @click="infoWindowButtonClicked()">This is a button</button></div>',
  methods : {
    infoWindowButtonClicked : function() {
      Event.fire('infoWindowButtonClicked'); 
    }
  }
})
Event.fire('infoWindowButton', new infoWindowButton().$mount()); 

And updated the above component to:

<template>
    <div class="map-container" ref="map"></div>
</template>

<script>
    export default {
        data: function () {
            return {
                map: null,
                infoWindow: {},
                infoWindowButton: '', // NEW
            }
        },
        created() {
            Event.listen('MapsApiLoaded', function(value){
                this.createMap();
            }.bind(this));
             // NEW
            Event.listen('infoWindowButton', function(component){
                this.infoWindowButton = component;
            }.bind(this));
            // NEW
            Event.listen('infoWindowButtonClicked', function(){
                this.openDialog();
            }.bind(this));
        },
        methods: {
            // create map
            createMap: function () {
                const element = this.$refs.map;
                const options = {
                    zoom: 7,
                    center: new google.maps.LatLng(9.625482,-84.029368)
                }
                this.map = new google.maps.Map(element, options);
                this.addMarker();
            },
            // Add marker
            addMarker: function(latLng) {
                this.marker = new google.maps.Marker({
                    position: new google.maps.LatLng(9.990378,-85.252195),
                    draggable:true,
                    map: this.map
                });
                this.marker.setMap(this.map);
                this.addInfoWindow();
            },
            // Add infowindow
            addInfoWindow: function () {
                this.infoWindow = new google.maps.InfoWindow({
                    size: new google.maps.Size(150, 50)
                });
                // VARIABLE UPDATED
                // var contentString = '<button type="button" @click="openDialog()">This is a button</button>';
                var contentString = this.infoWindowButton.$el;

                this.infoWindow.setContent(contentString);
                this.infoWindow.open(this.map, this.marker);
            },
            // Method to be reached by click event on button in InfoWindow
            openDialog: function () {
                console.log('openDialog');
            }
        },
    };
</script>

Note the env "infoWindowButton" data variable, the two event listeners in "created()" and the updated "contentString" variable.

Not related to this issue but to make my solution complete, events are handled by a small event wrapper which is also in my app.js

window.Event = new class {

  constructor() {
    this.vue = new Vue();
  }

  fire(event, data = null, action) {
    this.vue.$emit(event, data, action);
  }

  listen(event, callback) {
    this.vue.$on(event, callback)
  }

}
27 Jul
10 months ago

Kimmer started a new conversation Vue.js & Google Maps Api - Button @click In Infowindow

I've been stuck on this for a while, found some other people asking this question but could not find an answer. I hope someone here is able and willing to help me out.

In a vue.js component I have a button in Google Maps API Infowindows. Like this

<template>
    <div class="map-container" ref="map"></div>
</template>

<script>
    export default {
        data: function () {
            return {
                map: null,
                infoWindow: {},
            }
        },
        created() {
            Event.listen('MapsApiLoaded', function(value){
                this.createMap();
            }.bind(this));
        },
        methods: {
            createMap: function () {
                const element = this.$refs.map;
                const options = {
                    zoom: 7,
                    center: new google.maps.LatLng(9.625482,-84.029368)
                }
                this.map = new google.maps.Map(element, options);
                this.addMarker();
            },
            addMarker: function(latLng) {
                this.marker = new google.maps.Marker({
                    position: new google.maps.LatLng(9.990378,-85.252195),
                    draggable:true,
                    map: this.map
                });
                this.marker.setMap(this.map);
                this.addInfoWindow();
            },
            addInfoWindow: function () {
                this.infoWindow = new google.maps.InfoWindow({
                    size: new google.maps.Size(150, 50)
                });
                var contentString = '<button type="button" @click="openDialog()">This is a button</button>';
                this.infoWindow.setContent(contentString);
                this.infoWindow.open(this.map, this.marker);
            },
            openDialog: function () {
                console.log('openDialog');
            }
        },
    };
</script>

I'm trying to reach the "openDialog" method but the @click event does not work.

How can I trigger the "openDialog" method by clicking the button in the Infowindow?

Thanks a lot in advance.

01 Apr
1 year ago

Kimmer started a new conversation Get Ranking Based On Voting Scores

I have a list of tracks on which can be voted. To order the list in vue.js on the front-end I need a unique ranking value for every tack based on the voting score.

This code works perfectly except it does not use the "Tracks" model.

$subquery = "( 
    SELECT      tracks.id,
            IFNULL(Sum(votes.vote), 0) AS score
    FROM        tracks 
    LEFT JOIN   votes 
    ON      tracks.id = votes.track_id
    WHERE       tracks.listing_id = $id
    GROUP BY    tracks.id
    ORDER BY    score DESC, 
    tracks.created_at DESC 
) totals";
    
DB::statement(DB::raw('set @r=0'));

$tracks = DB::table(DB::raw($subquery))
->select(
'*', 
'score', 
DB::raw('@r:[email protected]+1 as rank'), 
DB::raw('@l:=score'))
->get();

return $tracks;

}

Is there a way to do this without a raw SQL (sub)query?

I tried this but it doesn't seem to work.

DB::statement(DB::raw('set @r=0'));

$tracks = Track::select(
    'tracks.*', 
    DB::raw('IFNULL(SUM(votes.vote), 0) AS score'), 
    DB::raw('@r:[email protected]+1 as rank')
    )
->leftJoin('votes', 'tracks.id', '=', 'votes.track_id')
->where('tracks.listing_id', $id)
->groupBy('tracks.id')
->orderBy('rank')
->get();
        
return $tracks;

Thanks!

26 Mar
1 year ago

Kimmer started a new conversation SSR With Vue And Vuetify

I’m trying to figure out how to do SSR with Laravel and I managed to get the results from this tutorial working in MAMP on my Mac (by installing php-v8js).

Now I’m trying to incorporate Vuetify but I’m running into a wall.

I created a component “resources/assets/js/components/Layout/Toolbar.vue” in which I added basic Vuetify toolbar markup

Then I added this line in “resources/assets/js/app.js”

Vue.component('toolbar', require('./components/Layout/Toolbar.vue’));

And created the following markup in “resources/assets/js/components/App.vue”.

<template>
  <div id="app">
    <toolbar></toolbar>
  </div>
</template>

Now when I check the page source in Chrome I can see the the server is sending over the toolbar markup like this

<v-toolbar>
// toolbar markup
</v-toolbar>

It’s clear that Vuetify doesn’t have any effect in this markup. I tried incorporating Vuetify by adding the lines below to the the .js files (one by one) created while doing the tutorial but I can’t get it to work.

import Vuetify from 'vuetify'
Vue.use(Vuetify)

Anyone know how to get SSR running with Vuetify?

Thanks!

06 Mar
1 year ago

Kimmer left a reply on Eloquent - Calculate Two Field Values And Order According To Result.

Thanks so very much! Did a quick test and your solution with the the leftJoin seems to work very nicely @matthew_inamdar .

05 Mar
1 year ago

Kimmer started a new conversation Eloquent - Calculate Two Field Values And Order According To Result.

I am building a query calling a collection of track to build up a track list. There’s a bunch of relationships that go with this.

  • A track has a song (one to one)
  • A track has votes (one to many)
  • A song has artists (many to many)

I can call all this with

Track::where('tracks.listing_id', $id)
    ->with('song', 'song.artists', 'votes')
    ->get();

I want to order the track by the amount of votes they have. Seems fairly simple BUT a vote can be positive (up vote) or negative (down vote). The votes records have a “vote” field in which the value can be “1” or “-1”. This means I can’t just count the number of records in the votes table for one given track.

So, how can I calculate the up and down votes to get an actual votes count and order my query results on that? Is it even possible

I played around with withCount() which allows me to count only the up-votes or down-votes but I could really use some help here. Maybe what I’m after isn’t even possible.

26 Nov
1 year ago

Kimmer started a new conversation Inserting Multiple Records With Al Kinds Of Related Models

This is rather complicated. I’ll try a explain as clearly as possible.

######Models: I have 3 models Track, Song and Artist. A track has one song, a song can belong to many tracks, a song can have many artists and an artist can belong to many songs. (see relationships below at "Models relationships")

######Database tables: The Database tables are tracks, songs, artists and artist_song (pivot). (see the fields below at "Database tables and fields")

######Scenario: Via an API call to the Spotify API data is returned. The returned JSON contains data from three songs which have one or more artists. (see JSON return below at "Returned API data")

######What I want to do: For every song in the JSON…

  • create a record in the tracks table with the ID of the song
  • create a record in the songs table with the song info (“name” to “title” field)
  • create a record for every artist in the artists table
  • attache the artists to the correct songs via the pivot table.

With as few queries as possible

######What I can do: I am able create all records but with queries in loops which could result in too many DB queries.

I can write the 3 songs in one query (see last code block) but I don’t know how to proceed with writing the tracks and artist for these songs.

######Models relationships

// Track
public function song() {
    return $this->belongsTo('App\Models\Song');
}

// Song
public function tracks() {
    return $this->hasMany('App\Models\Track');
} 
public function Artists() {
        return $this->belongsToMany('App\Models\Artist');
}

// Artist
public function Songs() {
    return $this->belongsToMany('App\Models\Song');
}

######Database tables and fields (minimised to only the fields I need for this question)

tracks
    - id
    - song_id

songs
    - id
    - title

artists
    - id
    - name

artist_song
    - song_id
    - artist_id

######Returned API data (example, minified to only the data I need for this question)

{
  “songs”: [
    {
      "artists": [
        {
          "name": "Dreadzone"
        }
      ],
      "name": "Digital Mastermind",
    },
    {
      "artists": [
        {
          "name": "Damian Marley"
        },
        {
          "name": "Stephen Marley"
        },
        {
          "name": "Rovleta Fraser",
        }
      ],
      "name": "Hey Girl",
    },
    {
      "artists": [
        {
          "name": "The Wailers"
        },
        {
          "name": "Alpha Blondy"
        }
      ],
      "name": "Jerusalem",
    }
  ]
}

######Inserting the 3 songs in one query

$songs = collect();

foreach ($spotifyTracksData->songs as $song) {
    $songs->push(['title' => $song->name]);
}

$return = Song::insert($songs->toArray());
12 Nov
1 year ago

Kimmer left a reply on Eloquent Many To Many Query Searching Values From Both Tables. All Values Should Be Present.

This seems to work.

It seems to search for a song in the database which

  • Has an identical title
  • Has the same artists
  • Has the same amount of artists
public static function songExistsByTitleArtists($track) {

    // Create array from artists IDs of a track coming in from a /tracks call to the Spotify API.
    // $artists = ['0jHCJWgwdcqysvbKWjXSI6', '41ekW4MXG59xJMXR8dX1OG'];
    $artists = collect($track->artists)->pluck('id');

    $query = song::query();

    //  Loop over the IDs in the $artists array and create a whereHas() statement for every ID
    foreach ($artists as $artist) {
        $query->whereHas('artists', function ($q) use($artist) {
            $q->where('spotify_id', $artist);
        });
    }

    // Compose the query
    $existingSong = $query
                    ->where('title', $track->name) // Compare incoming track title with song title in DB
                    ->has('artists', count($artists)) // Compare if the amount of artist in existing track is the same as the amount of IDs in the $artists array
                    ->first();

    return $existingSong;

}

Kimmer left a reply on Eloquent Many To Many Query Searching Values From Both Tables. All Values Should Be Present.

I've been occupied with other things for a couple of days but I've been searching for a solution on this problem again for several hours. Anyone willing to help me crack this, please?

07 Nov
1 year ago

Kimmer left a reply on Eloquent Many To Many Query Searching Values From Both Tables. All Values Should Be Present.

Ah but removing ->toArray() gives the same result, apparently

$ids = collect($track->artists)->pluck('id');
```

Kimmer left a reply on Eloquent Many To Many Query Searching Values From Both Tables. All Values Should Be Present.

This does return an array of the artists->id in the JSON @Cronix

$ids = collect($track->artists)->pluck('id')->toArray();

Here's an example:

["0jHCJWgwdcqysvbKWjXSI6","41ekW4MXG59xJMXR8dX1OG"]

Kimmer left a reply on Eloquent Many To Many Query Searching Values From Both Tables. All Values Should Be Present.

$track is the JSON return I get from Spotify after an API call. This is the minified version of the JSON return. This return holds the data I'm using to find the existing song in the database. I need to know if that song already exists.

{
  "artists" : [ {
    "id" : “Artist1”
  }, {
    "id" : “Artist2”
  } ],
  "name" : “Cool Song“,
}

No there is no artist_id in the songs table. There’s a pivot table. songs and artists have a many to many relationship. These are my migrations. I removed the columns that have no use for the issue in this threat.

Schema::create('songs', function (Blueprint $table) {
    $table->string('title');
});
// all references to artists are in the Pivot table ‘artist_song’

Schema::create('artists', function (Blueprint $table) {
    $table->string('spotify_id', 30);
});
// all references to songs are in the Pivot table ‘artist_song’

// Pivot table
Schema::create('artist_song', function (Blueprint $table) {
    $table->integer('song_id')->unsigned()->index();
    $table->integer('artist_id')->unsigned()->index();
    $table->primary(['song_id', 'artist_id']);
});

So I’m searching for spotify_id in the artists table.

I’m fairly new to all of this. I don’t really know why collect() is needed. My code is in a class I made which is in a folder “library” that I created. Maybe I need a certain namespace or a ‘use’?

Kimmer left a reply on Eloquent Many To Many Query Searching Values From Both Tables. All Values Should Be Present.

Thanks for your reply @robrogers3. Yes the table is “artists”

Sadly I can’t get it working.

Without editing your code returns:

Call to a member function pluck() on array

After some searching I managed to have this code return an array of ids from the incoming API return and solve the above error.

$ids = collect($track->artists)->pluck('id')->toArray();

Your code with the first line replaced with the edited version returned this error.

Call to a member function toArray() on array

I removed the ->toArray() from line three which left me with this error

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'artist_id' in 'where clause' (SQL: select exists(select * from `songs` where `spotify_id` in (select `spotify_id` from `artists` where `artist_id` in (0jHCJWgwdcqysvbKWjXSI6, 41ekW4MXG59xJMXR8dX1OG)) and `title` = Jerusalem) as `exists`)

'artist_id' does not exist in the artists table so I changed the code to this

$ids = collect($track->artists)->pluck('id')->toArray();
return Song::whereIn('spotify_id', function ($query) use ($ids) {
    $query->select('spotify_id')->from('artists')->whereIn('spotify_id', $ids);
})->where('title', $track->name)->exists();

This returns no error but, sadly, does not find the existing song.