Home > Mobile >  How to make it easier to access options in Laravel
How to make it easier to access options in Laravel

Time:12-31

There is a database structure like this:

users
    id
    name
    
user_options
    id
    user_id
    option_name
    option_value

There can be a lot of options, so I didn’t make a separate field for each of them.

I would like to make it easier to access an option by its name.

Currently implemented like this:

In the User model:

    public function options() : HasMany
    {
        return $this->hasMany(UserOptions::class);
    }

For the test, I write the code directly in web.php in routes:

$user = User::with('options')->first();

$theme = $user
            ->options
            ->firstWhere('option_name', '=', 'theme')
            ->option_value;

There are many options and I would not like to make such a voluminous appeal to each of them.

Please help me to simplify access to options

CodePudding user response:

If you absoltely must access like an object you could add an attribute accessor on your user model like so:

protected function options(): Attribute
{
  return Attribute::make(
    get: function($_){
      
      if($this->userOptions !== null){ // have the user options not already been set?
        $this->setUserOptions()        // set them if not
      }

      return $this->userOptions        // return them
    }
  )
}

private function setUserOptions(): void
{
  $this->userOptions = new stdClass()

  foreach(UserOptions::where('user_id', $this->id)->get() as $option){
    $optionName = $option['option_name']
    $optionValue = $option['option_value']

    $this->userOptions->$optionName = $optionValue
  }
}

Call like

$user->options->theme

But be way of nonexistant options

A much less complex way would be adding a helper function on your user Model though like so:

/**
 * @return Collection<UserOption>
 */
public function options(): HasMany
{
    return $this->hasMany(UserOption::class, 'user_id', 'id');
}

/**
 * @param string $optionName
 * @return mixed
 */
public function getOption(string $optionName): mixed
{
    /** @var UserOption $option */
    foreach($this->options as $option){
        
        if($option->option_name === $optionName){
            return $option['option_value'];
        }
    }

    return null;
}

And simply call like $user->getOption('color'); // eg: "red" | null

  • Related