5

I'm working on a project built on Laravel 3, and I'm trying to see if I can shorten the code for working with relationships (better ways of doing the following)

user controller

create user function

$newUser = new User;

if($userData['organization'])
    $newUser->organization = self::_professional('Organization', $newUser, $userData);
else
    $newUser->school = self::_professional('School', $newUser ,$userData);

create or retrieve school/organization id

private function _professional($type, $newUser, $userData)
{
    if ( $orgId = $type::where('name', '=', $userData[strtolower($type)])->only('id'))
        return $orgId;
    else
    {
        try {
            $org = $type::create(array('name' => $userData[strtolower($type)]));
            return $org->attributes['id'];
        } catch( Exception $e ) {
            dd($e);
        }
    }
}

Models

User model

class User extends Eloquent {

    public function organization()
    {
        return $this->belongs_to('Organization');
    }

    public function school()
    {
            return $this->belongs_to('School');
    }
}

Organization/School model

class Organization extends Eloquent {

    public function user() 
    {
        return $this->has_many('User');
    }

}

Migrations

Users migration

....
$table->integer('organization_id')->unsigned()->nullable();
$table->foreign('organization_id')->references('id')->on('organizations');

$table->integer('school_id')->unsigned()->nullable();
$table->foreign('school_id')->references('id')->on('schools');
....

Organizations/Schools migration

....
$table->increments('id');
$table->string('name');
$table->string('slug');
$table->integer('count')->default(1)->unsigned();
....

Now, my questions are:

  1. Is there any better way of generating the User -> School/Organization relationship, then the one used above? If so, how?

  2. Any better way of retrieving the User's School/Organization name then by doing: School::find($schoolId)->get()

Doing User::find(1)->school() won't retrieve any data for school, only:

[base:protected] => User Object
(
    [attributes] => Array
        (
            [id] => 1
            [nickname] => w0rldart
            ....
            [organization_id] => 
            [school_id] => 1
            ...
        )
    [relationships] => Array
        (
        )

    [exists] => 1
    [includes] => Array
        (
        )

)

[model] => School Object
(
    [attributes] => Array
        (
        )

    [original] => Array
        (
        )

    [relationships] => Array
        (
        )

    [exists] => 
    [includes] => Array
        (
        )

)
Alex
  • 7,538
  • 23
  • 84
  • 152

2 Answers2

3
// You have to save this before you can tied the organizations to it
$new_user->save();

// The organizations that you want to tie to your user
$oganization_ids = array(1, 2, 3);

// Save the organizations
$result = $new_user->organization()->sync($oganization_ids);
coffe4u
  • 538
  • 3
  • 5
  • The problem is that, for now, there is no autocomplete, so any input is a new input, with no existing IDs only name for the organization. So the organization must me inserted as well, and related with the user – Alex Jun 10 '13 at 19:59
3

Is there any better way of generating the User -> School/Organization relationship, then the one used above? If so, how?

Eloquent should be able to handle it automatically, see here: http://three.laravel.com/docs/database/eloquent#inserting-related-models.

Any better way of retrieving the User's School/Organization name then by doing: School::find($schoolId)->get()

If you mean you can't retrieve the relationship information: has_name and belongs_to return an Elloquent Expression, you still need to call get() on them to retrieve the object or the collection you want.

The way I've coped with this is adding an argument for relationships to determine if the method should return an expression or a result:

$table->increments('id');
$table->string('name');
$table->string('slug');
$table->integer('count')->default(1)->unsigned();
$table->unique('name');

...

class User extends Eloquent
{
    /**
     * Return an Elloquent Expression or a collection (or object)
     * Defaults to return a collection
     */
    public function organization ($as_expression=FALSE) {
        $related = $this->belongs_to('Organization');
        return $as_expression ? $related : $related->get();
    }

    public function school ($as_expression=FALSE) {
        $related = $this->belongs_to('School');
        return $as_expression ? $related : $related->get();
    }

    ...

    public function create ($user_data=array()) {
        $newUser = new User;
        $activity = @$user_data['organization'] ?
            'organization' : (@$user_data['school'] ? 'school' : '');

        switch ($activity) {
            case 'organization':
            case 'school':
                /**
                 * Call the corresponding method, return as Eloquent Expression
                 * Use a string to be verbose, TRUE does fine if wanted
                 */
                $new_user->{$activity}('as_expression')->save(array( 'name' => $user_data[$activity]));

                break;
            default:
                break;
        }

        return $new_user;
    }
}

...

class Organization extends Eloquent
{
    public function user ($as_expression=FALSE) {
        $related = $this->has_many('User');
        return $as_expression ? $related : $related->get();
    }
}
Ast Derek
  • 2,739
  • 1
  • 20
  • 28