orest

Member Since 1 Year Ago

Experience Points
48,300
Total
Experience

1,700 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
424
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.

  • Community Pillar

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

Level 10
48,300 XP
Feb
25
1 month ago
Activity icon

Started a new Conversation AssertSee In Vue Components

I want to test whether some elements or text are present in the view when the view consists of Vue components.

I can't use assertSee because all the thing that i want to test are within the Vue component

What i've been doing in the controller is the following:

   if (request()->expectsJson()) {
            return $conversations;
        }

    return view('conversations.index', compact('conversations');

And in the test i send use getJson to get the json response.

$response = $this->getJson('/conversations')->json();

But, i would like to remove that condition that returns a json response because it is there only for testing purposes and i don't actually return a json response but instead i return a view.

Is there a way to assert that elements or text are present in the Vue components ?

Feb
21
1 month ago
Activity icon

Replied to Organise Routes That Return View And Json Response

@automica

i use Vue in many parts of the app so

  • The requests from Vue components that use axios hit the routes in ajax.php
  • The requests from Vue components that just use location.href to redirect hit the routes in web.php ( There are cases where i don't need to send an ajax request from a Vue component and instead i use location.href )
  • The requests from blade hit the routes in web.php

Does this approach make any sense ?

I was using groups before but i ended up with too many routes in the same file and it was bugging me.

Feb
20
1 month ago
Activity icon

Replied to Organise Routes That Return View And Json Response

@automica

i created another route file named ajax.php where i store all the routes that return json response.

All the requests to the ajax.php routes are made using axios

I did use a prefix for this, all routes in ajax.php have a prefix ajax

I am not sure what you mean by grouping by prefix rather than response because in my case the prefix ajax denotes that those routes receive ajax requestsand therefore json responses are returned.

In the article that you sent the author uses prefixes such as user and admin and therefore it makes sense to return either json or view from those routes.

Activity icon

Replied to Resolve Dependencies Based On Request

@jlrdw

I came up with the following solution.

Is there anything wrong with using a factory in the service container to resolve the dependencies ?

class AppServiceProvider extends ServiceProvider
{
       public function register()
       {
               $this->app->bind(SearchRequest::class, function ($app) {
                     return (new SearchRequestFactory(request()))->create();
                });
        }
}
class SearchController
{
        public function index(SearchRequest $request)
        {
                   $searchRequest->handle();
         }
}
class SearchRequestFactory
{
         protected $request;

         public function __construct(Request $request)
          {
                   $this->request = $request;
          }

          public function create()
          {
                 if($this->request->input('type') == 'tags')
                 {
                       return new SearchTagsRequest($this->request);
                  }
                  return new SearchPostsRequest($this->request);
            }
}

Your solution looks less complex though and i think i like it more.

Feb
19
1 month ago
Activity icon

Replied to Resolve Dependencies Based On Request

but then again i would have to create a new instance based on the parameter that is passed

$request->handle(request('type'));
public function handle($type)
{
     if($type == 'post')
      {
           (new SearchPostsRequest())->validate();
      }
}

which is more or less the same with what i have.

What i was trying to say is whether there is a way to resolve the needed SearchRequest in a service container or something like that.

So instead of using a factory method i could have something like

class SearchRequest
{
      protected $request ;

      public function __construct(SearchRequestType $request)
       {
                $this->request = $request;
       }
}

Where the SearchRequestType will be either SearchTagsRequest or SearchPostsRequest. This way the dependency is injected in the class and it not created within the class.

Activity icon

Replied to Resolve Dependencies Based On Request

@jlrdw the SearchTagsRequest and SearchPostsRequest do not handle the search functionality, they are classes that handle the validation of the search parameters.

For example if a user enters a username that does not exist then an error will be thrown.

They have pretty much the same purpose as a FormRequest class, that's why i used the suffix Request

Activity icon

Started a new Conversation Resolve Dependencies Based On Request

I'm trying to make use of the dependency injection technique wherever it is possible but there is a case where i cannot find an alternative.

For example

class SearchController extends controller
{
    public function index(SearchRequest $request)
     {
             $request->handle();
     }
}
class SearchRequest 
{
     protected $request;

     public function __construct(Request $request)
      {
               $this->request = $request;
      }

     public function handle()
     {
             $this->getSearchRequest()->validate();
     }
     
     public function getSearchRequest()
     {
              if($this->request->input('type') == 'posts' )
              {
                       return (new SearchPostsRequest($this->request));
              }
              return new(SearchTagsRequest($this->request());
     }
}

In this case, i cannot inject the SearchPostsRequest or the SearchTagsRequest because it depends on the type query parameter.

Is there a workaround for this case ?

Or it is ok to not inject the dependency and just create it within the class ( also known service locator pattern if i'm not wrong )

Feb
17
1 month ago
Activity icon

Started a new Conversation Organise Routes That Return View And Json Response

I'm building an MPA but I use Vue in many parts of the application.

I have separate routes and controllers for view and json responses

Currently, I have all the routes in the web.php but because they are quite a few routes I'd like to organise them.

How would you organise the routes in this case ?

Is it ok if I put the routes that return json in the api.php file and also change the middleware from api to web ?

Feb
11
2 months ago
Activity icon

Started a new Conversation Activity Logger For Different Purposes

I have an activities table where I store activities related to model events. For example, when a user creates a thread then the activity is recorded

activities

- id
- user_id
- subject_id
- subject_type
- type
Activity::create([
    'user_id' => auth()->id(),
    'subject_id' => $thread->id,
    'subject_type' => 'App\Thread'
    'type' => 'created_thread'
 ]);

Now, I want to track also the pages that a user (guest or registered ) views. The reason is to show what was the last activity of all current visitors.

For example, when an authenticated user visits a thread, the activity is recorded

Activity::create([
    'user_id' => auth()->id(),
    'guest_id' => null,
    'subject_id' => $thread->id,
    'subject_type' => 'App\Thread'
    'type' => 'viewed_thread'
 ]);

When a guest visits a thread

Activity::create([
    'user_id' =>null,
    'guest_id' => 1,
    'subject_id' => $thread->id,
    'subject_type' => 'App\Thread'
    'type' => 'viewed_thread'
 ]);

Another example is to visit a page that doesn't have any subject associated with it

When a guest visits the registration page, then the following activity will be recorded

Activity::create([
    'user_id' =>null,
    'guest_id' => 1,
    'subject_id' => null,
    'subject_type' => null,
    'type' => 'viewed_registration_page'
 ]);

The activities that are related to page views don't have to be stored in the database permanently and the reason is that I need these activities only to show what was the last activity of all current visitors and after that I can delete them.

The questions are:

  1. Should I store both type of activities in the same table, taking into consideration that the created type of activities will be permanently stored in the database, whereas the viewed activities don't have to be stored permanently, or should I create two different tables ?
  2. Is it a good idea to delete all viewed type of activities after some point, since I will not longer need them and if yes, should I do that with a cron job ?
Feb
10
2 months ago
Activity icon

Replied to Form Request Vs Service

Ok..i get your point, except for the testing part

How does it make it more difficult ?

In a feature test for example, you just want to test that when you hit that endpoint, there will be a conversation record in the database.

Activity icon

Replied to Form Request Vs Service

@martinbean You don't agree in in general with the following approach ?

class ConversationController extends Controller
{
      public function store(CreateConversationRequest $request)
      {
                 $request->persist();
       }
}

To me it looks the same with using a an action class with the difference that you don't pass the validated data as a parameter.

class ConversationController extends Controller
{
      public function store(Request $request, CreateConversationAction $action)
       {
                 $action->handle($request->validated());
       }

}

My concern about the form request was more about the fact that it will have to create not only the conversation, but also add a message and a participant.

Activity icon

Replied to Form Request Vs Service

@michaloravec

Thanks for the suggestion.

I have watched this series, that's where i got the method name persist

Form requests are an option of course but i think ( i am not sure ) that then it will have too many responsibilities.

  1. Authorize
  2. prepare for validation and Validate
  3. create conversation , add message, add participants
  4. fire event that conversation was created

Is it me ? or all the steps above are too many for a form request object ?

Activity icon

Replied to Form Request Vs Service

@martinbean thanks for the answer.

I have another confusion regarding the event listeners. I know it is not related to the initial question, but it is a good example for me to get a better understanding.

My confusion is when to use events and event listeners.

For example, in the example above

  • I could just create a conversation and then fire an event ConversationWasCreated
  • And I could have one listener to add a message to the conversation
  • one listener to add a participant to the conversation
  • one listener to subscribe the participant to the conversation
  • and one listener to notify the participant that he is part of a new conversation

On the other hand I could do all the above steps without using any events. So for example in the CreateConverastionAction I could have

class CreateConversationAction
{
      public function handle()
       {
             $title = request('title');
             $message = request('message');
             $participant = request('participant');
             
             $conversation = Conversation::create($title);
             $conversation->addMessage($message);
             $participant = $conversation->addParticipant($participant);
             $conversation->subscribe($participant);
             $participant->notify(new YouHaveNewMessage());
       }
}

In practice it can be done in both ways but I want to understand which way makes more sense.

So for example, in the CreateConverastionAction should I include only the steps that are crucial, which are

  1. Conversation::create();
  2. $conversation->addMessage();
  3. $conversation->addParticipant();

and use event listeners for the other steps, which are important but not crucial when creating a conversation

  1. $conversation->subscribe($participant)
  2. $participant->notify(new YouHaveNewMessage());

Is this a good way to think of it ?

Activity icon

Replied to Form Request Vs Service

  1. Do Actions have a different purpose compared to Services and Jobs, because especially if a Job is synchronous then all the above seem like the same thing to me.

  2. What is your opinion about the logic within the addParticipants and addMessage methods. Is it ok to have the logic for creating and firing an event in those methods or it would be better to call an Action again ?

public function addParticipants(array $usernames, $admin = false)
{
    (new (AddParticipantToConversationAction($this, $usernames, $admin))->handle();
}

public function addMessage($message, $user = null)
    {
        (new(AddMessageToConversationAction($this, $message, $user))->handle();
    }

One downside with this approach though is that i might end up with too many Action classes

Activity icon

Started a new Conversation Form Request Vs Service

I'm trying to figure out what is an elegant way to organize the following workflow

  1. Submit form ( the form contains the title of the conversation, the body of the message and the name of the invited participant.
  2. Create a conversation
  3. associate the message with the conversation
  4. associate the participant with the conversation
  5. notify the participant that a new conversation is created

My current approach is the following:

  1. I validate all the input values in the form request and then i call persist() to create the conversation.
  2. Then i associate the participants with the converastion
  3. I associate the message with the conversation
  4. finally i fire an even that the conversation was created

ConversationController

 public function store(Request $request, CreateConversationRequest $conversationRequest)
    {
        $conversation = $conversationRequest->persist();
        $conversation->addParticipants(
            $request->input('participants'),
            $request->boolean('admin')
        );
        $conversation->addMessage(
            $request->input('message')
        );
        
        event(new NewConversationWasCreated($conversation));
   }
public function addMessage($message, $user = null)
    {
        $message = $this->messages()
            ->create([
                'body' => $message,
                'user_id' => $user ? $user->id : auth()->id(),
            ]);

        event(new NewMessageWasAddedToConversation($this, $message));

        return $message;
    }
public function addParticipants(array $usernames, $admin = false)
    {
        $participantIds = $this->getParticipantIds($usernames);

        foreach ($participantIds->toArray() as $participantId) {
            $participants[$participantId] = ['admin' => $admin];
        }

        $this->participants()->syncWithoutDetaching($participants);

        event(new NewParticipantsWereAdded($this, $participantIds));
    }

The Issue is

I think that the ConversationController as well as the Conversation model have too much logic.

  1. First Alternative

Move the logic from the controller in the persist method of the Form request ( For some reason it doesn't look like a good idea to put everything in the form request)

  1. Second Alternative

Create a CreateConverastionService

I was thinking that if i create a service to encapsulate all the steps for creating a conversation Then probably i would have to get rid of the form request which means that i should handle the validation of the inputs within the service.

class ConversationCointroller extends Controller
{
     public function store(Request $request)
     {
            (new CreateConversationService($request))->handle();
      }
{
class CreateConversationService
{
     protected $request;

     public function __construct(Request $request)
     { 
             $this->request = request;
      }
    
     public function handle()
     {
             $this->validate();
             $conversation = Conversation::create(
               [
                'user_id' => auth()->id()
                'title' => $this->request->input('title')
               ]
             $conversation->addParticipants(
             $this->request->input('participants'),
             $this->request->boolean('admin')
             );
            $conversation->addMessage(
                  $this->request->input('message')
              );
        
        event(new NewConversationWasCreated($conversation));
             
     }

{

With regards to the methods addParticipants and addMessage, maybe i could keep them but instead of implementing the logic inside the methods, i could call another service to handle all the logic for ***adding a participant and adding a message .

public function addParticipants(array $usernames, $admin = false)
{
    (new (AddParticipantToConversationService($this, $usernames, $admin))->handle();
}

public function addMessage($message, $user = null)
    {
        (new(AddMessageToConversationService($this, $message, $user))->handle();
    }

Which one do you think is the better approach ?

Any other suggestion is welcome of course.

Feb
07
2 months ago
Activity icon

Replied to Log User Activities

@snapey

I already have a trait named RecordsActivty which takes care of model events ( i use that trait in Models )

It sounds interesting to do something similar in controllers

For some reason i tend avoid entering a string as an argument ( like in the example that you gave ) but i can give it a shot, since my approach looks a little bit messy.

One concern that i have with regards to entering a string as an argument in this specific case is that:

If i want the description of the activity to be longer, then i would have to map the short description that i enter in the controller, to a longer description, and i don't know if that is a good idea ( please let me know your opinion on this )

 public function show(Thread $thread)
    {
         event(new UserActivity('User viewed thread', $thread));
    }

Event

class UserActivity
{
     public function __construct($description, $subject = null)
     {
           $this->description = $description;
           $this->subject = $subject;
      }
}

Listener

class LogUserActivity
{
    public function handle(UserActivity $event)
    {
         Activity::create([
            'user_id' => auth()->id() ?? null,
            'type' => 'viewed',
            'description' => $this->getDescription($event->description),
            'subject_id' => $event->subject ? $event->subject->id : null,
            'subject_type' => $event->subject ? get_class($event->subject) : null
        ]);
     }
     
     public function getDescription($description)
     {
            $fullDescription = [
                'User viewed thread' => 'Longer description for this activity'
            ];
            return $fullDescription[$description];
     }
}
Activity icon

Replied to Log User Activities

@siangboon i have watched that series but it covers activities with regards to model events ( i have already used that approach in my app ) but in this case i need to find an elegant way to log activities that are not based on model events.

Activity icon

Started a new Conversation Log User Activities

I want to log user activities like, user viewed a thread or user viewed list of online users

My current approach is the following

  1. create an event for each activity
  2. create a listener for each event which will store a new activity record in the database with the respective description

For example

ThreadController extends Controller
{
    public function show(Thread $thread)
    {
         event(new UserViewedAThread($thread, auth()->user());
    }
}

Event

class UserViewedAThread
{

    public $thread;
    public $user;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($thread, $user)
    {
        $this->thread = $thread;
        $this->user = $user;
    }
}

Listener

class LogViewedThreadActivity
{
    public function handle(UserViewedAThread $event)
    {
        Activity::create([
            'user_id' => $event->user->id,
            'type' => 'viewed',
            'description' => 'Viewed thread',
            'subject_id' => $event->thread->id,
            'subject_type' => Thread::class
        ]);
    }
}
OnlineUsersController extends Controller
{
    public function index()
    {
         event(new UserViewedOnlineUsers(auth()->user());
    }
}

Event

class UserViewedOnlineUsers
{

    public $user;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($user)
    {
        $this->user = $user;
    }
}

Listener

class LogViewedOnlineUsersActivity
{
    public function handle(UserViewedOnlineUsers $event)
    {
        Activity::create([
            'user_id' => $event->user->id,
            'type' => 'viewed',
            'description' => 'Viewed list of online users ',
            'subject_id' => null,
            'subject_type' => null
        ]);
    }
}

The problem with this approach is that i will have to create multiple events and listeners and the listeners will have basically the same job, which is to store a new record in the activities table.

Is there a better way to approach this ?

Jan
27
2 months ago
Activity icon

Replied to Using Static Functions Bad Practice?

Jeffrey in one of his videos does the following

Activity::feed($user);

Where Activity is a model and the method feed returns the activities for the given user.

Is this a bad use case for static methods ?

Jan
21
2 months ago
Activity icon

Started a new Conversation Eager Load The Following Users

I have the following tables

users

- id

follows

- id
- user_id
- following_user_id

And the relationship to retrieve the users, that a user follows

 public function follows()
    {
        return $this->belongsToMany(
            User::class,
            'follows',
            'user_id',
            'following_user_id'
        );
    }

I want the authenticated user to know which users is following

I tried to eager load all the users that the authenticated user follows. The issues are

  1. When i try to access any page i get Maximum function nesting level of '256' reached, aborting!
  2. I don't know if this can work even without getting an error because i am not sure whether the list of follows will be updated since the authenticated user is cached and therefore i don't know if the global scope will actually retrieve the list of follows every time the page is reloaded.

User.php

  public static function boot()
    {
        parent::boot();
        static::addGlobalScope(function ($query) {
            return $query->when(auth()->check(), function($query){
                $query->with('follows');
            });
        });
    }

Then i tried to determine whether every user that is fetched on the page is followed by the authenticated user

The issue again here is the same error

  • When i try to access any page i get Maximum function nesting level of '256' reached, aborting!

User.php

public static function boot()
    {
        parent::boot();
        static::addGlobalScope(function ($query) {
            return $query ->followedByAuthUser();
        });
    }
public function scopeFollowedByAuthUser($query)
    {
        return $query->select()->selectRaw('CASE
                WHEN
                EXISTS
                (
                    SELECT
                        *
                    from
                        follows
                    where
                        follows.following_user_id = users.id
                        and follows.following_user_id != ?
                        and follows.user_id = ?
                )
                THEN
                1
                ELSE
                0
                END as followed_by_auth_user',
            [auth()->id(), auth()->id()]
        );

    }

Any suggestions on a different approach or let me know what i am doing wrong ?

I have to mention that when i create a small test with 2 users both approaches seem to work.

Jan
05
3 months ago
Activity icon

Replied to Query Using Recursive CTE

i am using MySQL 8.

I ended up using sql functions because for some reason the categories.id was not synchronised and its value was always the same when i used the query above

Jan
03
3 months ago
Activity icon

Started a new Conversation Query Using Recursive CTE

I have the following tables

Category

- id
- parent_id
- title

Threads

- id
- category_id
- title

A category have sub-categories and only the "leaf" category can have threads To explain further with an example

Computer -> Mac -> macbook

In this case the category macbook can have threads while the parent categories can't have threads.

What i want to achieve is to find the latest thread of a category, among all sub-categories

Computer -> Mac -> macbook
Computer -> Windows-> HP

In the example above, the categories macbook and HP have threads and i want for the parent category Computer to find the latest thread among the categories macbook and HP

To achieve that i am using recursive CTE and it seems to work when i test it with sqlite but when i use mysql it doesn't work

public function scopeWithLatestThread($query)
{
	return $query->addSelect(DB::raw('(
            SELECT
                id
            FROM
                threads
            WHERE
                threads.category_id in
                    (
                        with recursive recursive_categories (id) as
                        (
                            SELECT id
                            from categories as initial_categories
                            where initial_categories.id=categories.id
                            UNION ALL
                            SELECT remaining_categories.id
                            FROM recursive_categories JOIN categories as remaining_categories
                            on recursive_categories.id=remaining_categories.parent_id
                        )
                        SELECT id FROM recursive_categories
                    )
            ORDER BY
                updated_at DESC
            LIMIT 1) AS latest_thread_id')
        )->with('latestThread');     
}
public function latestThread()
{
    return $this->belongsTo(Thread::class);
}

Category::whereNull('parent_id')->withLatestThread()->get();
Dec
29
3 months ago
Activity icon

Replied to Config Db Connection During Testing

no i didn't because i need to change the database connection in a small number of tests within various test files.

changing the settings in phpunit.xml per test seems the same to me which is not very convenient.

i'd rather not setting env variables manually

Activity icon

Started a new Conversation Config Db Connection During Testing

In the phpunit.xml i have the following settings

 <server name="DB_CONNECTION" value="sqlite"/>
  <server name="DB_DATABASE" value=":memory:"/>

However, in some cases i need to use mysql and i set the config in the tests that i need mysql like

config(['database.default' => 'mysql']);
config(['database.connections.mysql.database' => 'dbname')]);

This works for Feature tests but for some reason when i do the same thing for Unit tests it does not work and i can't figure out why.

I have tried to do config:clear and cache:clear but it didn't help

Any ideas ?

Dec
26
3 months ago
Activity icon

Started a new Conversation Policy For Polymorphic Model

I have a model named Reply which can be either a

  • Thread reply
  • Comment
  • Message

In each case the policy for deleting a reply is different

Right now i have a ReplyPolicy

class ReplyPolicy
{
	public function deleteReply(User $user, Reply $reply)
	{
		//
	}

	public function deleteComment(User $user, Reply $reply)
	{
		//
	}

	public function deleteMessage(User $user, Reply $reply)
	{
		//
	}

}

And when i need to authorize the user i do

$this->authorize('deleteReply', $reply); 
$this->authorize('deleteComment', $comment); 
$this->authorize('deleteMessage', $message); 

Is there a better approach to handle this case ?

Dec
19
3 months ago
Activity icon

Started a new Conversation Set Env Variable In Phpunit At Runtime

by default the database variables in the phpunit.xml are the following:

 <server name="DB_CONNECTION" value="sqlite"/>
 <server name="DB_DATABASE" value=":memory:"/>

In one of my tests, i want to set the DB_CONNECTION to mysql because i test a functionality which uses whereJsonContains which is not supported by sqlite.

Is there a way to change the DB_CONNECTION at runtime ?

  • I have tried to use putenv and config but none of them work
  • I don't want the default connection to be mysql because it is considerably slower than using memory database
Dec
05
4 months ago
Activity icon

Started a new Conversation Difference Between WhereColumn And Where Clause

i have the following table, model and scope

conversations

- id

reads

- id
- readable_id
- readable_type
- user_id
- read_at

users

- id

I have the following scope for the Conversation model

public function scopeWithRead($query)
{
    return $query->addSelect(['read_at' => Read::select('reads.read_at')
                ->whereColumn('reads.readable_id', 'conversations.id')
                ->whereColumn('reads.readable_type', 'App\Conversation')
                ->whereColumn('reads.user_id', auth()->id()),
        ]);
}

when i test this scope i get the correct results but when i actually try to use it from the front end i get 500 error

$conversations = Conversation::withRead()->get();

On the other hand, if i change from whereColumn to where, i get wrong results when i test it and the front end does not give any errors, however the results are wrong

public function scopeWithRead($query)
{
     return $query->addSelect(['read_at' => Read::select('reads.read_at')
                ->where('reads.readable_id', '=', 'conversations.id')
                ->where('reads.readable_type', '=', 'App\Conversation')
                ->where('reads.user_id', '=', auth()->id()),
        ]);
}

Any thoughts on what is wrong ?

Nov
23
4 months ago
Activity icon

Replied to Determine If Model Is Recordable

@wingly thanks for the suggestion

i thought of that but it doesn't depend only on the repliable model. There is a case where it depends on another column of the replies table.

Activity icon

Started a new Conversation Determine If Model Is Recordable

I have a trait that records the activity of a model

RecordsActivityTrait

One of the models is polymorphic and in some cases i don't want to record the activity for that particular case.

The model name is Reply and it has a repliable relationship

For example

if ( $reply->repliable_type == 'SomeName' ){
 // activity should not be recorded    
}

Now i'm wondering if i should create a method isRecordable for all models that i want to record the activity

public function isRecordable()
{
     return true;
}

And for the Reply model it would be

public function isRecordable()
{
    if ( $this->repliable_type == 'SomeName' ){
         return false;
     }
     return true;
}
}

or should i create a class that determines if the model is recordable

For example

class DetermineRecordability
{
     public function handle($model)
      {
               if ( class_basename($model) == 'Reply' && $model->repliable_type == 'SomeName'){
                    return false;
               }
               return true;
       }
}

Which approach do you think is better ?

Nov
20
4 months ago
Activity icon

Replied to Get The Value That Failed The Validation Rule

@automica thanks!

this is what i am doing but in my case

i have an array as input and each value in the array must exist in the database.

If one of the values in the array does not exist, then the validation will fail and

what i am looking for is to grab that value that failed the validation.

For example let's say that the input consists of the array

['john', 'doe'] and ```doe`` does not exist in the database

i want to be able to concat the message with the value doe

so the message error that i want is

The following members could not be found: doe

Activity icon

Replied to Get The Value That Failed The Validation Rule

@jlrdw thanks!

What i want is to add the value that failed the validation in the error message and not to display it in the view. ( i want to return it as a json response )

However, the $errors variable displays only the error that occurred and not the value that caused the error.

Nov
18
4 months ago
Activity icon

Started a new Conversation Get The Value That Failed The Validation Rule

I have a FormRequest with the following rule.

It takes an array as input and for each value in the array the following rules are applied.

 public function rules()
    {
        return [
            'participants.*' => ['required', 'string', 'exists:users,name'],
        ];
    }

What i want, is to get the value from the array that failed the validation rule and use it in the error message.

What i have tried is to use the :attribute which returns a string with the name of the array and the index of the value that failed the validation.

So for example if the array participants has the following values

participants = ['john', 'doe']

and the value doe does not exist in the database, then the :attribute will return the string participants.1 And i can use the index from the resulting string to get the value from the input array.

 public function messages()
    {
        return [
            'participants.*.exists' => 'The following recipients could not be found: :attribute ,
        ];
    }

I was wondering if there is a more elegant way to get the value that failed the validation.

Nov
17
4 months ago
Activity icon

Replied to HasMany < - > HasOne Relationship Fail ->What Did I Miss

public function teammates()
{
    return $this->belongsToMany(User::class, ‘user_id’);
}

Make sure that in your team table, you have a user_id

Nov
16
4 months ago
Activity icon

Replied to Repetitive Validation Rules And Messages

the rules required and string are used on several validations and the error message is always the same.

i want to avoid writing the same rule and error message in multiple places

instead i was looking for a solution where the rule and the message are stored in one place ( thus a rule named BodyIsRequired ( but maybe what i'm want to do is "too much" and i can just write the same rule and message since they are quite simple )

I agree that it would be better to read the rules and understand them without reaching another file.

Activity icon

Started a new Conversation Repetitive Validation Rules And Messages

I'm trying to come up with a solution to avoid writing the same validation rules and messages over and over.

For example i have the following rules for the body attribute

 public function rules()
    {
        return [
            'body' => ['string','required'],
        ];
    }

I want the validation message for both rules to be the same.

One approach is to create two custom rules and, string and required and write the message that i want in each rule.

class BodyMustBeString implements Rule
{

    public function passes($attribute, $value)
    {
        if (is_string($value)) {
            return true;
        }
        return false;
    }

    public function message()
    {
        return 'Please enter a valid message.';
    }
}
class BodyIsRequired implements Rule
{

    public function passes($attribute, $value)
    {
        if (empty($value)) {
            return false;
        }
        return true;
    }

    public function message()
    {
        return 'Please enter a valid message.';
    }
}

The other approach is to create one custom rule for the body attribute attribute that consists of both string and required rules.

class BodyRules implements Rule
{

    public function passes($attribute, $value)
    {
        if ( !empty($value) && is_string($value)) {
            return true;
        }
        return false;
    }

    public function message()
    {
        return 'Please enter a valid message.';
    }
}

Do you have any other approach or do you agree with any of my approaches ?

Activity icon

Replied to Errors Are Available In View But Not In Test Assertion

Ok, thanks!

By the way, if could suggest a different approach in case you think that my approach is "wrong" or unusual, please let me know.

Activity icon

Replied to Errors Are Available In View But Not In Test Assertion

Yes that is what i am doing.

And the errors are displayed correctly in the view, i just couldn't assert that the session has errors in my test.

More specifically, in my search endpoint what i do is

  1. Validate the search parameters and if validation fails, then display the errors
  2. If validation passes, then search and display the results
 public function show(Search $search, SearchRequest $searchRequest)
    {
        $validator = $searchRequest
            ->validate($this->request)
            ->getValidator();

        if ($validator->fails()) {
            return view('search.show')
                ->withErrors($validator);
        }

        $results = $search->handle($this->request);
        $query = $this->request->input('q');

        return view('search.show', compact('results', 'query'));
    }

NOTE

The SearchRequest does not extend the FormRequest, it just uses the Validator facade to apply the validation rules that i have defined.

Activity icon

Replied to Errors Are Available In View But Not In Test Assertion

ok that's what i'm doing wrong :)

Is it considered wrong to validate the request parameters when you make a GET request ?

In my case, i make a search request using GET and before i start searching i want to validate the search parameters.

Activity icon

Started a new Conversation Errors Are Available In View But Not In Test Assertion

I'm using a custom validation and if the validation fails i return a view with the errors

validator = Validator::make(
            $request->input(),
            $this->rules($request),
            $this->messages()
        );

  if ($validator->fails()) {
            return view('some-view')
                ->withErrors($validator);
        }

The issue that i have is that even though in the view i do have access to the errors

@if($errors->any())
    @foreach($errors->all() as $error)
        {{ $error }}
    @endforeach
@endif

When i try to assert that the session has errors, it fails.

$this->get('path')->assertSessionHasErrors('error-name');

but if i assert that the error message is being displayed in the view, it works. And indeed the errors are being displayed when i use the browser.

$this->get('path')->assertSee('error message');

Any thoughts on what i might be doing wrong ?

Nov
14
4 months ago
Activity icon

Replied to Return To View With Errors If Form Request Validation Fails

is the only way to make this work to create a new endpoint that only shows the search results or errors ?

class SearchController extends Controller
{
    public function show(Search $search, SearchRequest $searchRequest)
    {
          $results = $search->handle();
          return redirect(route('search-results.show', compact('results'));
    }
}

class SearchRequest extends FormRequest
{
     public function failedValidation(Validator $validator)
    {
        return redirect(route('search-results.show')->withErrors($validator);
    }
}
Activity icon

Started a new Conversation Return To View With Errors If Form Request Validation Fails

I use a form request named SearchRequest to validate the query parameters and in case the validation fails, I want to return to search.show view in order to display the errors.

If the validation does not fail, then execute the search and return to search.show to display the results.

class SearchController extends Controller
{
    public function show(Search $search, SearchRequest $searchRequest)
    {
          $results = $search->handle();
          return view('search.show', compact('results');
    }
}

class SearchRequest extends FormRequest
{
     public function failedValidation(Validator $validator)
    {
        return view('search.show')->withErrors($validator);
    }
}

When the validation fails, it does return the search.show view but the errors are not available

search.show.blade.php

@if($errors->any())
    @foreach($errors->all() as $error)
         <p> {{ $error }} </p>
    @endforeach
@else
    <p> {{  $results  }} <p>
@endif

I have also tried to redirect instead of returning a view in the failedValidation method

 public function failedValidation(Validator $validator)
    {
        return redirect(route('search.show'))->withErrors($validator);
    }

But for some reason the first time that I hit the endpoint, it does not show the errors. I have to refresh to display the errors and I don't get why that happens.

Any thoughts ?

Nov
13
4 months ago
Activity icon

Replied to Return Json Response Or A View

In the case where there is only a search bar ( a single input ) then yes it looks nice to display the results on the same page.

However in the case where of a search form ( multiple inputs ) it does not look very nice to me at least because the search form already takes a lot of space.

You are right it would be better to stick with either Ajax or search form. But i saw this mix on Macrumors and I wanted to create the same thing and I was not sure how to do it.

So the point was to use a search form but in case something goes wrong, to stay on the same page and at the same time give some feedback to the user, which can be achieved using Ajax

Activity icon

Replied to Return Json Response Or A View

@bugsysha

The reason I want to return a view is because the current page is a search form and if I return json data I will have to show in the same page the search form and the results of the search which will be a mess.

That’s why I want to go to a different view to display the search results

Nov
12
4 months ago
Activity icon

Started a new Conversation Return Json Response Or A View

I have a search functionality and i want to return either

  1. A json response which consists of an exception message in case no results are found or an exception is thrown during search

  2. a view with the search results if everything works properly

currently the only way i can think of dealing with this is

  • Send a search request
  • return error message. ( if any error occurs or no results are found )
  • send another search request to view the results ( if results are found and no exceptions are thrown )

Search.vue

search(){
	axios.get('/search/' + queryParameters)
	.then(() => this.showResults())
        .catch((error) => flash(error.message));
},
showResults(){
	location.href = '/search/results' + queryParameters;
}

And in laravel i will have the following routes

First make a search and if any exceptions are thrown ( the exceptions are thrown by the Search class ) then a response message is returned ( the response message is handled in Handler.php )

Route::get('/search', function(Request $request, Search $search){
	
	$search->handle($request);
});

If results are found and no exceptions are thrown then send a request to the following route

Search and return a view with the results ( this route is called by the showResults method in Search.vue

Route::get('/search/results', function(Request $request, Search $search){
	$results = $search->handle($request);
	return view('search.show', compact('results');
})

Is there an alternative to what i'm trying to do ?

Because right now in order to make a search and get results, i have to send 2 requests and search 2 times.

Nov
11
5 months ago
Activity icon

Started a new Conversation Handle Response Message In Front Or Back End ?

When i make a request from the front end to the back end ( post, get etc) with axios for example

I can use then and catch to handle either a successful or a failed request and flash a message in the front end to give feedback to the user.

For example.

axios.get('/apples')
.then((response) => flash("You got the apples"))
.catch((error) => flash("You didn't get the apples"));

Or i can write the messages in the back end and then use them to flash the messages in the front end.

For example

axios.get('/apples')
.then((response) => flash(response.message)
.catch((error) => flash(error.message));

My question is whether there is a reason to prefer either one, or it does not matter ?

Nov
09
5 months ago
Activity icon

Replied to Nested Foreach

Where are the buttons ?

What is the structure of the fields ? Probably you see extra buttons because each field has more elements than you expect it to have

Nov
08
5 months ago
Activity icon

Replied to Fetch One Record From One To Many Relationship

@tykus thanks!

wouldn't it be redundant to have the same user_id in both the conversations table and the conversation_participants table for the same conversation record ?

Activity icon

Started a new Conversation Fetch One Record From One To Many Relationship

I have the following tables

users
- id
conversations
- id
conversation_participants
- id
- conversation_id
- user_id

Now each conversation is created by a user.

What i'm looking for, is to create a relationship to get the user who started the conversation.

  • The user who created the relationship can be determined using the conversation_participants table.
  • The first participant of the conversation is always the user who started the conversation.

I've tried to do that using a belongsToMany relationship and fetch only 1 record. But it returns a collection, while i need a model.

class Conversation extends Model
{
    public function starter()
    {
           return $this->belongsToMany(
            User::class,
            'conversation_participants',
            'conversation_id',
            'user_id'
        )->orderBy('created_at','asc')->take(1);
    }
}

Is there a way to create such a relationship ?