Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

kevinjohn's avatar

Basics of Model::find()

Some real basic Q's, sorry.

When using ModelName::find(101) does the find function only search the database table for a column called id ?

So if my index and auto-increment column is called name_id should I use a where? e.g. ModelName::where('name_id', $id)->get();

It's not an issue to do this, just no where in the docs does it say that find() only works with one column name...

0 likes
22 replies
pmall's avatar
pmall
Best Answer
Level 56

You can add a $primaryKey attribute to your model to specify a custom primary key name public $primarykey = 'name_id';

From the docs :

Eloquent will also assume that each table has a primary key column named id. You may define a $primaryKey property to override this convention.

http://laravel.com/docs/5.1/eloquent

10 likes
krenor's avatar

The find() method finds the Model by it's $primaryKey property.
If you have none set, it's going to assume id. If you have something set up like
protected $primaryKey = foo_id the find() function will go through foo_id instead of id.

1 like
phildawson's avatar

Ah yes this is what the find does.

 $this->query->where($this->model->getQualifiedKeyName(), '=', $id);
public function getQualifiedKeyName()
{
    return $this->getTable().'.'.$this->getKeyName();
}

public function getKeyName()
{
    return $this->primaryKey;
}

default

protected $primaryKey = 'id';
2 likes
pmall's avatar

Also, if you want to get only one record and not a collection you should use first() instead of get(). basic example is with slugs :

ModelName::where('slug', '=', $slug)->first();
4 likes
kevinjohn's avatar

@Krenor & @phildawson - Thats great info, thanks folks. The new laravel docs are great, but every now and then I don't manage to piece it all together.

@pmall The first versus get was my next question - thanks very much indeed!

phildawson's avatar

@kevinjohn The first() is actually used by find() behind the scenes.

The get() executes the select query.

Foo::get(); // SELECT * FROM foos;

The first() also calls get() behind the scenes but with a limit of 1...

Foo::first(); // SELECT * FROM foos LIMIT 1;

...and then gets the first item of the Collection to return a Model. Its the first equivalent of typing

Foo::take(1)->get()->first();

^ Note the first() here is a method on the Collection, not the Query Builder first().

Its just chaining like doing the short way of.

$foos = Foo::get(); // Collection

$foo = $foos->first(); // get the first Model from the Collection
1 like
Prullenbak's avatar

I didn't know you could change the primary keys. That means you could do

public $primaryKey = 'slug';

and then

ModelName::find($slug);

If you use slugs instead of id's way more on a certain model. Seems nice.

These forums are great...Just browsing through them is educational :P

1 like
pmall's avatar

I think a lot of people underestimate the power of laravel ^^ there is a solution for every common situations :)

phildawson's avatar

@Prullenbak @pmall

I would have thought in the case of slugs you will still be wanting a static findSlug method or a query scope Foo::findSlug('example')->first();

public function scopeFindSlug($query, $slug)
{
    return $query->where('slug', $slug);
}

that is unless your primary keys are unique slugs? Sounds like a mess when it comes to relationships.

pmall's avatar

@phildawson you cant return a model from a scope. Your findSlug should be a static method in order to work like this.

phildawson's avatar

@pmall ik, I spotted I was busy editing :p My main point was $primaryKey should be for the primary key.

pmall's avatar

Yes I would go with a scope and not changing the primary key name. In a lot of situation you still want to find by id (editing the post for example).

Prullenbak's avatar

That's true. But it's nice to have the option if you (like I said) use slugs more on an object. You could still find by id by doing

Model::where("id",$id)->first();

So you're just switching slugs for id's, essentially. Definitely not for all situations, but could be handy sometimes.

phildawson's avatar

@Prullenbak You'll need to specify the actual primary key in all relationships too. Probably other things too, not worth the headache.

If you want to omit the first() or get() then just have a static method on your model.

class Foo extends Model {
    public static function findSlug($slug)
    {
        return static::where('slug', $slug)->first();
    }
}
Foo::findSlug('example');
3 likes
pmall's avatar

Yes you should change the primaryKey name when the column is actually the table primary key.

Prullenbak's avatar

@phildawson Most of the time it's indeed "not worth the headache", but sometimes it might not be such a headache and it could make life a little easier. Situations differ, and I thought it was a nice thing to know you could do. That's all.

phildawson's avatar

@Prullenbak :) All for hacking around a framework to make things easier but doing a quick search reveals 28 occurrences using getKeyName, I'd be reluctant to change it unless I knew all the consequences/side effects then docblock'd the hell out of it. I can't think of any situation where it wouldn't cause more issues than solves but that doesn't mean there isn't a use for modifying the primary key to a column.

Prullenbak's avatar

" I can't think of any situation where it wouldn't cause more issues than solves"

That's because it doesn't solve a problem. typing where('slug',$slug)->first() instead of find($slug) isn't a problem at all. Just as it's not a problem to type SELECT * FROM posts WHERE slug = $slug

This is not hacking around a framework. This is (being able to) use a feature of a framework to do a little less typing and to make some code a little bit shorter/nicer. That's what we do all the time, right? Maybe you can't think of any situation where the little idea I had (and now almost regret sharing) could come in handy. Well, I do. And I said multiple times: This is not at all for all situations. But it could be nice.

Remember, not every project is the same as the one you're working on (right now). Don't judge too quickly, because you haven't seen every situation in every project in every company.

phildawson's avatar

@Prullenbak I understand. There's no need to be defensive I was only trying to offer helpful advice.

I've iterated a few times though this isn't a feature of the framework, it would be changing the behaviour of something that isn't supposed to be changed to get a different outcome. I would call that a hack.

Overriding the $primaryKey is only for when the tables primary key is not "id", not anything else like trying to be more efficient with queries. It was simply a friendly warning that it could will have consequences, and I personally would document the non-standard behaviour for other devs and myself in two weeks time when I go crazy why the standard find and model relationships doesn't do what I usually expect.

I was actually agreeing that although I can't think of a reason that doesn't mean there isn't a case for it.

I can't think of any situation where it wouldn't cause more issues than solves

but that doesn't mean there isn't a use for modifying the primary key to a column.

Prullenbak's avatar

"I was only trying to offer helpful advice."

And I was only sharing a little idea that, I admit, also has downsides. We're all good :)

benr1804's avatar

@pmall Thanks for your answer. My question is, is there something similar I can specify for my timestamps column. I know Laravel uses 'created_at' and 'updated_at' when calling create and update methods.

I have a database table where I cannot control the schema and the column names are slightly different so wondered if you could do anything like this:

$createdAt = 'member_created';
$updatedAt = 'last_updated';

Many thanks

Please or to participate in this conversation.