Kimmer

Kimmer

Member Since 3 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-engines Created with Sketch.

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • first-thousand Created with Sketch.

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • 1-year Created with Sketch.

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • 2-years Created with Sketch.

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • 3-years Created with Sketch.

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • 4-years Created with Sketch.

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • 5-years Created with Sketch.

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • school-session Created with Sketch.

    School In Session

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

  • welcome-newcomer Created with Sketch.

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • full-time-student Created with Sketch.

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • pay-it-forward Created with Sketch.

    Pay It Forward

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

  • subscriber-token Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer-token Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • lara-evanghelist Created with Sketch.

    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 Created with Sketch.

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • lara-veteran Created with Sketch.

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • 10k-strong Created with Sketch.

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • lara-master Created with Sketch.

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • laracasts-tutor Created with Sketch.

    Laracasts Tutor

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

  • laracasts-sensei Created with Sketch.

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • top-50 Created with Sketch.

    Top 50

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

02 May
4 months 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
4 months 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
4 months 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. 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
4 months 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
5 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
5 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
5 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.

Is there anyway I can change the channel name?

I found this page which, as I understand, describes the solution. https://github.com/laravel/ideas/issues/202

I just can't seem to figure out how to implement this.

22 Jan
7 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
7 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
7 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. Most refer to the need of "pusher" needing to be the value of "BROADCAST_DRIVER" but it is already in my .env.

BROADCAST_DRIVER=pusher

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.

But, then I can't see anything coming from Pusher in the test Laravel install, where commenting works, in the console either. Maybe I don't know where to look ;-)

19 Jan
7 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
9 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
9 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
9 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
9 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
9 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')
        ->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 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".

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

A table named "votes".

| 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
1 year 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 pointed 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 an option for authorize() like this...

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

Shouldn't that option be an ID number? Apparently not?

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

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


public function delete(Spot $spot)

but

public function delete($spot)

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
1 year 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
1 year ago

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

I was hoping anyone can help me out with making a @click action work on a button inside a Google Maps Infowindow.

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

<script>
    export default {
        data: function () {
            return {
                map: null,
                infoWindow: {},
            }
        },
        created() {
            Event.listen('MapsApiLoaded', function(value){
                this.createMap();
            }.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)
                });
                var contentString = '<button type="button" @click="openDialog()">This is a button</button>';
                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>

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).

https://vuejsdevelopers.com/2017/11/06/vue-js-laravel-server-side-rendering/

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 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 songs table with the song info (“name” to “title” field)
  • create a record in the tracks table with the ID of the song
  • 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.

So...

Anyone willing to nudge me in the right direction?

Thanks!

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 needed 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 needed 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.

$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->increments('id');
    $table->string('title');
});
// all references to artists are in the Pivot table ‘artist_song’

Schema::create('artists', function (Blueprint $table) {
    $table->increments('id');
    $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->foreign('song_id')->references('id')->on('songs')->onDelete('cascade');
    $table->integer('artist_id')->unsigned()->index();
    $table->foreign('artist_id')->references('id')->on('artists')->onDelete('cascade');
});

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 but the resulting code…

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

… returns 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.

06 Nov
1 year ago

Kimmer started a new conversation Eloquent Many To Many Query Searching Values From Both Tables. All Values Should Be Present.

I have a table with called “songs” which contains songs that have a “title”.

I also have a table called “artists” which contains artists that have a “spotify_id”.

A song can have many artist and an artist can blog to many songs so I have a pivot table “artist_song” which connects the “songs” and “artists” tables

In my models I have...

class Song extends Model
{
    public function Artists() {
            return $this->belongsToMany('App\Models\Artist');
    }
}

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

Via an API call this response comes in (extremely minified to only contain elements needed for this issue)

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

So far so good. Now I want to check if the song exists in the database by it’s title and all artists for this song.

The result can only be positive if the title and all artists are identical. Based on the example, should the song "Cool Song" exist in the database with “Artist1” and “Artist2” and the API call returns “Cool Song“ with only “Artist1”, the result of the query should be negative because not identical.

The amount of artists will be variable depending on the song. Most songs only have one artist but some songs can have a lot of artists.

What would the Eloquent query look like? A very helpful colleague quickly typed something like this on a notepad.

$artists = $track->artists;

$existingSong = Song::with('Artists', function($query) use ($artists) {
            
    foreach($artists as $artist) {
        $query .= $query->where('spotify_id', $artist->id);
    }
    return $query;

})->get()->where('title', $track->name);

return $existingSong;

But this results in this error:

ErrorException in Str.php line 72:
mb_strpos() expects parameter 1 to be string, object given

Thanks!

22 Oct
1 year ago

Kimmer left a reply on Installing Laravel Outside Of The Httpdocs Folder

The .htaccess files was missing in the public folder. Adding it fixed the test link. Logging is still doesn't work but I think I'm getting close.

This thread has gone way out of topic so if I have another question I will start a new topic.

Thanks for your help!

Kimmer left a reply on Installing Laravel Outside Of The Httpdocs Folder

I tried that but it doesn't make a difference. Works on my local dev version but not on the server. I also tried removing the leading slash from the routes but also no difference.

I don't think it's the blade template. It seems my routes file just doesn't do anything on the server.

Kimmer left a reply on Installing Laravel Outside Of The Httpdocs Folder

Strange, the testlink I created also does not work. Made a simple a tag like this

<a href="{{ url('/test') }}">test</a>

and this in my routes/web.php file.

Route::get('/test', function () {
    return view('welcome');
});

Works locally but not on my server.

Kimmer left a reply on Installing Laravel Outside Of The Httpdocs Folder

Yes I have the structure now, but it is different then my development version. I think I'll manage to solve that. At the moment the differences are minimal so I'm focussing on getting everything to work on my production server first. This is mainly what I'm struggling with.

Your tip with url() did the trick. I just had to work out how to use that with Laravel Mix and versioning. My app is loading the CSS and JS files as it should. This is what the stylesheet link tag looks like.

<link rel="stylesheet" href="{{ url(mix('css/app.css')) }}">

However, my routes don't seem to work. Getting 404s. The url is fine. At the moment my app only has one link available for guests, a login via Socialite and Spotify. I'm going to create a testlink to a simple page and see if that works.