Hi @stevebauman, are that possible to add route model binding feature in Laravel to LDAPRecord and add pagination via Collection API that Laravel has?
So far, for handling pagination I convert LDAPRecord model to collection and install spatie/laravel-collection-macros to call paginate method.
Hi @satyakresna! Another great question.
I believe you should be able to accomplish this by creating your own LdapRecord model and adding the getRouteKey() and resolveRouteBinding() method:
namespace App\Ldap;
use LdapRecord\Models\ActiveDirectory\User as BaseUser;
class User extends BaseUser
{
public function getRouteKey()
{
return $this->getObjectGuid();
}
public function resolveRouteBinding($value, $field = null)
{
return $this->findByGuid($value);
}
}
Then, in your Laravel controllers/routes, it should be resolved through type-hints when you supply the users Object GUID as a URL parameter:
use App\Ldap\User;
Route::get('/ldap/users/{user}', function (User $user) {
// ...
});
Can you give that a shot?
Hi @stevebauman, I try and it looks like the another values like uid, givenname, cn, mail, etc don't appear when I run dd($user).
Here are my codes:
<?php
Route::get('/users/{user}/edit', [UserController::class, 'edit'])->name('users.edit');
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Ldap\User;
class UserController extends Controller
{
public function edit(User $user)
{
dd($user);
}
}
<?php
use LdapRecord\Models\OpenLDAP\User as BaseUser;
class User extends BaseUser
{
public function getRouteKey()
{
return $this->getObjectGuid();
}
public function resolveRouteBinding($value, $field = null)
{
return $this->findByGuid($value);
}
}
Hi @stevebauman, could you please follow up this issue?
Hi @satyakresna -- apologies. You're right -- the above doesn't work.
You will have to bind the models explicitly inside of the router using:
Route::model('parameter', Model::class) or;Route::bind('parameter', Closure $callback) (if you want the model resolution logic outside of the model)You can use either approach. Here's a quick overview of setting up both:
Using Route::model():
App\Providers\RouteServiceProvider.php:
// app/Providers/RouteServiceProvider.php
public function boot()
{
// ...
Route::model('ldap-user', \App\Ldap\User::class);
}
App\Ldap\User.php:
<?php
namespace App\Ldap;
use LdapRecord\Models\OpenLDAP\User as BaseUser;
class User extends BaseUser
{
public function resolveRouteBinding($value)
{
return $this->findByGuid($value);
}
}
routes/web.php:
Route::get('/ldap/users/{ldap-user}', [LdapUserController::class, 'index']);
Using Route::bind():
App\Providers\RouteServiceProvider.php:
// app/Providers/RouteServiceProvider.php
public function boot()
{
// ...
Route::bind('ldap-user', function ($value) {
return \App\Ldap\User::findByGuid($value);
});
}
routes/web.php:
Route::get('/ldap/users/{ldap-user}', [LdapUserController::class, 'index']);
Then, you should be able to visit the route with a string based GUID (or whichever attribute you use to locate an LDAP object) and it will resolve the model in your controller.
Let me know if you run into any issues! 馃憤
Hi @stevebauman, I try but it throws 404 Not Found. Here's my code. The url in browser looks like this: http://localhost:8002/users/[email protected],ou=users,dc=unud,dc=ac,dc=id/edit
Route::get('/users/{ldap-user}/edit', [UserController::class, 'edit'])->name('users.edit');
<?php
namespace App\Http\Controllers;
use App\Ldap\User;
class UserController extends Controller
{
public function edit(User $user)
{
dd($user);
}
}
<?php
namespace App\Ldap;
use LdapRecord\Models\OpenLDAP\User as BaseUser;
use LdapRecord\Query\Model\Builder;
class User extends BaseUser
{
/**
* The object classes of the LDAP model.
*
* @var array
*/
public static $objectClasses = [
'eduPerson',
'inetOrgPerson',
'organizationalPerson',
'person',
'top',
'unudPerson',
];
public function getRouteKey()
{
return $this->getObjectGuid();
}
public function resolveRouteBinding($value)
{
return $this->findByGuid($value);
}
}
Hi @stevebauman, could you please follow up this issue? Thank you.
Hey @satyakresna,
I believe your URL is incorrect. You're supplying a full distinguished name, when only the entryuuid should be given, as this attribute is used as the ObjectGUID for OpenLDAP:
Feel free to override the above attribute ($guidKey) if you'd prefer to find users by a different unique identifier for your LDAP environment.
If instead you'd prefer to keep using full distinguished names in the URL, then you will instead have to use the find() method, instead of findByGuid():
<?php
namespace App\Ldap;
use LdapRecord\Models\OpenLDAP\User as BaseUser;
class User extends BaseUser
{
public function resolveRouteBinding($dn)
{
return $this->find($dn);
}
}
Note, that if you're going to be supplying full DN's inside of the URL, you will have to URLEncode them, because DN's contain comma (,) and equal (=) symbols, which are reserved in URLs for query parameters.
Hope this helps!
Hi @stevebauman, I would like use the entryuuid. But, somehow OpenLDAP throws dn instead of entryuuid. Here are the code and screenshots
<?php
namespace App\Ldap;
use LdapRecord\Models\OpenLDAP\User as BaseUser;
use LdapRecord\Query\Model\Builder;
class User extends BaseUser
{
public function getRouteKeyName()
{
return 'entryuuid';
}
public function resolveRouteBinding($value)
{
return $this->findBy('entryuuid', $value);
}
}
// app/Providers/RouteServiceProvider.php
public function boot()
{
// ...
Route::model('ldap-user', \App\Ldap\User::class);
}
Route::get('/users/{ldap-user}/edit', [UserController::class, 'edit'])->name('users.edit');
<a href="{{ route('users.edit', $user) }}"/></a>

Could you please help about this issue?
Hi @stevebauman, could you please follow up this issue? Thanks.
Hi @satyakresna,
That's because you're passing in an LdapRecord model into blade, and the model is being resolved into a string.
When a model is resolved into a string, it will return the models distinguished name.
For example:
<a href="{{ route('users.show', $ldapUser) }}">View User</a>
Which executes:
<a href="<?php echo route('users.show', $ldapUser->__toString()); ?>">View User</a>
Which then outputs:
<a href="/users/uid=john doe,dc=local,dc=com">View User</a>
You will instead pass the entryUUID manually:
<a href="{{ route('users.show', $ldapUser->getFirstAttribute('entryUUID')) }}">View User</a>
Hi @stevebauman, it works great right now. Thanks a lot for your help. I was confused why it doesn't work and the culprit is the declaration route binding method. Ha ha ha ha.
In the code you given is like this:
// app/Providers/RouteServiceProvider.php
public function boot()
{
// ...
Route::model('ldap-user', \App\Ldap\User::class);
}
Route::get('/users/{ldap-user}/edit', [UserController::class, 'edit'])->name('users.edit');
It must be:
// app/Providers/RouteServiceProvider.php
public function boot()
{
// ...
Route::model('user', \App\Ldap\User::class);
}
Route::get('/users/{user}/edit', [UserController::class, 'edit'])->name('users.edit');
No problem! Happy to help. Really glad you've worked it out 馃帀