CedricBongaerts's avatar

MethodNotAllowedHttpException in RouteCollection.php line 207:

NOTE: The Best Answer is not the only thing that should be read, it's the collection of all the answers that lead to the good result!

I've been having some trouble with the code that was given to create a random unique invite code. Follow the full history of this here: https://laracasts.com/discuss/channels/tips/group-table-creating-a-unique-invite-code

Some Errors have been resolved but I'm still stuck with one last error (I hope..) :

' MethodNotAllowedHttpException in RouteCollection.php line 207: '

To give you a clear view of what I currently have I'll post my code below:

Routes.php:

$router->post('invite', ['as' => 'invite.create', 'uses' => 'GroupController@createInvite']);

Invite.php model:

<?php namespace App;

use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

class Invite extends Model {

    protected $fillable = ['group_id', 'code', 'expires_at'];
    
    protected $dates = ['expires_at'];

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

    public static function generate()
    {
        $exists = true;
        while ($exists) {
            $code = str_random(15);
            $check = self::where('code', $code)->first();
            if( ! $check){
                $exists = false;
            }
        }
        return $code;
    }
}

GroupController.php:

<?php namespace App\Http\Controllers;

use App\Group;
use App\Invite;
use App\Http\Requests;
use App\Http\Controllers\Controller;

use Illuminate\Http\Request;

use Carbon\Carbon;

class GroupController extends Controller {

    public function __construct()
    {
        $this->middleware('auth');
    }
...
public function createInvite()
    {
        $group = Group::find(1); // Group ID you want to manage
        $code = Invite::generate();
        $invite = $group->invites()->create([
            'code' => $code,
            'expires_at' => Carbon::now()->addDays(7) // invite expires in 7 days
        ]);

        //Then to check invite      
        return redirect()->back();
    }
...
}

Anyone know why it's giving this error?

Thanks

0 likes
16 replies
zachleigh's avatar

That error probably means that you are making a get or post request to a route that is not defined as being get or post. How are you calling that route in your view?

1 like
CedricBongaerts's avatar

@zachleigh With your comment I made a button to generate the invite code and I fixed the 'MethodNotAllowedHttpException'. This is how I did it:

{!! Form::open(['route' => 'invite.create']) !!}
    <div class="form-group">
            <div class="col-md-6 col-md-offset-4">
                {!! Form::submit('Generate Code', ['class' =>  'btn btn-primary']) !!}
            </div>
        </div>
{!! Form::close() !!}

I also changed the route.php to:

$router->post('invites', ['as' => 'invite.create', 'uses' => 'GroupController@createInvite']);

This way my POST methode is triggering the correct link:

<form method="POST" action="http://project.dev:8000/invites" accept-charset="UTF-8"><input name="_token" type="hidden" value="AvXCPzVvCUaWwGwoVOsQe3NZCNMlQs9y1oPXUJZd">
    <div class="form-group">
            <div class="col-md-6 col-md-offset-4">
                <input class="btn btn-primary" type="submit" value="Generate Code">
            </div>
        </div>
</form>

But now when I press the Generate Code button, it gives a new error:

BadMethodCallException in Builder.php line 1999: Call to undefined method Illuminate\Database\Query\Builder::invites()

1 like
Kryptonit3's avatar

is your method on group named right? invites() or invite() ?

1 like
zachleigh's avatar

In your form, "action " should specify a controller method, not a route.

1 like
CedricBongaerts's avatar

@Kryptonit3 No it's currently createInvite()

@zachleigh I changed the code to this and it seems to work.

{!! Form::open(['controller' => 'createInvite']) !!}
    <div class="form-group">
            <div class="col-md-6 col-md-offset-4">
                {!! Form::submit('Generate Code', ['class' =>  'btn btn-primary']) !!}
            </div>
        </div>
    {!! Form::close() !!}

Now I'm getting this error: QueryException in Connection.php line 624: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'name' cannot be null (SQL: insert into groups (name, updated_at, created_at) values (, 2015-06-14 15:09:44, 2015-06-14 15:09:44))

Though my groups table has one item in it: id = "1" , name="Group Test" , updated_at="2015-06-14 15:09:44", created_at="2015-06-14 15:09:44"

Here is a picture of my Navicat connected to my Database: http://i.gyazo.com/7eabb8daa4ba0a408b74a2188076836c.png

Kryptonit3's avatar

looks like you are submitting the form to create a group but not providing a name. could be a form issue, or how you handle the processing on the backend.

1 like
zachleigh's avatar

In your controller, you're calling $group->invites()->create. Id have to see your group model, but Im pretty sure that $group->invites() returns an array of invites. You cant call create on an array of models, so it tries to create a new group instead. This fails because you dont have the correct column names for the group table. I would do something like

$invites = $group->invites();

foreach ($invites as $invite)
{
  $invite->create([
            'code' => $code,
            'expires_at' => Carbon::now()->addDays(7) // invite expires in 7 days
        ]);
}
Kryptonit3's avatar
$group->invites()->create([
    'code' => $code,
    'expires_at' => Carbon::now()->addDays(7)
]);

is the proper way to create a related data record as long as the relationships are setup right and $group is an eloquent object of an existing Group record. Depending on the type of relationship you have you can use this to create multiple invites per group( many to many), or if it is a hasOne belongsTo relationship running this twice on one group will probably create an error.

1 like
CedricBongaerts's avatar

@zachleigh The code given gives this error: FatalErrorException in GroupController.php line 46: syntax error, unexpected '$invite' (T_VARIABLE)

@Kryptonit3 I followed your 'hasMany' relationship

Here are my models below..

My Group mode is like this:

    <?php namespace App;

use Illuminate\Database\Eloquent\Model;

class Group extends Model {

    protected $table = 'groups';

    protected $fillable = ['name'];

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

    public function invite()
    {
        return $this->hasMany('App\Invite');
    }

}

And my Invite model is:

<?php namespace App;

use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

class Invite extends Model {

    protected $fillable = ['group_id', 'code', 'expires_at'];
    
    protected $dates = ['expires_at'];

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

    public static function generate()
    {
        $exists = true;
        while ($exists) {
            $code = str_random(15);
            $check = self::where('code', $code)->first();
            if( ! $check){
                $exists = false;
            }
        }
        return $code;
    }
}
zachleigh's avatar

In your group controller, you're calling invites() but in the model the method is invite().

1 like
CedricBongaerts's avatar

@zachleigh Still getting the same error but nice catch.

QueryException in Connection.php line 624: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'name' cannot be null (SQL: insert into groups (name, updated_at, created_at) values (, 2015-06-14 15:58:34, 2015-06-14 15:58:34))

Update I also retried the code you suggested but I'm still getting the same error:

<?php namespace App\Http\Controllers;

use App\Group;
use App\Invite;
use App\Http\Requests;
use App\Http\Controllers\Controller;

use Illuminate\Http\Request;

use Carbon\Carbon;

class GroupController extends Controller {

    public function __construct()
    {
        $this->middleware('auth');
    }
...
public function createInvite()
    {
        $group = Group::find(1); // Group ID you want to manage
        $code = Invite::generate();
        $invites = $group->invite();

        foreach ($invites as $invite)
        {
          $invite->create([
                    'code' => $code,
                    'expires_at' => Carbon::now()->addDays(7) // invite expires in 7 days
                ]);
        }

        //Then to check invite      
        return redirect()->back();
    }
...
}
Kryptonit3's avatar

What are you doing to create this error? It looks like you are trying to create a group but not providing a name. Check your form route/controller action. I have a feeling you are posting to the wrong thing.

1 like
Kryptonit3's avatar

For semantic purposes the invite method on your Group model should be named invites() as a Group has many invites.

This is how is should be done. And once you feel good about how it works, implement proper record fetching (adding $id to the createInvite() method etc).

public function createInvite()
{
    $group = Group::find(1); // Group ID you want to manage
    $code = Invite::generate();
    $invite = $group->invites()->create([
        'code' => $code,
        'expires_at' => Carbon::now()->addDays(7) // invite expires in 7 days
    ]);

    $string 'Your group name is ' . $group->name . ' and the invite you created for this group is ' . $invite->code . ' and it expires ' . $invite->expires_at->diffForHumans();
    
    return $string;
}
1 like
CedricBongaerts's avatar

@Kryptonit3 @zachleigh Ok I fixed it! Awesome

Here is the code I have now:

View with form:

    {!! Form::open(['route' => 'invite.create', 'controller' => 'createInvite']) !!}
    <div class="form-group">
            <div class="col-md-6 col-md-offset-4">
                {!! Form::submit('Generate Code', ['class' =>  'btn btn-primary']) !!}
            </div>
        </div>
    {!! Form::close() !!}

When I view-source I get (which should be correct):

<form method="POST" action="http://eindwerk.dev:8000/invites" accept-charset="UTF-8" controller="createInvite"><input name="_token" type="hidden" value="AvXCPzVvCUaWwGwoVOsQe3NZCNMlQs9y1oPXUJZd">
    <div class="form-group">
            <div class="col-md-6 col-md-offset-4">
                <input class="btn btn-primary" type="submit" value="Generate Code">
            </div>
        </div>
    </form>


Invite.php Model:

<?php namespace App;

use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

class Invite extends Model {

    protected $fillable = ['group_id', 'code', 'expires_at'];
    
    protected $dates = ['expires_at'];

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

    public static function generate()
    {
        $exists = true;
        while ($exists) {
            $code = str_random(15);
            $check = self::where('code', $code)->first();
            if( ! $check){
                $exists = false;
            }
        }
        return $code;
    }
}

Group.php model

<?php namespace App;

use Illuminate\Database\Eloquent\Model;

class Group extends Model {

    protected $table = 'groups';

    protected $fillable = ['name'];

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

    public function invites()
    {
        return $this->hasMany('App\Invite');
    }

}

My GroupController.php with the createInvite() function:

<?php namespace App\Http\Controllers;

use App\Group;
use App\Invite;
use App\Http\Requests;
use App\Http\Controllers\Controller;

use Illuminate\Http\Request;

use Carbon\Carbon;

class GroupController extends Controller {

    public function __construct()
    {
        $this->middleware('auth');
    }
...
public function createInvite()
    {
        $group = Group::find(1); // Group ID you want to manage
        $code = Invite::generate();
        $invite = $group->invites()->create([
            'code' => $code,
            'expires_at' => Carbon::now()->addDays(7) // invite expires in 7 days
        ]);

        return 'created invite';
    }
...
}

My routes.php

$router->post('invites', ['as' => 'invite.create', 'uses' => 'GroupController@createInvite']);

FINALLY! Cheers

Kryptonit3's avatar
Level 11

I know this is in your routes.php

$router->post('invite', ['as' => 'invite.create', 'uses' => 'GroupController@createInvite']);

but just in case there is something conflicting show us all routes that are around there. Make sure there isn't a naming or method conflict.

Also all you have to do is {!! Form::open(['route' => 'invite.create']) !!}

And since the controller method is hardcoded to find Group::find(1) then this is ok, but you will eventually need to post an actual group id with a related view input and look for that in the method.

1 like
CedricBongaerts's avatar

Yep! I understand it now. With alot of searching today.. finally. I just need some rest I think. Been working 36hours straight living on Redbulls, Coffee and Cigarettes :D Gonna sleep now and do all that tomorrow!

Thanks again for your help! I'd like to give both of you a 'Best Answer' tag seeing you both helped out enourmously but seeing @Kryptonit3 helped me off from the start I'll simply be giving his last post the Correct Answer. Just not everything above helped out and there isn't really a best answer.

Please or to participate in this conversation.