FrazeColder

Member Since 2 Years Ago

Experience Points
1,670
Total
Experience

3,330 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
2
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 1
1,670 XP
Nov
23
1 month ago
Activity icon

Replied to Laravel Nova: Delete Images From Disk When Content Is Modified And Image Is Removed

@bobbybouwmann Do you have any article or documentation where I can look that up?

Nov
22
1 month ago
Activity icon

Started a new Conversation Vue Js Clipboard: How To Allow Quill Mention Chars?

Hi,

I am using this package here to support mentions within my comments. The problem I am facing is that when I type a @ and select a user everything works fine! The mention tag is getting placed correct!

But when I edit an comment again the mention gets kind of destroy. Normally the mention looks like this @myuser. But when clicking on edit the mention looks like this @a href="http://mywebsiteproject.test/user/myuser" target=_blankmyuser.

I know this comes from another package I am using which is called quill-paste-smart.

So, there is a problem which the text which gets pasted into the textfield... But I don't know why. The HTML Tag of a mention looks like this:

<span class="mention" data-index="0" data-denotation-char="@" data-id="1" data-value="<a href=&quot;http://mywebsiteproject.test/user/myuser&quot; target=_blank>myuser" data-link="http://mywebsiteproject.test/user/myuser">
    <span contenteditable="false">
        <span class="ql-mention-denotation-char">@</span>
        <a href="http://mywebsiteproject.test/user/myuser" target="_blank">myuser</a>
    </span>
</span>

But after I pressed edit the html tags look like this:

<span class="mention" data-index="0" data-denotation-char="@" data-id="1" data-value="a href=&quot;http://mywebsiteproject.test/user/DealBee&quot; target=_blankDealBee" data-link="http://mywebsiteproject.test/user/DealBee">
    <span contenteditable="false">
        <span class="ql-mention-denotation-char">@</span>
        a href="http://mywebsiteproject.test/user/DealBee" target=_blankDealBee
    </span>
</span>

=> Basically there is a problem with the tag..

This is how my clipboard module looks like:

clipboard: {
    allowed: {
        tags: ['a', 'b', 'strong', 'u', 's', 'i', 'p', 'br', 'ul', 'ol', 'li', 'span'],
        attributes: ['href', 'rel', 'target', 'class', 'data-index', 'data-denotation-char', 'data-id', 'data-value', 'data-link', 'contenteditable', 'ql-mention-denotation-char']
    },
    keepSelection: true,
},

Does anybody know how to fix this problem/allow the mention tags and attributes?

Kind regards

Nov
21
1 month ago
Activity icon

Replied to Laravel Nova: Delete Images From Disk When Content Is Modified And Image Is Removed

@bobbybouwmann is it also possible to do this only for models/queries which come from nova? Because I don't need to modify those which are coming from the normal front end as they are already modified!

Activity icon

Started a new Conversation Laravel Nova: Delete Images From Disk When Content Is Modified And Image Is Removed

Hi,

I am working with spatie media library to store my images. On the frontend site I am using Quill editor with Vue js to give users the option to modify their posts. The users on the frontend also have the option to upload images. Those images get send in base64 within the content.

On the server side I am checking if the content contains any images which are base64 encoded. If so, I store them via spatie media library and replace the base64 image tag with and an img tag which has the image link as source set. This happens BEFORE storing the content to the database.

Same procedure for updating the content. I check if all images which are stored for the post model in the spatie media library are still within the content. If not, delete those images. When there are new images I do the same procedure as described above. If the post gets deleted, the image will also be deleted.

Here you can read the "tutorial" on how to do this.

However, I don't know how I can perform the same procedure when the admin is editing the content... Because I need to modify the query BEFORE the content gets stored as base64 images are way to long for my database.

Does anybody knows how to do this or had an similar problem? I was thinking about observers. But there I have the problem that it is already to late. At the time the observer code is getting executed the content already got stored. This won't work as my database only allows text with around 64.000 chars. I also don't want to change that!

Second problem with observers will be that I will end up in a infinity loop because I need to call ->save() on my model which will trigger the observer again...

Any ideas on this? Basically I need to catch the SQL query before it will get executed.

Kind regards and thank you!

Nov
20
1 month ago
Activity icon

Started a new Conversation Laravel Nova: Modify Value (muliply) Before Saving To Database

Hi,

I am using Laravel Nova to administrate my project. However, I save certain values in my database like percentages or prices as x*100. Why I am doing this? Because when saving numbers *100 I can store them as int instead of double or float.

However, this leads to the problem that I am seeing the number which is saved and multiplied by 100 in the database on my Laravel Nova Admin dashboard. I mean I can bypass that by using resolveUsing or displayUsing (read here). Then e.g. 1530 will be presented as 15,30 when diving by 100 which is correct.

The only problem with this is when typing 100 in the percentage field e.g. it also gets saved as 100 and not as 10000 (100*100). Does anybody knows how I can implement this?

I also tried to use eloquent observers. But this doesn't work because I end up in a infinity loop.

Kind regards and thank you!

Activity icon

Replied to Computed Column In Value / Trend Metrics

@bobbybouwmann I get Property total does not exist on the Eloquent builder instance. Do you know why that? I am using Laravel 8 and Nova 3.

I do exactly the same thing except my Model is called Product. I want to sum up the link_clicks_general and link_clicks_details.

public function calculate(NovaRequest $request)
    {
        $product = Product::selectRaw('SUM(link_clicks_general + link_clicks_details) as total');

        return (new \Laravel\Nova\Metrics\ValueResult($product->total))
            ->format(['thousandSeparated' => true])
            ->currency('$');
    }
Nov
19
1 month ago
Activity icon

Started a new Conversation Laravel Eloquent Belongs To Many Query Returns Entries Multiple Time

I have a products, users and products_marks table. Users can "mark" products. When they mark one product the database stores the user_id and the product_id in the products_marks table.

Marks basically mean a user wants to watch this product and has a watchlist. Of course I want to show the user all products he has marked. This means I have to get all products where the user_id in the products_marks table matches the actually user. However, I have some extra requirements to this as well.

Products do have a post_status_id. This represents weather the product is publish, offline, in review, pending, etc. The marked products should only be represented to the user if the product is also online. BUT if the user has marked a product which he has posted by himself, so he is the owner of the product, he should also see this product when it is publish AND pending.

This also works in most cases. I already have an eloquent query for this. But now I have found a strange problem. A user reported me that he sees one product two times in his watchlist. I have run the SQL query for exactly this user and yes, the database is returning the product two times! Why this? What do I have to change in order to get each product only once?

User model:

/** Relationship */
public function markedProducts(){
    return $this->belongsToMany('App\Models\Product', 'products_marks');
}

/** Eloquent Query */
public static function markedProductsPaginated(User $user){
    $products = Product::select('products.*')
        ->join('products_marks', 'products_marks.product_id', '=', 'products.id')
        ->whereHas('marks', function ($query) use ($user) {
            $query->where(function($query) use ($user){
                $query->where('products_marks.user_id', $user->id);
            });
            $query->where(function($query){
                $query->where('page_status_id', PageStatus::getIdByStatus('publish'));
            });
            $query->orWhere(function($query) use ($user){
                $query->where('page_status_id', PageStatus::getIdByStatus('pending'))
                    ->where('products.user_id', $user->id);
            });
        })
        ->orderBy('products_marks.created_at', 'desc')
        ->paginate(10);

    $products->loadCount('allPublishedComments');

    return $products;
}

Query as SQL statement:

select `products`.* from `products` inner join `products_marks` on `products_marks`.`product_id` = `products`.`id` where exists (select * from `users` inner join `products_marks` on `users`.`id` = `products_marks`.`user_id` where `products`.`id` = `products_marks`.`product_id` and ((`products_marks`.`user_id` = 19) and (`page_status_id` = 1) or (`page_status_id` = 4 and `products`.`user_id` = 3))) order by `products_marks`.`created_at` desc limit 10 offset 0

I have also created a db fiddle here where you can run this SQL statement and see that the database is returning the entry for the user_id 13 two times. But why is that? And why only sometimes?

It looks like when multiple users mark the same product I get it multiple times back. As you can see in the fiddle the product with the id 43 got marked two times!

Kind regards and thank you!

Activity icon

Awarded Best Reply on Laravel FormRequest Validation Gets User Model And Sometimes Directly The Name

If anybody else is facing this problem, I found the solution. Well, at least I found the problem I have:

I did forget to pass the User $user to my validate function... Check your function parameters!

Activity icon

Replied to Laravel FormRequest Validation Gets User Model And Sometimes Directly The Name

If anybody else is facing this problem, I found the solution. Well, at least I found the problem I have:

I did forget to pass the User $user to my validate function... Check your function parameters!

Nov
13
2 months ago
Activity icon

Replied to Laravel FormRequest Validation Gets User Model And Sometimes Directly The Name

Thanks for your answer!

However, I have exactly the same problem as written above just not with $this->user or $this->user->name but with $this->route('user') or $this->route('user')->name...

Why does it either return the user object or cannot access the property name?

Activity icon

Started a new Conversation Laravel FormRequest Validation Gets User Model And Sometimes Directly The Name

Hi,

I am using Laravel 8 and validate my requests with the form request validation. However, I have a strange problem. Before I am going to describe my problem I will paste my routes and my validation class here:

routes:

Route::post('users', ['as' => 'user.search', 'uses' => '[email protected]']);

Route::post('user/name', ['as' => 'user.name.exists', 'uses' => '[email protected]']);

Route::post('user/email', ['as' => 'user.email.exists', 'uses' => '[email protected]']);

Route::post('user/email/check', ['as' => 'user.email.check', 'uses' => '[email protected]']);

Route::get('user/{user:name}', ['as' => 'user.show', 'uses' => '[email protected]']);

Route::get('user/{user:name}/einstellungen', ['as' => 'user.settings', 'uses' => '[email protected]']);

Route::get('user/{user:name}/produkte', ['as' => 'user.products', 'uses' => '[email protected]']);

Route::post('user/{user:name}/produkte', ['as' => 'user.products.post', 'uses' => '[email protected]']);

Route::get('user/{user:name}/saved/produkte', ['as' => 'user.marked.products', 'uses' => '[email protected]']);

Route::post('user/{user:name}/saved/produkte', ['as' => 'user.marked.products.post', 'uses' => '[email protected]']);

Route::post('user/{user:name}/avatar/upload', ['as' => 'user.avatar.update', 'uses' => '[email protected]']);

Route::post('user/{user:name}/avatar/valid', ['as' => 'user.avatar.valid', 'uses' => '[email protected]']);

Route::post('user/{user:name}/avatar/löschen', ['as' => 'user.avatar.delete', 'uses' => '[email protected]']);

Route::post('user/{user:name}/update/password', ['as' => 'user.password.change', 'uses' => '[email protected]']);

Route::post('user/{user:name}/validate/password', ['as' => 'user.password.validate', 'uses' => '[email protected]']);

This is my FormRequest validation which checks if the user is authorized to perform this request and if the given data are valid. As you can see, I check if the Auth::user()->name is the same as the requested user ($this->user->name) to change the image. Because only the owner of his profile image should be allowed to change is profile image.

class UserAvatarUpdateRequest extends FormRequest
{
    public function authorize()
    {
        dump(array('auth' => Auth::user()->name, 'requested' => $this->user));     

        if(Auth::check() && Auth::user()->name == $this->user->name){
            return true;
        }

        return false;
    }
    
    public function rules()
    {
        return [
            'avatar' => [
                'required',
                'image',
                'max:5000',
                'mimes:jpeg,png,jpg',
                Rule::dimensions()->minWidth(200)->minHeight(200)->ratio(1)
            ],
        ];
    }

}

Now I will come to the problem. As you can see I have several routes for my user and there is one route called user.avatar.valid and another route called user.avatar.update.

Both routes, user.avatar.valid and user.avatar.update are using the FormRequest validation class I have pasted above. Basically user.avatar.valid is being called before the user submits the form to check if the uploaded image is valid. I know, I also could do this in one request but that's not possible because I am using vee-validate for Vuejs to validate if the form is valid.

However, thats not the probleme here. The problem is that when calling the user.avatar.valid route my dump echos for the key requested the name of the requested user. But, when performing a request for user.avatar.update I don't get the name of the user but rather the user object which contains the id, name, email and so on.

But exactly this is the point... when trying to call user.avatar.update I get a 403 error (forbidden) because $this->user is not equal to Auth::user()->name. Obviously it is not the same when I compare a string (name) to the user object.

However, when calling user.avatar.valid it passes because here I get the name when calling $this->user and not the user object.

But why is that?

When I change $this->user to $this->user->name I get the actual name for the user when calling the user.avatar.update route but on the other side I get a 500 error when calling the user.avatar.valid route because it says Trying to get property 'name' of non-object...

Does anybody has an idea where the problem here is and how to fix this?

Kind regards and thank you!

Nov
10
2 months ago
Activity icon

Replied to Laravle 8 Wrong Timezone (-1) When ->toArray() A Collection

My fault... it's just being casted to a utc format... All good!

Activity icon

Started a new Conversation Laravle 8 Wrong Timezone (-1) When ->toArray() A Collection

Hi,

I have set my timezone in config/app.php to Europe/Berlin. I know Laravel has changed the date format from Laravel 6 to Laravel 7 to the ISO 8601 format. But that's not the problem here..

My problem is that I get different times when using the toArray() function on a collection.

Here is an example:

$product = Product::where('id', '1')->get();
dd($product->end_date)

The dd() returns

Illuminate\Support\Carbon @1607547599 {#1949 ▼
  #constructedObjectId: "0000000076d58c550000000061b504d8"
  #localMonthsOverflow: null
  #localYearsOverflow: null
  #localStrictModeEnabled: null
  #localHumanDiffOptions: null
  #localToStringFormat: null
  #localSerializer: null
  #localMacros: null
  #localGenericMacros: null
  #localFormatFunction: null
  #localTranslator: null
  #dumpProperties: array:3 [▶]
  #dumpLocale: null
  date: 2020-12-09 21:59:59.0 Europe/Berlin (+01:00)
}

Even when using doing a toArray() on the Carbon class (dd($product->end_date->toArray())) I get the correct time:

array:12 [▼
  "year" => 2020
  "month" => 12
  "day" => 9
  "dayOfWeek" => 3
  "dayOfYear" => 344
  "hour" => 21
  "minute" => 59
  "second" => 59
  "micro" => 0
  "timestamp" => 1607547599
  "formatted" => "2020-12-09 21:59:59"
  "timezone" => Carbon\CarbonTimeZone {#1986 ▶}
]

However, and here comes the problem now, when performing a toArray() on the collection I don't get 2020-12-09 21:59:59 but rather 2020-12-09T20:59:59.000000Z which is 1 hour to less.

dd($product->toArray()['end_date']);

Results in 2020-12-09T20:59:59.000000Z.

But why? Where is the problem? Why is one hour missing? Did I missed something in the upgrade guide?

Kind regards

Activity icon

Replied to Laravel Eloquent: Only Retriev Entries Where Relationship Has Entries (join)

Thanks! You are a legend!

May any idea on my other thread about the comments and child comments?

Activity icon

Replied to Laravel Eloquent: Only Retriev Entries Where Relationship Has Entries (join)

But this leads to the problem that my $appends attributes are not correct anymore...

Activity icon

Replied to Laravel Eloquent: Only Retriev Entries Where Relationship Has Entries (join)

Yes, this is working. But I want to sort the complete relation either by products_marks.id or products_marks.created_at... how can I do this?

Activity icon

Replied to Laravel Eloquent: Only Retriev Entries Where Relationship Has Entries (join)

I think I have it know. Is this correct?

$products = Product::whereHas('marks', function ($query) use ($user) {
            $query->where('products_marks.user_id', $user->id)
                ->where('page_status_id', PageStatus::getIdByStatus('publish'))
                ->orWhere('page_status_id', PageStatus::getIdByStatus('pending'))
                ->where('products.user_id', $user->id);
        })
            ->orderBy('created_at', 'desc')
            ->paginate(10);
Activity icon

Replied to Laravel Eloquent: Only Retriev Entries Where Relationship Has Entries (join)

Yes, you are right!

This is my query at the moment:

$products = Product::whereHas('marks', function ($query) use ($user) {
            $query->where('products_marks.user_id', $user->id);
        })
            ->where('page_status_id', PageStatus::getIdByStatus('publish'))
            ->orWhere('page_status_id', PageStatus::getIdByStatus('pending'))
            ->orderBy('created_at', 'desc')
            ->paginate(10);

page_status_id represents whether a product is published (1) or pending (4). I want to get only published articles OR pending articles where the logged in user is also the author (products.user_id) of the product.

Activity icon

Replied to Laravel Eloquent: Only Retriev Entries Where Relationship Has Entries (join)

Yes, this is working. Thank you. However, I do get all products instead of only the marked once.. is my relation wrong?

This is what I get as raw SQL: select * from products where exists (select * from users inner join products_marks on users.id = products_marks.user_id where products.id = products_marks.product_id and products_marks.user_id = 2) and page_status_id = 1 or page_status_id = 4 order by created_at desc

Activity icon

Replied to Laravel Eloquent: Sort Table By Sum Count Of Two Tables

Yes, I know... but this is how it is implemented now and it would be a huge effort to change this. Maybe I will do this later... but I need a solution for the current problem.

Activity icon

Started a new Conversation Laravel Eloquent: Only Retriev Entries Where Relationship Has Entries (join)

Hi,

I have a products and a products_marks table. The products_marks table contains a user_id and a product_id and represents all products which are marked/saved by a user. So, this is more or less something like watch list.

My goal is now to perform a eloquent query which returns me only the products which are also present in the product_marks table for a certain user_id. For this example lets choose the user_id` 2.

This is my products.php model:

public function marks()
    {
        return $this->belongsToMany('App\Models\User', 'products_marks', 'product_id', 'user_id')->withTimestamps();
    }

This is how I archive what I want at the moment. I perform a eloquent query with a join. But how can I do this with a relationship?

$products = Product::join('products_marks', 'products_marks.product_id', '=', 'products.id')
            ->where('products_marks.user_id', 2)
            ->orderBy('created_at', 'desc')
            ->paginate(10);

Kind regards and thank you!

Activity icon

Started a new Conversation Laravel Eloquent: Sort Table By Sum Count Of Two Tables

I have a products, comments and child comments table.

Products.php mode

public function comments()
{
    return $this->morphMany('App\Models\Comment', 'commentable')->orderBy('id');
}

Comment.php model

public function children()
{
    return $this->hasMany('App\Models\ChildComment');
}

My goal is now to execute a eloquent query which returns me the products table but ordered by the comments_count + child_comments_count.

At the moment this is how I get my totalCommentsCount attribute. I know it's not perfect but I don't know how do to this better... Also I cannot order the eloquent query by this attribute because at this point the query has already been executed:

public function getCommentsAndChildrenCountAttribute(){
    $comments = $this->comments()->with('children')->withCount('children')->get();

    $count = 0;
    foreach($comments as $comment){
        $count += $comment->children_count + 1;
    }

    return $count;
}

Does anybody has an idea how to do this?

Nov
09
2 months ago
Activity icon

Replied to Laravel Explicit Route Mode Binding Not Working In Some Cases?

Nope, I don't even have changed the order... just using {product:slug}

Nov
08
2 months ago
Activity icon

Replied to Laravel Explicit Route Mode Binding Not Working In Some Cases?

But the solution {product:slug} is now working. Could you please explain why the "top to bottom" evaluation doesn't effect this?

Activity icon

Replied to Laravel Explicit Route Mode Binding Not Working In Some Cases?

Ah ok.. very bizarre.. I mean you write where the {product} (slug) is placed in the url but it doesn't have any effect because of the order... strange behavior

Activity icon

Replied to Laravel Explicit Route Mode Binding Not Working In Some Cases?

Thank you!!! It is now working...

But I still would like to know what the problem was...

Activity icon

Started a new Conversation Laravel Explicit Route Mode Binding Not Working In Some Cases?

Hi,

I am using Laravel 8 and explicit route mode binding in my project to call an product under the slug instead of the id. I have products, posts and etc, which are all using explicit route mode binding with the slug in the database instead of the id.

What really confuses me is that the explicit route mode binding is working everywhere but not with products. Here is my RouteServiceProvider:

// Change route for product from $id to $slug
Route::bind('product', function ($value) {
    return Product::where('slug', $value)->first() ?? abort(404);
});

// Change route for user from $id to $name
Route::bind('user', function ($value) {
    return User::where('name', $value)->first() ?? abort(404);
});

// Change route for product from $id to $slug
Route::bind('post', function ($value) {
    return Post::where('slug', $value)->first() ?? abort(404);
});

Here are some example routes for a user, a product and a post:

works:      Route::get('/product/{productType}/{product}', ['as' => 'product.show', 'uses' => '[email protected]']);     
404 error:  Route::post('product/{product}/like', ['as' => 'product.like', 'uses' => '[email protected]']);          
404 error:  Route::post('product/{product}/dislike', ['as' => 'product.dislike', 'uses' => '[email protected]']); 
404 error:  Route::post('product/{product}/mark', ['as' => 'product.mark', 'uses' => '[email protected]']);

works:      Route::get('user/{user}', ['as' => 'user.show', 'uses' => '[email protected]']);
works:      Route::post('user/{user}/update/password', ['as' => 'user.password.change', 'uses' => '[email protected]']);

works:      Route::get('/blog/{postCategory}/{post}', ['as' => 'post.show', 'uses' => '[email protected]']);

When I do a dd for the value in the RouteServiceProvider for user, product and post I can figure out what's the problem here. All values do dump the actual slug of the resource. Even the get request for a product is the actual slug. However, when performing an post request for a product, I always get the end of the url as value. Of course this leads to a 404.

For example the route product/{product}/mark with an post requests does dump mark as value and not the slug of the product... why is that? All other post requests work fine!

I also tried switch a route from a post method to a get method but same result here... also an 404 error and I get mark as value again...

Can anybody explain whats the problem here and why it is not working?

When I change product/{product}/mark to produkt/{product}/mark it is working. But why? and why is '/product/{productType}/{product}' working? That is really strange..

Kind regards and thank you!

Oct
26
2 months ago
Activity icon

Started a new Conversation Do I Have To Write Tests For My Laravel Nova Code?

Hi Guys,

I am using Laravel Nova to administrate my users, posts, comments, etc. So, basically I coded a CMS for myself using Laravel Nova as my admin dashboard.

All the code I have written is PHPUnit tested except the code under app/Nova which is the code for the Nova dashboard. Now I wonder if I should write PHPUnit tests as well for this code as Laravel Nova comes as a tested package.

I am using the functions Nova is providing and some other functions/fields other packages for Nova are providing.

What do you say? I kind of see the point "you should test if the actions really do what you want" but also I think Laravel is a simple CRUD package which comes as a tested package. Means, If I set the database fields correct, everything should work like a charm without testing it.

What do you think?

Kind regards and thank you!

Oct
10
3 months ago
Activity icon

Replied to Request Validator For ISOString Date With Milliseconds

Any updates here on how do validate this ISO string?

Oct
01
3 months ago
Activity icon

Started a new Conversation Vue.js Components Test Or Laravel Dusk?

Hi, I want to test my Vue.js components but I don't know if I should use Laravel Dusk or Vue.js to test my components. I know it's possible to test the state of Vue components with Laravel Dusk as well..

However, what are the pros and cons on testing Vue components with Laravel Dusk or with Vue.js itself? Testing it with both, Laravel Dusk and Vue.js, wouldn't make sense I guess..

How do you see it?

Kind regards

Sep
22
3 months ago
Activity icon

Started a new Conversation Can PHP Traits Add Values To Protected Values Of The Model

Hi,

I am using Laravel 7 and at the moment I am trying to centralize some code by using PHP traits. However, I want to have traits which e.g. also add values to the protected $attributes variable or the protected $with variable.

Why I want that? Because I want to have code reuse and not to tell every Laravel model where I use my trait to also load the relationship and add the attributes to my model. That would be quite redundant...

I already figured out a way to add values to the protected $attributes variable. However, how can I add comments to my protected $with variable?

This is the code to add values to the protected $attributes variable:

    /* Add attributes to model $appends */
    protected function getArrayableAppends()
    {
        $this->appends = array_unique(array_merge($this->appends, ['publishedComments']));

        return parent::getArrayableAppends();
    }

Kind regards

Sep
19
3 months ago
Activity icon

Replied to Admin Needs To Approve Actions - Possible?

Hi at @jtanmay sadly not.. If you find any idea on how to do this please tell me!

Sep
18
3 months ago
Activity icon

Started a new Conversation ID Field Is Not Being Displayed (after Larave Update From 6.x To 7.x And Nova 2.x To 3.x)

Hi,

I have updated Laravel from 6.x to 7.x and Nova from 2.x to 3.x yesterday. However, since I did that the ids are not being displayed at the tables on Nova anymore when using ID::make(). Not even ID::make('ID', 'id'), ID::make()->asBigInt() or ID::make('ID', 'id')->asBigInt() is working and I don't know why.

This affects all my Nova models and not the one I am posting here. This is just an example model because it's quite slim.

Any ideas why Nova cannot resolve the ids of my model? When using Text::make('ID', 'id') I see the id. But why not with ID::make()?

Here is my model:

namespace App;

use Gwd\SeoMeta\Traits\SeoSitemapTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
use Gwd\SeoMeta\Traits\SeoMetaTrait;

class Page extends Model
{
    use SeoMetaTrait, SeoSitemapTrait;

    protected static function boot()
    {
        parent::boot();
        static::creating(function ($page) {
            if (!$page->user_id){
                $page->user_id = Auth::id();
            }
        });
    }

    /**
     * @Protected_variables
     */

    protected $table = 'pages';

    protected $guarded = ['id'];

    protected $casts = [
        'publish_at' => 'datetime',
        'created_at' => 'datetime',
        'updated_at' => 'datetime'
    ];

    /**
     * @Public_variables
     */

    /**
     * @Relationships
     */

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

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

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

Here is my Nova model:

<?php

namespace App\Nova;

use Epartment\NovaDependencyContainer\HasDependencies;
use Epartment\NovaDependencyContainer\NovaDependencyContainer;
use Froala\NovaFroalaField\Froala;
use Gwd\SeoMeta\SeoMeta;
use Illuminate\Http\Request;
use Inspheric\Fields\Indicator;
use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\DateTime;
use Pdewit\ExternalUrl\ExternalUrl;
use App\PageStatus;

class Page extends Resource
{
    use HasDependencies;

    /**
     * The model the resource corresponds to.
     *
     * @var string
     */
    public static $model = \App\Page::class;

    /**
     * The single value that should be used to represent the resource when being displayed.
     *
     * @var string
     */
    public static $title = 'title';

    /**
     * The columns that should be searched.
     *
     * @var array
     */
    public static $search = [
        'title',
        'slug'
    ];

    /**
     * Get the fields displayed by the resource.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function fields(Request $request)
    {
        return [
            ID::make()->sortable(),

            Text::make('Title')
                ->rules('required', 'max:255'),

            ExternalUrl::make('Product Link', 'slug')
                ->onlyOnDetail(),

            Text::make('Slug', 'slug')
                ->hideFromIndex()
                ->creationRules('unique:pages,slug')
                ->rules('required', 'alpha_dash', 'max:80'),

            Froala::make('Content')
                ->hideFromIndex()
                ->rules('required'),

            Indicator::make('Status', function() {
                return $this->pageStatus->status;
            })
                ->labels([
                    'publish' => 'Publish',
                    'future' => 'Future',
                    'draft' => 'Draft',
                    'pending' => 'Pending',
                    'private' => 'Privat'
                ])
                ->colors([
                    'publish' => 'green',
                    'future' => 'purple',
                    'draft' => 'blue',
                    'pending' => 'orange',
                    'private' => 'red'
                ]),

            BelongsTo::make('Status', 'pageStatus', 'App\Nova\PageStatus')
                ->onlyOnForms(),

            NovaDependencyContainer::make([
                DateTime::make('When to Publish', 'publish_at')
                    ->format('DD.MM.YYYY @ HH:MM:SS')
                    ->rules('required', 'date_format:Y-m-d H:i:s')
            ])->dependsOn('pageStatus', PageStatus::getIdByStatus('future')),

            BelongsTo::make('Type', 'pageType', 'App\Nova\PageType')
                ->viewable(false)
                ->sortable(),

            BelongsTo::make('User', 'user'),

            SeoMeta::make('SEO', 'seo_meta'),
        ];
    }

    /**
     * Get the cards available for the request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function cards(Request $request)
    {
        return [];
    }

    /**
     * Get the filters available for the resource.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function filters(Request $request)
    {
        return [];
    }

    /**
     * Get the lenses available for the resource.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function lenses(Request $request)
    {
        return [];
    }

    /**
     * Get the actions available for the resource.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function actions(Request $request)
    {
        return [];
    }
}

Here is my migration:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePagesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('pages', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedBigInteger('user_id')->index();
            $table->char('title')->index();
            $table->char('slug')->index()->unique();
            $table->text('content');
            $table->unsignedBigInteger('page_type_id')->index();
            $table->unsignedBigInteger('post_category_id')->index()->nullable();
            $table->unsignedBigInteger('page_status_id')->index();
            $table->timestamp('publish_at')->nullable();
            $table->softDeletesTz();
            $table->timestamps();

            $table->foreign('user_id')
                ->references('id')
                ->on('users')
                ->onDelete('restrict');

            $table->foreign('page_type_id')
                ->references('id')
                ->on('page_types')
                ->onDelete('restrict');

            $table->foreign('post_category_id')
                ->references('id')
                ->on('post_categories')
                ->onDelete('restrict');

            $table->foreign('page_status_id')
                ->references('id')
                ->on('page_statuses')
                ->onDelete('restrict');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('pages');
    }
}

Kind regareds

Sep
03
4 months ago
Activity icon

Replied to Laravel Socialite Register User With Social Account And Force Them To Pick A Username

I do know that. However, I want the user to be able to set an own nickname because the nickname provided by Facebook or Google mostly like is the first and last name.

Activity icon

Started a new Conversation Laravel Socialite Register User With Social Account And Force Them To Pick A Username

I want to give users the opportunity to login/register via social login (like Facebook or Google). In order to do this I am using the package Socialite provided by Laravel.

I also give the users the opportunity to register by email and password. When doing so they have to choose a username as well. So far so good. Here is no problem because when the user gets created he has submitted a username, a email address and a password.

However, when doing this via social login the user has not chosen a username. I just get the name of the user from Google or Facebook but that's not what I want. I want the user to choose a username/nickname.

The problem is that the username is not nullable because I am using implicit binding on my username for the user model.

Right now I am bypassing this problem by putting the email, provider and provider_id I get from the social login in the user session. Whenever the user session contains those 3 parameters I show a form to the user where he has to choose a username. When submitting the form the user gets created by the username provided from the form and the email, provider and provider_id from the session.

Another possible solution is to make username nullable in the database and store the email, provider and provider_id right away when doing the social login and setting the username to null. This would solve the problem of having a session conflict but I would have a empty username in my database which would lead to many other problems as username is my key for the implicit route binding. I don't really favor this solution too but it is one possible solution.

My question to you is now what better way to do this is there? My favorite way would be to pass the email, provider and provider_id to the ProductController@index` as PHP variables because they cannot be manipulated! However, I haven't found any solution on how to do this except doing this via sessions.

Here is my sourcecode so far:

SocialLoginController

class SocialLoginController extends Controller
{

    public function redirect($provider)
    {
        return Socialite::driver($provider)->redirect();
    }

    public function callback($provider)
    {
        $getInfo = Socialite::driver($provider)->user();

        $user = $this->userExists($getInfo);

        if(!$user){
            $user = array();
            $user['email'] = $getInfo->email;
            $user['provider'] = $provider;
            $user['provider_id'] = $getInfo->id;
            $user['avatar'] = $getInfo->avatar_original;

            Session::put('user', $user);
            return redirect()->to(route('home'));
        }

        auth()->login($user);

        return redirect()->to(route('product.index'));

    }

    function createUser(SocialRegisterUserRequest $request)
    {
        //TODO: Avatar
        //TODO: Username

        $userSession = Session::get('user');

        $user = User::create([
            'name' => $request->name,
            'email' => $userSession['email'],
            'email_verified_at' => date('Y-m-d H:i:s'),
            'provider' => $userSession['provider'],
            'provider_id' => $userSession['provider_id']
        ]);

        Session::flash('user');

        auth()->login($user);

        return redirect()->to(route('product.index'));
    }
}

web.php (routes)

Route::get('/auth/redirect/{provider}', '[email protected]');

Route::get('/callback/{provider}', '[email protected]');

Route::post('/social/register', ['as' => 'social.register', 'uses' => '[email protected]']);

Some explanation for you: When doing a social login the user calls the route [email protected]. This passes to request to the redirect function. When the user has approved the social login for my app on Facebook or Google he will be redirected to the callback function. Here he checks if the user already exists. If so, he gets logged in if not the data are put into the session. Now the form for choosing a username will be shown to the user. When he submits this form he will be routed to the createUser function which then finally creates the user.

Any ideas on how to do this in a better way? I am grateful for any kind of help!

Kind regards

Aug
30
4 months ago
Activity icon

Started a new Conversation Use Laravel Socialite Register User And Redirect To Form To Fill Out More Data?

Hi guys,

I have implemented Laravel Socialite with Google today as described in this article. So far so good, everything is working.

However, I want to do a few changes and customize the process of registering users who login the first time via social networks. My Laravel project is working with nicknames like in forums. Of course these nicknames have to be unique.

My goal is now to redirect users who login via social networks for the first time to a form where they can enter a nickname and when this form gets submitted the user gets created. I am a little bit screwed on how I am going to implement this and need your advice.

The problem is, I have to fetch the data from e.g. Google, redirect the user to a form where he enters his nickname and submits the form. But this form has to include all data, also the data which I got from Google in order to create a user with nickname, email, avatar, provider (e.g. google, facebook, etc.) and provider id.

I haven't pasted any code here now because my code looks exactly the same as described in the article above I linked!

Kind regards!

Aug
27
4 months ago
Activity icon

Started a new Conversation Laravel Route Model Binding With Sorted Eager Loading?

I have products which have also comments. This comments can be voted and comments can also have child comments. The comments get loaded via eager loading $with which is defined in the product model and the child comments get as well loaded via eager loading which is also defined in the comments model. The child comments can also be voted (but don't have any child comments).

Product.php (Model)

namespace App;

class Product extends Model
{
    /**
     * @Protected_variables
     */

    protected $with = [
        'comments',
        'user'
    ];

    /**
     * @Relationships
     */

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

    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }
}

Comment.php (Model)

namespace App;

class Comment extends Model
{
    /**
     * @Protected_variables
     */
     
    protected $with = [
        'children',
        'user'
    ];

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

    public function children()
    {
        return $this->hasMany('App\ChildComment');
    }
        
    public function likes()
    {
        return $this->belongsToMany('App\User', 'comments_likes', 'comment_id', 'user_id')->withTimestamps();
    }
}

I use route model binding to receive my product in the ProductController. Here is an example of the route Route::get('/product/{product}', ['as' => 'product.show', 'uses' => '[email protected]']); and the function show:

[email protected]:

public function show(Product $product, Request $request)
{
    if(request()->wantsJson()){
        return response()->json([
            'product' => $product
        ]);
    }

    return view('pages.productDetails')->with([
            'product' => $product
        ]);
}

In the show function I can now access the comments of the product, as well as the child comments of the comments and all the other relations which get loaded via the $with attribute in the models.

Now comes questions. As I already have loaded the relationship, how can I either 1. sort them now or 2. pass the sort arguments to the model to get a sorted relationship back?

When I write dd($product->comments->sortByDesc('created_at')->toArray()); I get my product with the comments which are sorted by created_at. That's what I want. But I cannot assign the sorted collection to the product collection like this $product->comments = $product->comments->sortByDesc('created_at'); because $product->comments is @property-read.

I also don't want to do another query and pass this $product->comments()>orderBy('created_at', 'desc')->get(); to my response. Because then the eager loading in the model redundant.

Is there a way to 1. either sort the relationship collection or 2. pass the sort arguments to the model to get a sorted relationship back?

I actually want to stick to my route binding model. I know I could pass the sorting arguments and product id as arguments and then execute it via get. But is there a solution to do that within the model eager loading?

Also, please note I want to sort my comments also by likes and the count of child comments they have. I don't want to sort them only by date, so I need to pass the sort argument to the model when choosing a solution for number 2.

Kind regards!

Aug
26
4 months ago
Activity icon

Started a new Conversation Laravel Eager Loading Sort By Count Of Relationship Entries/values

I have products which have also comments. This comments can be voted and comments can also have child comments.

Now I want to sort these comments by date, amount of likes and amount of child comments.

Before I show you my tries I will show you my code:

Product.php (Model)

namespace App;

class Product extends Model
{
    /**
     * @Protected_variables
     */

    protected $with = ['comments', 'user'];

    /**
     * @Relationships
     */

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

    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }
}

As you can see, I already tell Laravel with the variable $with to load comments and user always when loading a product.

ProductController.php

public function show(Product $product, Request $request)
{
    if($request->has('sorting') && in_array($request->sorting, ['Beliebtesten', 'Diskutiertesten', 'Neusten'])){
        if($request->sorting == 'Neusten'){
            $product->load(['comments' => function ($query) {
                $query->orderBy('created_at', 'desc');
            }]);
        }else if($request->sorting == 'Diskutiertesten'){
            $product->load(['comments.children' => function ($query) {
                $query->orderBy('published_date', 'asc');
            }]);
        }else{
            $product->load('comments')->get()->sortByDesc(function($product)
            {
                return $product->likes->count();
            });
        }

        return response()->json([
            'product' => $product
        ]);
    }else{
        $product->load('comments');

        return response()->json([
            'product' => $product
        ]);
    }
}

So, I have two questions now:

  1. Do I even need $product->load('comments')? - Because I have figured out when I just pass the $product without executing $product->load('comments') I also have the comments loaded... Looks like I don't need it. Is that right?

  2. How can I sort the comments by amount of likes (rows, because you can only upvote) and by amount of child comments (rows)?

This is what I have tried so far (all not working for me):

$product->load('comments')
    ->withCount('likes')
    ->orderBy('likes_count','DESC')
    ->get();
$product->loadCount('comments');

$product->orderBy('comments_count', 'desc');
Aug
14
5 months ago
Activity icon

Started a new Conversation Vue Js Infinit Scroll Disable After Page 3 And Replace With “load More” Button?

I want to implement an infinity scroll for my Vue js app. However, this infinity scroll should only load x times when hitting the bottom of the page. In my case I want the infinity scroll to load more content only for the first 3 times the user hits the bottom and then the infinity scroll should display a "load more" button and only load more content if the user clicks on this "load more" button.

I haven't implemented anything yet but I want to know what would be your Vue js infinity scroll package to go and why? How would you solve this?

There are two good infinity scroll packages for Vue js. The more famouse vue-infinite-loading and the vue-infinite-scroll package.

I have already checked the documentation of both packages but sadly I haven't found a build in function for this case. How would you implement this? Maybe another package?

Kind regards and thank you!