timgavin

Member Since 4 Years Ago

West Palm

Web Developer at Freelance

Experience Points 20,620
Experience Level 5

4,380 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 217
Lessons
Completed
Best Reply Awards 2
Best Reply
Awards
  • Start Your Engines Achievement

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • First Thousand Achievement

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • One Year Member Achievement

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • Two Year Member Achievement

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • Three Year Member Achievement

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • Four Year Member Achievement

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • Five Year Member Achievement

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • School In Session Achievement

    School In Session

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

  • Welcome To The Community Achievement

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • Full Time Learner Achievement

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • Pay It Forward Achievement

    Pay It Forward

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

  • Subscriber Achievement

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • Lifer Achievement

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • Laracasts Evangelist Achievement

    Laracasts Evangelist

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

  • Chatty Cathy Achievement

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • Laracasts Veteran Achievement

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • Ten Thousand Strong Achievement

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • Laracasts Master Achievement

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • Laracasts Tutor Achievement

    Laracasts Tutor

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

  • Laracasts Sensei Achievement

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • Top 50 Achievement

    Top 50

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

24 Mar
1 day ago

timgavin left a reply on Trying To Get Property Of Non-object In Blade @if()

Figured it out. Stupid error: a user was deleted in the database and that was causing recipient to be null in one of the results. ?‍♂️

timgavin started a new conversation Trying To Get Property Of Non-object In Blade @if()

I just upgraded my Laravel app to 5.7 and began testing. I encountered the Trying to get property of non-object error on a page that has been working just fine since the app was built, which was Laravel 5.2.

The line on which the error appears:

@if($thread->recipient->username != auth()->user()->username)

Now here's the weird thing, if I do the following, it actually prints the username!

{{ dd($thread->recipient->username) }}
@if($thread->recipient->username != auth()->user()->username)

I have no idea why this is happening or how to go about fixing it, as it works outside of the @if statement. Is it a bug in Blade?

17 Mar
1 week ago

timgavin left a reply on Redirect To Same Page With Cookie

@CRONIX - Thank you!

I started using this and it's so bulky!

$response = new \Illuminate\Http\Response(view('cart.index'));
$response->withCookie(cookie()->forever('cart', $cookie));
return $response;

timgavin started a new conversation Redirect To Same Page With Cookie

  1. I have a shopping cart page located at /cart, which shows the user their cart contents.
  2. The cart contents are stored in a cookie.
  3. The Route is set up as Resource::get('/cart', '[email protected]');
  4. A user can add items to their cart if they are not logged in, but in order to make a purchase they have to login.

Now, in [email protected] I check if the user is logged in, and if so check their purchase history to see if they've ordered this item before. If they have, I remove the item from the cart cookie.

My problem is that when returning from the index method, I have to use return view('cart.index') because if I use return redirect('/cart') I'm stuck in an infinite loop.

However, if I dont' use redirect the cookie doesn't update.

How can I update the cookie and send them to the /cart page?

16 Mar
1 week ago

timgavin left a reply on Get The 15th Of The Month With Carbon

@CORYS8646 - That's funny, because before I posted this question I was trying startOfMonth() and it didn't work. firstOfMonth() did. :)

15 Mar
1 week ago

timgavin started a new conversation Get The 15th Of The Month With Carbon

I'm configuring pay periods, which are on the 15 of the month and the last day of the month.

I want to grab sales that happened between those days, so I need to find sales that happened between the 1st and the 15th, and the 16th and the end of the month.

The first part is easy. The second, not so hard, but a little on the messy side.

$month = Carbon::now()->format('m');
$year = Carbon::now()->format('y');
$day = $year.'-'.$month.'-15';

$startDate = Carbon::parse($day)->format('Y-m-d');
$endDate = Carbon::now()->endOfMonth()->format('Y-m-d');

Is there a cleaner way of doing this?

19 Feb
1 month ago

timgavin left a reply on Replace String With Function

@CRONIX - Sweet, thanks!

timgavin left a reply on Replace String With Function

I think I just figured it out. If I change [image1], [image2] and [image3] to just [image] I can do this...

@foreach(explode('[image]', $article->body) as $part)
    <p>{{ $part }}</p>
    @if($loop->iteration == 1)
        {{ $article->getFirstMedia('image1') }}
    @endif
    @if($loop->iteration == 2)
        {{ $article->getFirstMedia('image2') }}
    @endif
    @if($loop->iteration == 3)
        {{ $article->getFirstMedia('image3') }}
    @endif
@endforeach

So far it's working well.

timgavin started a new conversation Replace String With Function

I'm using Laravel Media Library and would like to be able to add responsive images inside of my news articles, so I thought about using short codes as placeholders for each image, something like

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

[image1]

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

This would require searching through the text body, finding the string [image1] and replacing it with $article->getFirstMedia('images')

Or to put it another way:

str_replace('[image1]', $article->getFirstMedia('images'), $article->body)

I'm just not having luck figuring this out. Any suggestions?

10 Feb
1 month ago

timgavin started a new conversation Looking For Opinions/advice On Scaffolding An Admin CP

I'm trying to keep my controllers from getting out of hand, both in the number of controllers I create, and in the number of methods within each controller; I'm trying to keep the methods to the basic 7 per controller.

I'm working on a new app, which means I need to be able to administer pages, a blog, a photo gallery, etc.

So I create a BlogController and create the resource methods. Now comes my question: what do you do if you want an Admin to be able to update the blog too, from within an admin control panel?

Do you create a separate Controller, such as AdminController and put those methods in there? This is what I normally do, but it gets loaded with methods. I mean LOTS of methods, and I don't like this approach because now I'm doing blog methods from outside the BlogController. Wouldn't it be better to keep it all on the BlogController?

How do you handle this situation?

timgavin left a reply on Relationship On Same Table Not Working

Turns out I had a column on the users table named referrer that was causing an issue. I changed the relationship's method name from referrer() to referredBy() and it worked. *eyeroll*

timgavin started a new conversation Relationship On Same Table Not Working

I have a relationship that's acting weird. If I get the results and dd(), it has the correct data. However, if I run the collection through a foreach loop it's like the relationship disappears.

The users table has a field called referred_by, which stores the user ID of the person who referred the user. In my instance I'm looking for all the new users who were referred by the user with the ID of 3.

Here's the relationship in User.php

public function referrer()
{
    return $this->belongsTo(User::class, 'referred_by');
}

Here's the code which is returning funky results

$users = User::where('referred_by', 3)
    ->with('referrer')
    ->get();

// doing dd() here returns a collection with full referrer relationship;
// the returned data is as expected

dd($users);

foreach($users as $user)
{
    // dd($user) here returns the relationship, as it should

    // dd($user->referrer) here returns null, like the relationship doesn't exist
}
09 Feb
1 month ago

timgavin left a reply on First() And Update() Row In One Query

@BOBBYBOUWMANN - increment() was perfect. Thanks! :)

timgavin left a reply on First() And Update() Row In One Query

@BOBBYBOUWMANN - That was one of the first things I tried, but got an Undefined variable: account error

timgavin started a new conversation First() And Update() Row In One Query

How can I do this in one line?

$account = Account::where('user_id', $user->id)->first();
$account->update(['balance' => $account->balance + 25]);
08 Feb
1 month ago

timgavin left a reply on Overriding Auth\LoginController

@SNAPEY - Ok, thanks. Turns out the problem was that I was using Spatie's Larvel Permission middleware on the route, and when I removed that and added auth middleware to the constructer on my controller the intended behavior started working as expected.

timgavin started a new conversation Overriding Auth\LoginController

I've overridden Laravel's default authentication by adding some of my own methods. However, I'm not sure the way I went about it is right.

Basically I added methods - such as the ones below - inside of App\Http\Controllers\Auth\LoginController

// allow login using either email or username
protected function credentials(Request $request)
{
    $usernameInput = trim($request->{$this->username()});
    $usernameColumn = filter_var($usernameInput, FILTER_VALIDATE_EMAIL) ? 'email' : $this->username();

    return [$usernameColumn => $usernameInput, 'password' => $request->password];
}

public function logout(Request $request)
{
    if (\Cookie::get('impersonate') === 'true') {
        \Cookie::queue(\Cookie::forget('impersonate'));
    }

    \Auth::logout();

    return redirect('/');
}

Was this the correct way of doing it? I'm not so sure because the Laravel docs say I should create a LoginController at App\Http\Controllers\LoginController

I'm now trying to implement an intended login, to redirect the user back to a page after login, and every scenario I try is not working, the user is just directed to $redirectTo = '/home'.

Do I need to move my override methods into App\Http\Controllers\LoginController and return App\Http\Controllers\Auth\LoginController back to its default state?

What's the correct way of doing this?

31 Jan
1 month ago

timgavin left a reply on Combining Multiple Less Files

@CRONIX - Thank you!!!!

timgavin started a new conversation Combining Multiple Less Files

What's the proper way to combine multiple Less files into one? The following doesn't work...

mix.less([
   'resources/assets/less/theme/core.less',
   'resources/assets/less/theme/components.less',
   'resources/assets/less/theme/pages.less',
   'resources/assets/less/theme/menu.less',
   'resources/assets/less/theme/responsive.less',
   'resources/assets/less/app.less'
],'public/css/app.css');
30 Jan
1 month ago

timgavin left a reply on Running Console Command From Subfolder

@TYKUS - You're right. I just commented them out and they still work. Thanks again!

timgavin left a reply on Running Console Command From Subfolder

@TYKUS - smacks forehead

Good catch. I totally forgot about that. ?

@billriess was right. Thank you.

timgavin left a reply on Running Console Command From Subfolder

@billriess

Doesn't work; same error message.

protected $commands = [
        \App\Console\Commands\MyCommands\CommandOne::class,
    ];

timgavin started a new conversation Running Console Command From Subfolder

I created a command in a subfolder...

php artisan make:command MyCommands/CommandOne

And I edited it...

<?php

namespace App\Console\Commands\MyCommands;

use Illuminate\Console\Command;

class CommandOne extends Command
{
    protected $signature = 'my:command';

    protected $description = 'Testing it out';

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
        $this->info('It works!');
    }
}

I then ran it...

my:command

and got an error:

bash: my:command: command not found

How do I run a command in a sub-folder?

26 Jan
1 month ago

timgavin left a reply on Adding A Raw Order By To Pivot Table

@REALRANDYALLEN - Yep, a join did it. Thanks :)

25 Jan
2 months ago

timgavin started a new conversation Adding A Raw Order By To Pivot Table

I'm curating my posts table on the home page to only show posts I've handpicked.

When I select a post for the home page, its ID goes into a posts_homepage table, which is basically a pivot table. I select the post's id (post_id) from posts_homepage and then get the posts from the posts table.

This is working just fine, however, now I want to put them in a particular order, so I've added an order_by field to posts_homepage. I'm having a difficult time figuring out how to get the result in the order I want, nothing's working; I'm just getting them in the default order.

TABLE posts_homepage
post_id    INT 10 UNSIGNED
order_by INT 10 UNSIGNED
$posts = Post::latest('published_at')
    ->whereHas('user', function ($query) {
        $query->where('verified', 1);
    })
    ->whereRaw("posts.id IN (SELECT post_id FROM posts_homepage)")
    ->whereRaw("posts.status = 'published'")
    ->paginate(30);

I've tried removing latest('published_at') and inserting ->orderByRaw('ORDER BY posts_homepage.order_by ASC'), but that didn't make a difference or I'd receive an error message Unknown column 'posts_homepage.order_by' in 'order clause'

I also tried ->whereRaw("posts.id IN (SELECT post_id FROM posts_homepage ORDER BY order_by ASC)") but that didn't work either. I've tried a few other options as well, but can't get them returned based on the order_by field

Any suggestions?

17 Dec
3 months ago

timgavin left a reply on Add A End Date Automatically

@realrandyallen Thanks, this is exactly what I was looking for!

timgavin started a new conversation Add A End Date Automatically

I have a field that is a dateTime called start_at. I'd like to be able to automatically insert a dateTime value into an end_at field that is exactly one hour later than the start_at field.

DateTime::make('Start At')->rules('required'),

Is this possible? If so, how?

16 Dec
3 months ago

timgavin left a reply on Timezone Conversion

@kyYou're probably right; I was most likely thinking about this in the wrong way.

I have a calendar that is to be used by people globally. On this calendar a user can reserve a 1 hour block of time, and that hour can only have two users reserve it.

Currently, when selecting a start time, say 4:00 PM EST, the HTML value for the start time is 2018-12-16 16:00:00. Well, this gets entered as such in mySQL and then when I come back and view the page it's showing the block of time reserved is 1:00 PM because of the timezone offset.

So I guess I'm having a hard time figuring out what I need to do. My guess right now is to show 4:00 PM to the user, but have the HTML value be the offset time of 1:00 PM. Not sure how to do that though, but that's my current guess...

timgavin started a new conversation Timezone Conversion

When inserting a date into a table, how do I offset for the user's timezone using Carbon?

I'm trying different variations of the following, but can't get them to work. I either receive errors, or it just goes into the db as 2018-12-16 16:00:00 with no offset.

'start_at' => Carbon::parse('2018-12-16 16:00:00', auth()->user()->timezone),
14 Dec
3 months ago

timgavin left a reply on Pagination Is Over Http Instead Of Https

@realrandyallen As I mentioned in my post, I've already done that with URL::forceScheme('https'); :)

timgavin started a new conversation Pagination Is Over Http Instead Of Https

When paginating using {{ $posts->links() }}, Laravel is displaying the links as http:// instead of https://, even though I've specified https in the APP_URL inside .env, have set up URL::forceScheme('https'); in AppServiceProvider.php and am using SSL certs, not only from CloudFlare (using FULL), but have also installed a cert on the load balancer and am using LetsEncrypt on each server via Forge.

What could the issue be?

09 Nov
4 months ago

timgavin left a reply on Method Not Allowed For A Route That Doesn't Even Exist

Never mind, I understand why I'm receiving the method not allowed error. Brain fart on my part. it's been a while since I worked with Laravel. :)

Still doesn't explain why google is indexing it. weird.

timgavin left a reply on Method Not Allowed For A Route That Doesn't Even Exist

Why wouldn't I see a 404 when going to a non-existent URL?

I've searched my entire project, it's no anywhere else.

I've now started looking into other URLs that should be POST or DELETE only and accessing them via GET and I'm receiving that exception instead of a 404.

timgavin left a reply on Method Not Allowed For A Route That Doesn't Even Exist

I'm going to that route directly in my browser and receiving the MethodNotAllowedHttpException exception.

timgavin started a new conversation Method Not Allowed For A Route That Doesn't Even Exist

I have a POST route that is only accessible if a user is logged in:

Route::post(/'do/update', '[email protected]');

However, Google Search Console is showing a crawl anomaly for /do/update using GET. So I tested this, and when accessing that url via GET, I receive an MethodNotAllowedHttpException exception.

How is this even possible? There isn't a route set up via GET for /do/update - AND everything under /do is protected via middleware.

timgavin started a new conversation Security In Routes

I'm curious what's the best practice for stacking rules in routes/web.php?

Do I put the route first, then the security rules?

Route::group(['prefix' => 'account'], function () {
    Route::group(['middleware' => ['role:user]], function () {

Or the security role, then the route?

Route::group(['middleware' => ['role:user]], function () {
    Route::group(['prefix' => 'account'], function () {

Or does it not even matter?

16 May
10 months ago

timgavin left a reply on 1 Laravel Installation With 2 TLDs

Thanks to @campo and @cronix I got it all figured out; hope this helps someone else.

As @campo suggested, I added my subdomain to Cloudflare but just turned off protection.

In my .env file I had to put quotes around the value. Omitting quotes not only made it so I couldn't login to the site, but it also broke Envoyer's .env decryption!

SESSION_DOMAIN=".mysite.com"

In my Routes file I added another route to redirect all GET traffic back to the original site, and added the POST route to handle the uploads.

Route::group(['domain' => 'upload.mysite.com'], function () {
    Route::get('/', function () {
        return redirect(url('https://mysite.com'));
    });
    Route::group(['middleware' => ['role:user|admin,post']], function () {
        Route::post('files', '[email protected]')->middleware('throttle:4,1');
    });
});

And in my form I just added the URL

<form action="https://upload.mysite.com">
15 May
10 months ago

timgavin left a reply on 1 Laravel Installation With 2 TLDs

Unfortunately, when updating the .env and adding SESSION_DOMAIN=.mysite.com, then clearing my browser cache and cookies, I'm no longer able to login.

timgavin left a reply on 1 Laravel Installation With 2 TLDs

@campo I believe what's happening is that when the app goes to the upload subdomain, the currently logged in user's session is not being transferred to the route. Don't really know how to fix this though.

timgavin left a reply on 1 Laravel Installation With 2 TLDs

if I add Route::get('/', '[email protected]'); back in, and go to that route, I'm redirected to the login page.

timgavin left a reply on 1 Laravel Installation With 2 TLDs

The form is not located on the GET route. I decided against that as it didn't seem necessary since I'm only concerned with the uploaded file.

Should it be on the GET route?

BTW, I removed Route::get('/', '[email protected]'); from the route group as well, so there shouldn't be any conflicts.

timgavin left a reply on 1 Laravel Installation With 2 TLDs

I'm receiving a "this page timed out due to inactivity" error from Laravel. So I'm guessing it might be a CSRF issue? I do have the token on the form, and everything works perfectly up until I change the URL to upload.mysite.com.

After the file is uploaded, it's supposed to redirect to /home, instead it goes back to the form URL and shows the error message.

Oh, and I do have a Let's Encrypt cert on the subdomain, so https isn't an issue.

timgavin left a reply on 1 Laravel Installation With 2 TLDs

Well that makes sense!

I've tried it now, and it's still not working properly.

Here are my current routes for uploading

Route::group(['prefix' => 'files'], function () {
    Route::get('/', '[email protected]');
    Route::post('/', '[email protected]')->middleware('throttle:4,1');
});

and here's what I've changed it to

Route::domain('upload.mysite.com')->group(function () {
    Route::group(['prefix' => 'files'], function () {
        Route::get('/', '[email protected]');
        Route::post('/', '[email protected]')->middleware('throttle:4,1');
    });
});

Do I need to put ALL of my other routes in a separate Route::domain function as well? If so, what would I call it?

timgavin left a reply on 1 Laravel Installation With 2 TLDs

@campo I already tried that, it wouldn't resolve unless it went through Cloudflare.

I had set up the subdomain, and it was working fine, so long as I had it listed in the Cloudflare CP. Once I deleted the record from Cloudflare I could no longer access it in my browser.

Perhaps I did something wrong?

timgavin started a new conversation 1 Laravel Installation With 2 TLDs

I'm allowing my customers to upload large files. Because I'm using Cloudflare, anything over 100 MB gets rejected, which is no good.

So what I'm thinking of doing is switching the upload form action from mysite.com/upload to mysite.net/upload. This way I'm using a domain name that isn't going through Cloudflare, so file sizes won't be restricted.

I've set up mysite.net as a site in Forge to mirror mysite.com by setting the root location in nginx to point to the current folder of mysite.com. So now when someone goes to mysite.net they see the contents of mysite.com.

Unfortunately, mysite.net is now open to DDOS attacks because it isn't running through Cloudflare.

So what I'd like to do is make it so that mysite.net/upload is the only route that's open under that domain, and that it's only accessible from my load balanced servers.

Is this possible, and if so: how do I do it?

I've been researching this and haven't really come across an answer that applies to me, the most common scenario is using subdomains, which is not applicable in my situation.

10 May
10 months ago

timgavin left a reply on 413 Request Entity Too Large (Cloudflare)

@Cronix Brilliant! Ok, so one thing I didn't mention is that I'm using a load balancer on Forge/DigitalOcean. I can set up the subdomain to point to the load balancer, but I'm curious on setting up the sub domain on the two app servers to point to the app's current directory.

Would I create a new site in Forge and add the subdomain as the URL, then edit the nginx conf file and point the root to the main site?

timgavin started a new conversation 413 Request Entity Too Large (Cloudflare)

I'm allowing large file uploads in my Laravel app, and am using Cloudflare. One of my customers told me today that they were unable to upload a 150 MB file and received a 413 Request Entity too Large error. I looked into this and it's actually coming from Cloudflare; they won't allow uploads greater than 100 MB unless you pay through the nose.

Cloudflare suggests that I create a subdomain that isn't tracked by them and upload through that.

My question: how would I do this in Laravel?

I'm using Spatie's Media Library and uploading to the site on which Laravel is installed; how do I use a subdomain within the app?

30 Mar
11 months ago

timgavin started a new conversation Block A State From Accessing A Route

I looked into Laravel Firewall, which will allow you to block access to routes by IP or country, but I'm wondering if there's a way to block by state?

For instance, say I want to block access to everyone in Florida from visiting my /I-hate-florida/ route.

Is this possible?

03 Mar
1 year ago

timgavin started a new conversation Search Multiple Fields In Same Table

I have a table which holds a user's statistics, such as age, height, weight, etc.


| user_stats  |
| ------------- |
| birthday  | date  | 2000-01-01 |
| height  | varchar  | 6.0 |
| weight | varchar | 200 |

Using Scout and Algolia, I want a user to be able to search for all of these attributes, and return only users that match.

In my form, I'm using <select> menus to display the search options, such as...

<select name="age">
    <option" value="20-30">20-30</option>
    <option value="31-40">31-40</option>
</select>

So, if a user wanted to find people who were 17 years old, 6' tall and 200 lbs., how would I go about doing this in my controller?

28 Feb
1 year ago

timgavin left a reply on Download Large File From S3 *kind Of* Working

@ohffs , you pointed me in the right direction.

I feel like an idiot. I had a .download class on the link, which triggered javascript that had implemented e.preventDefault(). Removing the class fixed it.

Thanks. :)