datarecall

datarecall

Member Since 10 Months Ago

Experience Points
43,260
Total
Experience

1,740 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
411
Lessons
Completed
Best Reply Awards
0
Best Reply
Awards
  • start your 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-in-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 Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • evangelist 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.

Level 9
43,260 XP
Oct
15
5 days ago
Activity icon

Started a new Conversation Help With New Structure Ideas

I am looking at re-designing my database structure for part of this site I am working on and would love your input.

I currently have a Diary and a Diary can have many Weeks,

When they first set up their diary they can attach products to the "setup" of what products will be used throughout the diary (product type 1, product type 2, product type 3).

Then in the Weeks when they add new weeks to the Diary they can add another "product type 4" to it only, all other product types will not be allowed to be added here.

I originally went with a productables polymorphic table so I could attach products to any model diary or week, however, this made it seemingly difficult to find all products that were used in a diary since a Week belongs to a Diary and made me have to write a lot of joins and to get the proper results.

Any thoughts on how best to set up the new structure?

Oct
06
2 weeks ago
Activity icon

Started a new Conversation Livewire + Alpine + Flickity Help

I have been stuck on this for a couple of days, trying to get my flickity carousels to work properly.

I have a carousel with 10 buttons on it. It modifies the $week property on click. This is inside a carousel so the user can scroll through the buttons; however, when a user setWeek by click on the button, the page re-renders and displays the new data; however, the flickity carousel does not re-render. It works on initial load, but I can't figure out in alpine to re-render the carousel. I looked at hooking into the dom and listening for element.updated but could not figure out how to do it with the way I have alpine setup considering there are multiple carousels on this page.

<div x-data
     x-init="
     new Flickity( $refs.slider, flickityOptions)
    "
     >
    <div x-ref="slider" class="carousel">
        {{$slot}}
    </div>
</div>

the week is set through livewire

 <a wire:click.prevent="setWeek({{$diaryWeek->number}})" href="{{ route('diary.show', [$diary->id, Str::slug($diary->name), 'week' =>$diaryWeek->number]) }}">
Oct
03
2 weeks ago
Activity icon

Replied to Filter On HasOne

But that just filters the latestweek so if it has a week of another type it will show.

Activity icon

Started a new Conversation Filter On HasOne

I have a has one relationship that will get the latest week from a diary

public function latestWeek()
    {
        return $this->hasOne(Week::class)->latest('number');
    }

I am trying to filter diaries that have latestWeek.type = $type

protected function type($type)
    {
        return $this->builder->whereHas('latestWeek', function($q) use ($type){
            $q->where('type', '=', $type);
        })->whereDoesntHave('harvests');

The problem is that this is filtering the latest week not filtering on the latest week what I am trying to do is $diaries->where('latestWeek.type','=',$type) but what I am returning is only weeks that have had that type before if that makes sense.

Oct
01
2 weeks ago
Activity icon

Replied to Livewire Pagination

Thats what I was thinking, need to find a way to append the request parameters to the URL somehow though, any thoughts on how I would do that @snapey ?

Sep
29
3 weeks ago
Activity icon

Replied to Livewire Pagination

@snapey its giving the wrong href link when using livewire pagination, unless I'm missing something. From what I can tell the pagination relies on the nextPage method, so there is no way for a bot to realize that appending page 2 to the query string will give u page 2 results.

When using nextPageUrl it gives you this as the link

/livewire/message/forum-home?page=5

Sep
28
3 weeks ago
Activity icon

Started a new Conversation Livewire Pagination

When creating a custom pagination view, do you have any idea how I can add withQueryString() and page increment/decrement so bots can crawl it (google etc)

this is what I am using for my custom pagination view currently:

@if ($paginator->hasPages())
{{--    {{dd($paginator->nextPageUrl())}}--}}
    @if($paginator->hasMorePages())
        <div class="load-new-reply has-text-centered mt-15 mb-30">
            {{dump($paginator->nextPageUrl())}}
            <a wire:click.prevent="nextPage" href="{{ route('forum.index', ['page' => $paginator->currentPage() + 1]) }}" rel="next"
               class="has-text-weight-bold">{{ $message }}</a>
        </div>
    @endif
@endif

While this works it doesn't allow for queryString so changing it to :

@if ($paginator->hasPages())
{{--    {{dd($paginator->nextPageUrl())}}--}}
    @if($paginator->hasMorePages())
        <div class="load-new-reply has-text-centered mt-15 mb-30">
            {{dump($paginator->nextPageUrl())}}
            <a wire:click.prevent="nextPage" href="{{ $paginator->nextPageUrl() }}" rel="next"
               class="has-text-weight-bold">{{ $message }}</a>
        </div>
    @endif
@endif

Produces this URL in the href :

/livewire/message/forum-home?page=5

Which is uncrawlable, is there any way you can think of to provide the query string and get livewire to have the proper href's in the pagination links?

Sep
26
3 weeks ago
Activity icon

Started a new Conversation Livewire Filters

I am converting some of my pages to livewire components I have this filter based on the filters the episodes for the Forum TDD series this is my livewire component:

<?php

namespace App\Http\Livewire;

use App\Channel;
use App\Filters\ThreadFilters;
use App\Queries\ThreadQuery;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Component;
use Livewire\WithPagination;

class ForumHome extends Component {

    use WithPagination, AuthorizesRequests;

    public $channel;

    private $filters;

    public function mount(Channel $channel, ThreadFilters $filters)
    {
        $this->channel = $channel;
        $this->filters = $filters;
    }

    public function render()
    {
        $threads = ThreadQuery::getThreads($this->channel, $this->filters);

        return view('livewire.forum.home', [
            'threads' => $threads
        ]);
    }

}

On the first page load, this works fine and thread filters is set on the initial load if I dump($this->filters); in the render method it displays: https://share.getcloudapp.com/ApuL6B1d

Since this is using pagination when I click next page I get the error:

Argument 2 passed to App\Queries\ThreadQuery::getThreads() must be an instance of App\Filters\ThreadFilters, null given, called in /home/vagrant/code/gd/app/Http/Livewire/ForumHome.php on line 31

The error seems right since my threadQuery is setup like:

public static function getThreads(Channel $channel, ThreadFilters $filters){

I just don't know why its not keeping the data consistent when $this->filters is being set on mount().

Sep
21
4 weeks ago
Sep
18
1 month ago
Activity icon

Replied to Help With Refactor

thank you @erikverbeek it great to see someone's process, on a refactor like this.

When you say create a global user() helper do you mean something like:

<?php
function user($guard = null) {
    return auth($guard)->user();
}

generate a service provider for your helper by the following command

php artisan make:provider UserHelperServiceProvider

in the register function of your newly generated UserHelperServiceProvider.php add the following code

require_once app_path('Helpers/UserHelper.php');

now in your config/app.php load, this service provider and you are done

'App\Providers\UserHelperServiceProvider',
Activity icon

Started a new Conversation Help With Refactor

I have a pivot table that allows users to ignore other users and now I need to check every model to make sure the publishing user_id is not in that user's ignore list so it doesn't display it. most of my controllers look something like this but it seems redundant and feels like the wrong way to go about it.

The query classes are all cached, so doing it through eloquent would only hurt since the queries are already cached. Also, this returns the paginated results so caching can happen on a per-page basis

Any help is appreciated.

$diaries = DiaryQuery::getPaginated($filters,$page);

        if(auth()->check()){
            $ignores = auth()->user()->ignores()->get();
            if($ignores->isNotEmpty()){
                $diaries = $diaries->filter(function ($diary) use ($ignores){
                    return !$ignores->contains('id', $diary->user_id);
                });    
            }
        }
Sep
15
1 month ago
Activity icon

Started a new Conversation Variable In Blade Component Name

Using Blade X components how would you accomplish something like

<x-profile.activities.{{$activity->type}} :activity="$activity"></x-profile.activities.{{$activity->type}}>

where type is something like created_thread, this is dynamic so blade if's would clutter a lot fo the blade template up? Or am I stuck with @include

Sep
14
1 month ago
Activity icon

Replied to Testing Notifications

@sergiu17 it needs the first there to get the comment details, everything works except when the notification implements ShouldQueue that is what is causing that error for some reason

Sep
13
1 month ago
Activity icon

Started a new Conversation Stop DB & Mail Notifications When Connected To Pusher

I have a conversation that uses pusher to send updates to conversation peers it also notifies email and database that someone has messaged them.

However, if they are connected to pusher they will get a live update that the chat has been updated is there a way to stop the other notifications from happening if a push was successfully sent to that user.

I thought about hooking into the Echo

window.Echo.private('conversations.'+this.conversation.id)
                .listen('NewMessageAddedToConversation', (e) => {
                    this.chats[index].messages.push(e.message)
			
                    this.$forceUpdate();
			//SOMETHING HERE TO POST AND READ THE NOTIFICATION
                });

1 problem I see with this is the other notifications will still go out but it will allow the user to get more broadcasts since I am checking the notification table for duplicates, so this still does not fix my problem where the user will get spammed with notifications.

Activity icon

Replied to How To Send 1 Notification To User

I ended up going with something like this, it seems really dirty I am sure there is a better way this is my conversation model

    public function notify(Message $message)
    {
        $this->users()
            ->where('users.id' ,'!=',$message->user_id)
            ->get()->each(function ($user, $key) use ($message){
                $dupe = $user->checkDuplicateNotification('conversation_id', $message->conversation->id);
                if(!$dupe){
                    $user->notify(new ConversationWasUpdated($message));
                }
            });
    }

This is my user model

    public function checkDuplicateNotification($variable, $compare){
        $notifications = $this->unreadNotifications->toArray();
        foreach($notifications as $notification){
            if(isset($notification['data'][$variable]) && $notification['data'][$variable] ==  $compare){
                return true;
            }
        }
        return false;
    }
Activity icon

Started a new Conversation Testing Notifications

I am writing a test to make sure that the user can Axios all their notifications from the database, however, all my notifications implement ShouldQueue which is causing this error if I do not use Notification::fake();

Right now I have this is my test I am working on

$thread = factory(Thread::class)->create();
        $this->withoutExceptionHandling();
        $this->signIn();

        $thread->subscribe();

        $this->assertCount(1, $thread->subscriptions);

        $this->assertCount(0, auth()->user()->notifications);

        $comment = factory(Comment::class, 1)->make([
            'commentable_type' => 'App\Thread',
            'commentable_id'   => $thread->id,
        ])->first();

        $thread->addComment($comment, $comment->user_id);

        $this->assertCount(1, auth()->user()->notifications);
        
        $response = $this->get(route('api.notification.index'))
            ->assertSuccessful()
            ->assertStatus(200);

The main part of the test is the get so I can determine if the user can pull all their notifications from the controller, but I am receiving this error

Illuminate\Database\Eloquent\ModelNotFoundException : No query results for model [App\Comment].
Sep
12
1 month ago
Activity icon

Replied to How To Send 1 Notification To User

@laracoft i was thinking of doing it in the message model notify but how would you check them first?

Activity icon

Started a new Conversation How To Send 1 Notification To User

I have built a small messaging system so users can message each other pusher and notifications are working however if a user sends 3 messages in a row it will create 3 notifications for the user:

https://share.getcloudapp.com/z8uZ2wv1 Question 1: Other then implementing a unique on the MySQL like below how would you make sure that only one notification is created for that user saying he has a new message Question 2: Can notifications themselves push to pusher or should it be done on the event class itself?

$table->unique(['type','notifiable_type','notifiable_id','data','read_at']);

Event: NewMessageAddedToConversation

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

    public $message;
    /**
     * Create a new event instance.
     *
     * @param MessageResource $message
     */
    public function __construct(Message $message)
    {
        $this->message = $message;
        $this->dontBroadcastToCurrentUser();
    }
    /**
     * Get the subject of the event.
     */
    public function subject()
    {
        return $this->message;
    }

//    public function broadcastAs()
//    {
//        return 'message.created';
//    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('conversations.'.$this->message->conversation->id);
    }
}

This should broadcast to pusher if they are on online and on the channel EventServiceProvider

NewMessageAddedToConversation::class => [
            NotifyConversationPeers::class
        ]

NotifyConversationPeers.php

public function handle($event)
    {
        $message = Message::find($event->message->id);
        $message->notify($event->message);
    }

Message Model

public function notify()
    {
        $this->conversation->users->where('id' ,'!=',$this->user_id)->each->notify(new ConversationWasUpdated($this));
    }

Notifications\ConversationWasUpdated

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use App\Message;
use App\User;

class ConversationWasUpdated extends Notification
{
    use Queueable;
    public $message;
    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct(Message $message)
    {
        $this->message = $message;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['database'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->line('The introduction to the notification.')
                    ->action('Notification Action', url('/'))
                    ->line('Thank you for using our application!');
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {

        $user = User::find($this->message->user_id);
        
        return [
            'message'  => $user->name . ' sent you a message ',
            'notifier' => $user->id,
            'link'     => $this->message->conversation->route
        ];
    }
}
Sep
09
1 month ago
Activity icon

Started a new Conversation Suggestions For: Messenger W/Pusher?

have any of you had any luck with a package that is already done for laravel + vue + pusher for messaging between users, I have gone through about 10 of them most of them don't really work. The ones that do you need to hack the installs to get to work with L7.

Any help would be appreciated.

Aug
23
1 month ago
Activity icon

Started a new Conversation Union And Group By Help

I have this query right now and it is somewhat working however if there is only 1 supplier in the database the result is giving me 2 results, I need to figure out a way so its grouped by suppliers.id after the union is done? Maybe a subquery?

$first = Supplier::select('suppliers.*')
                ->addSelect(DB::raw('COUNT(DISTINCT(diaries.id)) AS diaries_count'))
                ->addSelect(DB::raw('COUNT(DISTINCT(harvests.id)) AS harvests_count'))
                ->addSelect(DB::raw('AVG(product_rating.score) AS score'))
                ->addSelect(DB::raw('COUNT(DISTINCT(products.id)) AS products_count'))
                ->addSelect(DB::raw('AVG(harvests.dry_weight / harvests.num_plants) AS grams_count'))
                ->withCover()
                ->with('type')
                ->join('products', 'products.supplier_id', '=', 'suppliers.id')
                ->leftJoin('product_rating', 'product_rating.product_id', '=', 'products.id')
                ->leftJoin('productables', function ($join) {
                    $join->on('products.id', '=', 'productables.product_id')
                        ->where('productables.productable_type', Week::class);
                })
                ->leftJoin('weeks', 'weeks.id', '=', 'productables.productable_id')
                ->leftJoin('diaries', 'diaries.id', '=', 'weeks.diary_id')
                ->leftJoin('harvests', 'harvests.diary_id', '=', 'diaries.id')
                ->groupBy('suppliers.id')
                ->where('type_id', '=', $type->id);

            return Supplier::select('suppliers.*')
                ->addSelect(DB::raw('COUNT(DISTINCT(diaries.id)) AS diaries_count'))
                ->addSelect(DB::raw('COUNT(DISTINCT(harvests.id)) AS harvests_count'))
                ->addSelect(DB::raw('AVG(product_rating.score) AS score'))
                ->addSelect(DB::raw('COUNT(DISTINCT(products.id)) AS products_count'))
                ->addSelect(DB::raw('AVG(harvests.dry_weight / harvests.num_plants) AS grams_count'))
                ->withCover()
                ->with('type')
                ->join('products', 'products.supplier_id', '=', 'suppliers.id')
                ->leftJoin('product_rating', 'product_rating.product_id', '=', 'products.id')
                ->leftJoin('productables', function ($join) {
                    $join->on('products.id', '=', 'productables.product_id')
                        ->where('productables.productable_type', Diary::class);
                })
                ->leftJoin('diaries', 'diaries.id', '=', 'productables.productable_id')
                ->leftJoin('harvests', 'harvests.diary_id', '=', 'diaries.id')
                ->where('type_id', '=', $type->id)
                ->union($first)
                ->groupBy('suppliers.id')
                ->distinct()
                ->filter($filters)
                ->orderByDesc('score')
                ->paginate(config('rollitup.pagination.SuppliersPerPage'));
Aug
13
2 months ago
Activity icon

Replied to Eloquent Sub Query

@michaloravec thanks that worked perfectly.

Activity icon

Replied to Eloquent Sub Query

$product = Product::find(88);
        $diaries = Diary::whereHas('productables', function ($query) use ($product) {
            $query->where('product_id', $product->id);
        })->get();
        dd($diaries);

Product 88 is attached to App\Diary and it is also attached to a Week (which belongs to a different diary) https://share.getcloudapp.com/lluYYEPp

The result is pulling the right Diary but since this product is attached to the Week as well need to figure out a way to grab the diary that corresponds to those weeks.

Activity icon

Replied to Eloquent Sub Query

Just sent you an email @michaloravec

Activity icon

Replied to Eloquent Sub Query

@michaloravec we already setup the morphto on the productable model though so using it like above is forcing us to do it that way.

Activity icon

Replied to Eloquent Sub Query

@michaloravec ok so

$diaries = Diary::whereHas('productables.productable', function ($query) use ($product) {
            $query->where('id', $product->id);
        })->get();

Since Productables model has productable method and its a morphto it wants me to use a wherehasmorph but then we run in into the problem of the nested relationships again

Activity icon

Replied to Eloquent Sub Query

@michaloravec I get that part but say on my product page I want to list all diaries

$product = Product::find(1);
$diaries = Diary::
			//See if this product is used on the diary itself
				//if it is return the diary
			// see if the product is used on the week
				//if it is used on a week find the corresponding diary that has this week and return it
Activity icon

Replied to Eloquent Sub Query

@michaloravec thanks alot for all your help, one other question for you if you don't mind since you kind of understand the table structure

If I have a product now with a specific ID how would you determine the diaries that use this product since its a polymorphic table and the week belongs to a specific diary you would need to figure out a way to do a subquery to attach the App\Week with the Diary_id ?

Activity icon

Replied to Eloquent Sub Query

Got it the orWhereIn was causing the issue @michaloravec I switched it to wherein on the id

Activity icon

Replied to Eloquent Sub Query

I think its the way its joining up this is the query that is being produced by the one we have done so far

SELECT
	*
FROM
	`products`
WHERE
	EXISTS (
		SELECT
			*
		FROM
			`productables`
		WHERE
			`products`.`id` = `productables`.`product_id`
		AND (
			(
				`productables`.`productable_type` = 'App\Diary'
				AND EXISTS (
					SELECT
						*
					FROM
						`diaries`
					WHERE
						`productables`.`productable_id` = `diaries`.`id`
					AND `id` = 13
				)
			)
			OR (
				`productables`.`productable_type` = 'App\Week'
				AND EXISTS (
					SELECT
						*
					FROM
						`weeks`
					WHERE
						`productables`.`productable_id` = `weeks`.`id`
					OR (`id` IN(51, 52, 53, 54))
				)
			)
		)
	)

But the query I think it needs to be is:

SELECT
	*
FROM
	`products`
WHERE
	EXISTS (
		SELECT
			*
		FROM
			`productables`
		WHERE
			`products`.`id` = `productables`.`product_id`
		AND (
			(
				`productables`.`productable_type` = 'App\Diary'
				AND
				`productables`.`productable_id` = 13
			)
			OR (
				`productables`.`productable_type` = 'App\Week'
				AND		
				`productables`.`productable_id` IN(51,52,53,54)
				
			)
		)
	)
Activity icon

Replied to Eloquent Sub Query

Making headway @michaloravec ok so the results produced don't seem to be correct though that query is producing 44 results for $products however when I run these queries

dump($diary->products); //PRODUCES 1 Result
dump($diary->weeks->pluck('products')->collapse()); //PRODUCES 5 RESULTS

also I tried changing

$query->where('id', $diary->id);
$query->where('productable_id', $diary->id);

but the results still returned 44 so maybe the wherehasmorph filter isn't running at all ?

Activity icon

Replied to Eloquent Sub Query

Ok @michaloravec I got that all setup now the error is :

Call to undefined method App\Product::productables.productable()

but I can run it through tinker like so:

Psy Shell v0.10.4 (PHP 7.4.5 — cli) by Justin Hileman
>>> $p = Product::find(1)
[!] Aliasing 'Product' to 'App\Product' for this Tinker session.
=> App\Product {#4237
     id: 1,
     supplier_id: 1,
     name: "omnis",
     long_desc: "Dicta eveniet suscipit deserunt facere dolore necessitatibus
 provident atque. Maxime qui rerum sint quaerat non est dolore. Ut eos pariat
ur suscipit fuga illo aut dolorem consequatur. Quaerat velit totam aut possim
us.",
     release_date: "2018-04-18",
     active: 1,
     created_at: "2020-08-07 20:20:48",
     updated_at: "2020-08-07 20:20:48",
     media: Illuminate\Database\Eloquent\Collection {#4236
       all: [],
     },
   }
>>> $p->productables->first()->productable
=> App\Diary {#4231
     id: 12,
     user_id: 442,
     name: "Similique et adipisci quia vero et dolorem dolorem.",
     type: "gree",
     grow_medium: "hy",
     published_at: "2020-08-07 20:20:54",
     created_at: "2020-08-07 20:20:54",
     updated_at: "2020-08-07 20:20:54",
   }
>>>
Activity icon

Replied to Eloquent Sub Query

Sorry @michaloravec trying to explain everything here

I have a productable table which is more or less a pivot table that will link to the Diary / Week which contains the product_id here is a screenshot of the productable table: https://share.getcloudapp.com/P8ubb5e1

Then I have trying to query all products which are in this is the Product Model, I added this to my products model as per your instructions

public function productable()
    {
        return $this->hasMany(Productables::class,'product_id');
    }

for this part here:

public function productable()
{
    return $this->morphTo();
}

should I create the productable model and add that to it?

Activity icon

Replied to Eloquent Sub Query

this is in my Product Model:

public function productable()
    {
        return $this->morphTo('productable');
    }

when I add 'productable.productable' its giving me the error:

BadMethodCallException
Call to undefined method App\Product::productable.productable()
Activity icon

Replied to Eloquent Sub Query

@michaloravec this is the error that I get for that

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'products.productable_type' in 'where clause' (SQL: select * from `products` where ((`products`.`productable_type` = App\Diary and exists (select * from `diaries` where `products`.`productable_id` = `diaries`.`id` and `id` = 13)) or (`products`.`productable_type` = App\Week and exists (select * from `weeks` where `products`.`productable_id` = `weeks`.`id` or (`id` in (51, 52, 53, 54))))))

it seems to be looking in the products table not the productable table but the end result of the query its getting all the products in the diary, so would you need a subquery ?

Activity icon

Replied to Eloquent Sub Query

@michaloravec I saw that but how would you modify the query to use it properly?

$weekIds = $diary->weeks->pluck('id');
        $products = Product::query()
            ->whereHasMorph(
                'productable',
                ['App\Diary', 'App\Week'],
                function (Builder $query, $type) use($diary,$weekIds){
                    if ($type === 'App\Diary') {
                        $query->orWhere('productable_id', $diary->id);
                    }
                    if ($type === 'App\Week') {
                        $query->orWhereIn('productable_id', $weekIds);
                    }
                })->get();

gives me the error Column not found: 1054 Unknown column 'products.productable_type'

Activity icon

Started a new Conversation Eloquent Sub Query

I have a polymorphic table called productables it laid out like: https://share.getcloudapp.com/z8uZZYeR

product_id is linked to my products table

A product can be added to a diary and/or a product can be added to a week

If I want to grab all products that belong to that diary/weeks I am trying a query like this:

$weekIds = $diary->weeks->pluck('id'); //(this return an array of all the week ids for this diary)
$products = Product::query()
            ->whereHas('productable', function ($query) use ($diary) {
                $query->where([
                    'productable_type' => 'App\Diary',
                    'productable_id' => $diary->id
                ]);
            })->orWhereHas('productable', function ($query) use ($weekIds) {
                $query->whereIn([
                    'productable_type' => 'App\Diary',
                    'productable_id' => $weekIds
                ]);
            })->get();
        dd($products);

but productable is not a relationship on the Product model I don't think it should be either unless I am wrong?

Aug
07
2 months ago
Activity icon

Replied to Pagination

@jlrdw the problem is I can't figure out how to turn that method into an eloquent query right now this is just a collection which you can't paginate cleanly

Activity icon

Started a new Conversation Pagination

I have a method on my Supplier model that looks like:

public function getAllDiariesAttribute()
    {
        $products = $this->products();
        $weeks = $products->with('weeks.diary.latestWeek')->get()->pluck('weeks')->collapse()->pluck('diary');

        return $weeks->merge($products->with('diaries.latestWeek')->get()->pluck('diaries'))->flatten()->unique('id');
    }

Products are attached to the diary itself or to the weeks(which are attached to the diary)

Any thoughts on how you could make this an eloquent query to be able to do pagination on the results?

Aug
03
2 months ago
Activity icon

Started a new Conversation Webpack: Trying To Deploy Over Asset Limit

I am over my assets amount of 300 when uploading to vapor so I changed my webpack.mix.js file to :

const mix = require('laravel-mix');
var S3Plugin = require('webpack-s3-plugin')

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/assets/js')
    .sass('resources/sass/app.scss', 'public/assets/css')
    .copyDirectory('resources/img', 'public/assets/img')
    .version();

if (mix.inProduction()) {
    mix.version();
    mix.webpackConfig({
        plugins: [
            new S3Plugin({
                // Exclude uploading of html
                exclude: /.*\.html$/,
                // s3Options are required
                s3Options: {
                    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
                    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
                    region: process.env.AWS_DEFAULT_REGION
                },
                s3UploadOptions: {
                    Bucket: process.env.AWS_BUCKET,
                    CacheControl: 'public, max-age=31536000'
                },
                directory: 'public/assets'
            })
        ]
    });
}

if (mix.inProduction()) {
    const ASSET_URL = process.env.ASSET_URL + "/";

    mix.webpackConfig(webpack => {
        return {
            plugins: [
                new webpack.DefinePlugin({
                    "process.env.ASSET_PATH": JSON.stringify(ASSET_URL)
                })
            ],
            output: {
                publicPath: ASSET_URL
            }
        };
    });
}

This uploads all my asset files to amazon s3 however since the files are still there they are trying to deploy to vapor as well, any thoughts on how I can "clean" this directory after the upload but prior to deploying to vapor ?

Aug
01
2 months ago
Activity icon

Replied to Help With Resource

the problem with that is that you Can see that getRatings() is returning a paginate method which however that did get me to try to transform the array on an ->transform :

    public function index(Product $product)
    {
        $ratings = $this->getRatings($product);

        $ratings->transform(function ($item, $key) use($product){
            $item->product = $product;
            return $item;
        });
        return RatingResource::collection($ratings);
    }

while this produces the correct result I am wondering if there is a better way then looping through all the ratings and appending the product onto it.

Activity icon

Replied to Help With Resource

@geordiejackson $this->resource is giving me the resource from $ratings which is done here:

 /**
     * @param Product $product
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function getRatings(Product $product): \Illuminate\Contracts\Pagination\LengthAwarePaginator
    {
        return $product->ratings()
            ->latest()
            ->with('user')
            ->withPivot('score', 'body')
            ->paginate(config('rollitup.pagination.ratingsPerPage'));
    }

this is pulling data from the pivot table. So $this->resource is actually giving back the ratings()

Activity icon

Started a new Conversation Help With Resource

In my product controller I have

   public function index(Product $product)
    {
        $ratings = $this->getRatings($product);
        
        return RatingResource::collection($ratings);
    }
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class RatingResource extends JsonResource {
    /**
     * Transform the resource into an array.
     *
     * @param Request $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'user'  => $this->user,
            'product' => NEED TO HAVE $PRODUCT HERE
            'diary' => [
                'title' => $this->name,
                'url'   => $this->route,
                'comment_count' => $this->comment_count,
                'weeks_count' => $this->weeks_count
            ],
            'created_at' => $this->pivot->created_at,
            'score' => $this->pivot->score,
            'body'  => $this->pivot->body,
        ];
    }
}

In this resource, I need access to the $product since I need to send the product back when an ajax request is hit

Jul
30
2 months ago
Activity icon

Replied to Pagination Problem + Eloquent Help

@michaloravec I tried to do has many through but could retrieve the right results is this possible do you think?

Activity icon

Replied to Pagination Problem + Eloquent Help

@michaloravec @jlrdw the problem is that this is in the suppliers model/level and a supplier has many products which is why I thought I could maybe use HasManyThrough

$supplier->products()->with('ratings.user')->get()->pluck('ratings')->sortByDesc('created_at');

but this is returning a collection and you can't paginate a collection you can only paginate an eloquent query.

Activity icon

Started a new Conversation Pagination Problem + Eloquent Help

Help With Pagination

I have a model called "supplier" and this model has many "products"

Each product has a rating with is attached by a pivot table product_id / diary_id

I am currently using this to get the $supplier ratings

public function getRatingsAttribute()
    {
        return $this->products()->with('ratings.user')->get()->pluck('ratings')->sortByDesc('created_at');
    }

which returns this

Illuminate\Support\Collection {#4351
  #items: array:1 [
    0 => Illuminate\Database\Eloquent\Collection {#4359
      #items: array:1 [
        0 => App\Diary {#4364
          +fillable: array:5 [
            0 => "user_id"
            1 => "name"
            2 => "type"
            3 => "grow_medium"
            4 => "published_at"
          ]
          #with: array:2 [
            0 => "media"
            1 => "user"
          ]
          #appends: array:3 [
            0 => "thumbCoverUrl"
            1 => "route"
            2 => "isHarvested"
          ]
          #casts: array:2 [
            "user_id" => "integer"
            "published_at" => "datetime"
          ]
          #connection: "sqlite"
          #table: "diaries"
          #primaryKey: "id"
          #keyType: "int"
          +incrementing: true
          #withCount: []
          #perPage: 15
          +exists: true
          +wasRecentlyCreated: false
          #attributes: array:8 [
            "id" => "1"
            "user_id" => "1"
            "name" => "Sint illo eveniet sed eaque animi ratione."
            "type" => "outdoor"
            "grow_medium" => "soiless"
            "published_at" => "2020-07-30 18:14:47"
            "created_at" => "2020-07-30 18:14:47"
            "updated_at" => "2020-07-30 18:14:47"
          ]
          #original: array:14 [
            "id" => "1"
            "user_id" => "1"
            "name" => "Sint illo eveniet sed eaque animi ratione."
            "type" => "outdoor"
            "grow_medium" => "soiless"
            "published_at" => "2020-07-30 18:14:47"
            "created_at" => "2020-07-30 18:14:47"
            "updated_at" => "2020-07-30 18:14:47"
            "pivot_product_id" => "1"
            "pivot_diary_id" => "1"
            "pivot_score" => "1"
            "pivot_body" => "this is my comment"
            "pivot_created_at" => "2020-07-30 18:14:47"
            "pivot_updated_at" => "2020-07-30 18:14:47"
          ]
          #changes: []
          #classCastCache: []
          #dates: []
          #dateFormat: null
          #dispatchesEvents: []
          #observables: []
          #relations: array:3 [
            "pivot" => Illuminate\Database\Eloquent\Relations\Pivot {#4367
              +incrementing: false
              #guarded: []
              #connection: "sqlite"
              #table: "product_ratings"
              #primaryKey: "id"
              #keyType: "int"
              #with: []
              #withCount: []
              #perPage: 15
              +exists: true
              +wasRecentlyCreated: false
              #attributes: array:6 [
                "product_id" => "1"
                "diary_id" => "1"
                "score" => "1"
                "body" => "this is my comment"
                "created_at" => "2020-07-30 18:14:47"
                "updated_at" => "2020-07-30 18:14:47"
              ]
              #original: array:6 [
                "product_id" => "1"
                "diary_id" => "1"
                "score" => "1"
                "body" => "this is my comment"
                "created_at" => "2020-07-30 18:14:47"
                "updated_at" => "2020-07-30 18:14:47"
              ]
              #changes: []
              #casts: []
              #classCastCache: []
              #dates: []
              #dateFormat: null
              #appends: []
              #dispatchesEvents: []
              #observables: []
              #relations: []
              #touches: []
              +timestamps: true
              #hidden: []
              #visible: []
              #fillable: []
              +pivotParent: App\Product {#4352
                +fillable: array:5 [
                  0 => "supplier_id"
                  1 => "name"
                  2 => "long_desc"
                  3 => "active"
                  4 => "release_date"
                ]
                #with: array:1 [
                  0 => "likes"
                ]
                #appends: array:2 [
                  0 => "likesCount"
                  1 => "isLiked"
                ]
                #casts: array:4 [
                  "supplier_id" => "integer"
                  "active" => "boolean"
                  "dry_weight" => "integer"
                  "wet_weight" => "integer"
                ]
                #connection: "sqlite"
                #table: "products"
                #primaryKey: "id"
                #keyType: "int"
                +incrementing: true
                #withCount: []
                #perPage: 15
                +exists: false
                +wasRecentlyCreated: false
                #attributes: []
                #original: []
                #changes: []
                #classCastCache: []
                #dates: []
                #dateFormat: null
                #dispatchesEvents: []
                #observables: []
                #relations: []
                #touches: []
                +timestamps: true
                #hidden: []
                #visible: []
                #guarded: array:1 [
                  0 => "*"
                ]
                +mediaConversions: []
                +mediaCollections: []
                #deletePreservingMedia: false
                #unAttachedMediaLibraryItems: []
              }
              #foreignKey: "product_id"
              #relatedKey: "diary_id"
            }
            "user" => App\User {#4376
              #fillable: array:6 [
                0 => "is_admin"
                1 => "name"
                2 => "email"
                3 => "password"
                4 => "api_token"
                5 => "avatar"
              ]
              #with: array:1 [
                0 => "media"
              ]
              #appends: array:1 [
                0 => "thumbAvatarUrl"
              ]
              #hidden: array:2 [
                0 => "password"
                1 => "remember_token"
              ]
              #casts: array:2 [
                "is_admin" => "boolean"
                "email_verified_at" => "datetime"
              ]
              #connection: "sqlite"
              #table: "users"
              #primaryKey: "id"
              #keyType: "int"
              +incrementing: true
              #withCount: []
              #perPage: 15
              +exists: true
              +wasRecentlyCreated: false
              #attributes: array:10 [
                "id" => "1"
                "is_admin" => "0"
                "name" => "Marcus Prohaska"
                "email" => "[email protected]"
                "email_verified_at" => "2020-07-30 18:14:47"
                "password" => "yIXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi"
                "api_token" => null
                "remember_token" => "ps9PxiqFLk"
                "created_at" => "2020-07-30 18:14:47"
                "updated_at" => "2020-07-30 18:14:47"
              ]
              #original: array:10 [
                "id" => "1"
                "is_admin" => "0"
                "name" => "Marcus Prohaska"
                "email" => "[email protected]"
                "email_verified_at" => "2020-07-30 18:14:47"
                "password" => "yIXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi"
                "api_token" => null
                "remember_token" => "ps9PxiqFLk"
                "created_at" => "2020-07-30 18:14:47"
                "updated_at" => "2020-07-30 18:14:47"
              ]
              #changes: []
              #classCastCache: []
              #dates: []
              #dateFormat: null
              #dispatchesEvents: []
              #observables: []
              #touches: []
              +timestamps: true
              #visible: []
              #guarded: array:1 [
                0 => "*"
              ]
              #rememberTokenName: "remember_token"
              +mediaConversions: []
              +mediaCollections: []
              #deletePreservingMedia: false
              #unAttachedMediaLibraryItems: []
            }
          ]
          #touches: []
          +timestamps: true
          #hidden: []
          #visible: []
          #guarded: array:1 [
            0 => "*"
          ]
          +mediaConversions: []
          +mediaCollections: []
          #deletePreservingMedia: false
          #unAttachedMediaLibraryItems: []
        }
      ]
    }
  ]
}

The problem is I need to paginate these results but since its already a collection laravel will not allow you to easily do this, could I possibly get by with a HasManyThrough on the $supplier->ratings() then I should be able to paginate that?

Jul
29
2 months ago
Activity icon

Replied to Pivot Table Grouping

That worked perfectly @silencebringer thank you very much for your help!

Activity icon

Replied to Pivot Table Grouping

@silencebringer thanks for the help, still having an issue though it looks like: This is what returns from $this->techniques https://share.getcloudapp.com/9ZuXe4PO

/**
     * Determine the techniques used in a diary
     */
    public function getTechniquesAttribute()
    {
        return $this->weeks()->with('techniques')->get()->pluck('techniques', 'number');
    }

Since its week number as the key then a collection of techniques that are used inside that collection would you have to foreach through the first transform?

Jul
28
2 months ago
Activity icon

Replied to Pivot Table Grouping

@silencebringer thank you for your response, and I apologize I was not overly clear on the model

That model is the Diary Model the Diary Model Has Man Weeks and the pivot table is technique_id/week_id so

$diary->weeks()->with('techniques')

I think is the proper way but my code just feels ugly.

So in our Diary template we need to be able to show this

image TechniqueName
	   Weeks 1-3,5,9
Activity icon

Started a new Conversation Pivot Table Grouping

I have a pivot table called techniques and this pivot table connects techniques with weeks

public function getTechniquesAttribute()
    {
//NUMBER is the week number for the grouping later on
        return $this->weeks()->with('techniques')->get()->pluck('techniques', 'number');
    }

    public function getStringTechniquesAttribute()
    {
        $techniqueCollection = $this->techniques;

        $selectedTechniques = [];
        foreach ( $techniqueCollection as $weekNumber => $collection )
        {
            foreach ( $collection as $technique )
            {
                $selectedTechniques[$technique->name][] = $weekNumber;
            }
        }

        foreach ( $selectedTechniques as $name => $arr )
        {
            $desc = Str::plural('Week', count($arr));
            $out[] = [
                'name' => $name,
                'image' => 'NA',
                'desc' => $desc . ' ' . $this->rangeToStr($arr)
            ];
        }

        return $out;
    }
	

This code somewhat works but now I need the image column from techniques and it's forcing me to redo this, there has to be a better way to accomplish this I just don't see how.

Range to string just takes an array and implodes the array and does a range check so it will display 1-3,5,8

The end result in blade is:

image TechniqueName
	   Weeks 1-3,5,9
Jul
26
2 months ago
Activity icon

Replied to Help With Eloquent

Thank you for your reply @s4muel, I guess I'm wondering if an attribute is the proper place at all since most attributes are just computer but here I am merging 2 relationships into a value.