0

I have the following code in an api endpoint, which checks there are no relationships on a model to be deleted (and returns true to show it's in use):

CONTROLLER

public function destroy(Group $group)
    {
        if ($group->inUse()) {
            return response(
                ['message' => 'This group cannot be deleted because it has either associated 
                catalogue items, users or organisations'],
                409
            );
        }

        $group->delete();
    }

MODEL

public function inUse()
{
    $models = [
        'categories',
        'items',
        'organisations',
    ];

    foreach ($models as $model) {
        if (count($this->{$model}) > 0 ){
            return true;
        }
    }

    return false;
}

The line which I don't fully understand is where we check the number of relations for each model: count($this->{$model})

I read on php.net that $this->{$var} is a variable variable, but that can't be the case here, the first run through of the loop would return an undefined variable $categories:

if($this->$categories) {
    //
}

Is this a laravel feature or special syntax? I did a quick search but nothing came up I could see.

Thanks in advance.

Leon Segal
  • 679
  • 7
  • 28
  • where did you find this code? – Akbar Soft Nov 19 '18 at 14:10
  • You can read about it here: [Complex (curly) syntax](http://php.net/manual/en/language.types.string.php#language.types.string.parsing.complex) – Remul Nov 19 '18 at 14:18
  • @Remul This is string interpolation and I believe it is something slightly different. – Leon Segal Nov 19 '18 at 14:34
  • @DejavuGuy it was in a codebase I am working on - I sanitised/changed it to hide the business critical info. – Leon Segal Nov 19 '18 at 14:35
  • 1
    I agree its not exactly what your looking for, but its the only mention of accessing object properties with curly braces on the php.net site that I could find. You can read more about in this [answer](https://stackoverflow.com/a/10333200/9193055) . – Remul Nov 19 '18 at 14:56
  • @Remul yeah my bad, I was totally getting mixed up there, you were right about the brackets! – Leon Segal Nov 19 '18 at 21:53

3 Answers3

5

Its php syntax, curly brackets used to call object properties dynamically, in your case this will be translated as:

if (count($this->categories) > 0 ), if (count($this->items) > 0 ) ...

RainDev
  • 1,098
  • 8
  • 9
1

You are calling property on the given model - by the look of it represented by the relationship as you're checking for the number of records.

I believe your $models variable contains names of the relationships https://laravel.com/docs/5.7/eloquent-relationships

Checking for count would suggest they return instance of the Collection and you could probably just use $this->{$model}->count() or $this->{$model}->isEmpty().

The curly braces in your example are optional and both of these are equivalent:

$this->{$model}
$this->$model

Same as using curly braces with strings:

"Some text {$array[0]}"

These are not variable variables - as documentation states

A variable variable takes the value of a variable and treats that as the name of a variable.

http://php.net/manual/en/language.variables.variable.php

Sebastian Sulinski
  • 5,815
  • 7
  • 39
  • 61
  • I thought the curly brackets in $this->{$var} meant a variable variable - https://secure.php.net/manual/en/language.variables.variable.php I would expect this to return an undefined variable error. – Leon Segal Nov 19 '18 at 14:32
  • They would be if you included `$` before the brackets and used it as a reference to the variable i.e. `${$var}`, but you're referring to the internal property of the given object `$this->{$var}` is equivalent of `$this->$var` - just a little syntax sugar with the brackets in this case. – Sebastian Sulinski Nov 19 '18 at 14:33
  • Thanks - I think that is what I tripping up on! – Leon Segal Nov 19 '18 at 14:38
1

As you can see here, first, it defines an array that list the relationships to check:

$models = [
    'categories',
    'items',
    'organisations',
];

Then, it loop this array to check that at least one of this relations has elements:

foreach ($models as $model) {
    if (count($this->{$model}) > 0 ){
        return true;
    }
}

So, if we take the first element of the array:

echo $models[0] // 'categories'

in the validation:

foreach ($models as $model) {
    // in this case, $model is 'categories'
    // now it check if the relationship has elements:
    // the following is equivalent to: if(count($this->{$model} > 0) {
    if (count($this->categories) > 0 ){
        return true;
    }
}
...
Kenny Horna
  • 13,485
  • 4
  • 44
  • 71