Ответы пользователя по тегу Laravel
  • Как связать значения характеристики с товаром?

    iMedved2009
    @iMedved2009
    Не люблю людей
    Окей берем вариант Дмитрий Л
    products
    --- id
    --- name

    product_attributes
    --- id
    --- name

    product_attribute_values
    --- id
    --- attribute_id
    --- product_id
    --- value

    Окей. Предположим

    class Product

    class Product extends Model
    {
        use HasFactory;
    
        protected $fillable = ['name'];
    
        public function attributes(): BelongsToMany
        {
            return $this->belongsToMany(Attribute::class, 'product_attribute_value')->withPivot(['value']);
        }
    }


    class Attribute

    class Attribute extends Model
    {
        use HasFactory;
    
        protected $fillable = ['name'];
    
        public function getValuesAttribute($value){
            return collect(explode(',', $value));
        }
    }


    данные

    $a1 = \App\Models\Attribute::create([
                'name' => 'Attr1',
            ]);
            $a2 = \App\Models\Attribute::create([
                'name' => 'Attr2',
            ]);
            $a3 = \App\Models\Attribute::create([
                'name' => 'Multy Attr3',
            ]);
    
    
            $p1 = \App\Models\Product::create([
                'name' => 'Product1',
            ]);
            $p1->attributes()->attach($a1->id, [
                'value' => '2012',
            ]);
            $p1->attributes()->attach($a2->id, [
                'value' => 'Джинса',
            ]);
            $p1->attributes()->attach($a3->id, [
                'value' => 'Синий',
            ]);
            $p1->attributes()->attach($a3->id, [
                'value' => 'Черный',
            ]);
            $p1->attributes()->attach($a3->id, [
                'value' => 'Зеленый',
            ]);
    
    
    
            $p2 = \App\Models\Product::create([
                'name' => 'Product2',
            ]);
            $p2->attributes()->attach($a1->id, [
                'value' => '2013',
            ]);
            $p2->attributes()->attach($a2->id, [
                'value' => 'Лен',
            ]);
            $p2->attributes()->attach($a3->id, [
                'value' => 'Красный',
            ]);
            $p2->attributes()->attach($a3->id, [
                'value' => 'Серобурый',
            ]);
    
            $p3 = \App\Models\Product::create([
                'name' => 'Product3',
            ]);
            $p3->attributes()->attach($a1->id, [
                'value' => '2015',
            ]);
            $p3->attributes()->attach($a2->id, [
                'value' => 'Лен',
            ]);
            $p3->attributes()->attach($a3->id, [
                'value' => 'Синий',
            ]);
            $p3->attributes()->attach($a3->id, [
                'value' => 'Желтый',
            ]);



    Естественно если мы дернем $products = Product::with('attributes')->get(); то у нас будет картинка которая автору не нравится.

    Но нет препятствий патриотам, добавляем в класс Product метод
    public function attributes_with_grouped_values(): HasMany{
            $instance = $this->newRelatedInstance(Attribute::class);
    
            $query = $instance->newQuery()->join('product_attribute_value', 'product_attribute_value.attribute_id', '=', 'attributes.id')
                ->groupBy('attributes.id', 'attributes.name', 'product_attribute_value.product_id')
                ->select('attributes.id', 'attributes.name', 'product_id', DB::raw('string_agg(product_attribute_value.value, \',\') as values'));
            // в случае с мускул string_agg(product_attribute_value.value, \',\') заменить на group_concact
            return $this->newHasMany(
                $query, $this, 'product_attribute_value.product_id', 'id'
            );
        }


    добавляем в класс Attribute метод
    public function getValuesAttribute($value){
            return collect(explode(',', $value));
        }


    Проверяем

    $products = Product::with('attributes_with_grouped_values')->get();
            foreach ($products as $product){
                echo $product->name.PHP_EOL;
                foreach ($product->attributes_with_grouped_values as $attribute){
                    dump(json_encode([$attribute->name => $attribute->values->all()]));
                }
            }


    Product1
    ^ "{"Attr1":["2012"]}"
    ^ "{"Attr2":["\u0414\u0436\u0438\u043d\u0441\u0430"]}"
    ^ "{"Multy Attr3":["\u0421\u0438\u043d\u0438\u0439","\u0417\u0435\u043b\u0435\u043d\u044b\u0439","\u0427\u0435\u0440\u043d\u044b\u0439"]}"
    Product2
    ^ "{"Attr1":["2013"]}"
    ^ "{"Attr2":["\u041b\u0435\u043d"]}"
    ^ "{"Multy Attr3":["\u041a\u0440\u0430\u0441\u043d\u044b\u0439","\u0421\u0435\u0440\u043e\u0431\u0443\u0440\u044b\u0439"]}"
    Product3
    ^ "{"Attr1":["2015"]}"
    ^ "{"Attr2":["\u041b\u0435\u043d"]}"
    ^ "{"Multy Attr3":["\u0416\u0435\u043b\u0442\u044b\u0439","\u0421\u0438\u043d\u0438\u0439"]}"


    Ровно как хотели.
    Является это хорошим решением? Не факт. Возможно в вашем случае стоит завести readonly виртуальную модель, возможно стоит смотреть в сторону view models и есть еще куча вариантов решения проблемы
    Ответ написан
    Комментировать
  • Возможно ли в laravel валидации поймать значение input'a и вставить в сообщение о ошибке?

    iMedved2009
    @iMedved2009
    Не люблю людей
    protected $messages = [
    'nameOrganization.required' => 'Заполните поле :attribute. :input - не подходит'
    ];

    https://laravel.com/docs/9.x/validation#manual-cus...
    Ответ написан
    5 комментариев
  • Как присоединить только 1 запись в запросе?

    iMedved2009
    @iMedved2009
    Не люблю людей
    Users::select(
        'users.*', 
        DB::raw("IF(exist (select * from admin where admin.user_id = users.id), 'admin', (select name from rank where score<=users.points order by score desc limit 1)) as rank"))
    ->get();
    Ответ написан
  • Как правильно добавить в Laravel ресурс данные из других моделей или массива?

    iMedved2009
    @iMedved2009
    Не люблю людей
    public function toArray($request)
        {
            return [
                'name' => $this->name,
                'email' => $this->email,
                'balance' => $this->resource->hasVerifiedEmail()?100:0,
            ];
        }


    но наверное правильнее - если у вас это во многих местах такая логика - вынести в модель т.е. через mutators и тогда будет просто $this->balance.
    Ответ написан
  • Неопределенная переменная в &quot;представлении&quot; Laravel. Почему так и как исправить?

    iMedved2009
    @iMedved2009
    Не люблю людей
    1. Не совсем понятно откуда у вас появляется во view переменная $i. Ее либо надо туда передавать, либо там инициализировать.
    2. При этом делать этого не надо, у blade есть The Loop Variable и стоит использовать {{$loop->index}}
    3. Этот код странен. Вы выбираете все из базы и начинаете фильтровать циклом. Зачем вам БД?
    $students = Students::all()->where('class','=',$i);

    Как бы
    $students = Students::where('class','=',$i)->get();

    4. Но и это не совсем правильно. Совсем правильно будет вместо
    if (isset($i)) {
                $students = Students::all()->where('class','=',$i);
            } else {
                $students = Students::all();
            }

    сделать:
    $students = Students::when($i, function($builder, $i){ return $builder->where('class', '=', $i); } )->get();


    Вот только параметр $i у вас обязательный - что в роуте что в методе. Каким образом у вас может возникнуть ситуация когда $i в методе необьявлена? По идее никогда - у вас вылетит эксепшн

    5. Смысл этого кода какой?
    try {
                $dbconnect = DB::connection()->getPDO();
                $dbname = DB::connection()->getDatabaseName();
            } catch(Exception $e) {
                return redirect('/exception');
            }
    Ответ написан
  • Почему не находит параметр в маршруте?

    iMedved2009
    @iMedved2009
    Не люблю людей
    В том что доку надо читать?

    {{route('category.show', ['category' => $category])}}
    Ответ написан
  • Отношение первой таблицы к третьей таблице через вторую таблицу, как?

    iMedved2009
    @iMedved2009
    Не люблю людей
    1. Открываем Laravel naming conventions и избавляемся от всех этих model_index. Фреймворк это не только набор инструментов, но так же набор соглашений которые стоит наблюдать

    2. Открываем доку на пункте Has Many Through

    class AutoMark extends Model
    {
        use HasFactory;
    
        public function models()
        {
            return $this->hasMany(AutoModel::class, 'mark_index', 'index');
        }
    
        public function modifications()
        {
            return $this->hasManyThrough(AutoModification::class, AutoModel::class);
        }
    }
    Ответ написан
    4 комментария
  • Laravel проверить есть ли запись в избранном, как решить проблему?

    iMedved2009
    @iMedved2009
    Не люблю людей
    Вы left join должны ограничивать при присоединении - а не в where.

    $user = Auth::user();
    DB::table('book')
        ->select('book.*')
        ->where([
            ['book.country', '=', $country->id],
            ['book.city', '=', 0],
            ['book.approve', '=', 1],
        ])
        ->when($user, function($query, $user)
        {
        	  $query->leftJoin('favorite', function($query) use($user){
                     $query->whereColumn('book.id', 'favorite.radio_id')->where('favorite.user_id', '=', $user->id);
              })->addSelect('favorite.id as favorite_checked');
    
        })
        ->paginate(50);


    P.S. А модели вы почему не используете?
    Ответ написан
    6 комментариев
  • Laravel Eloquent, where с несколькими вариациями значения столбца?

    iMedved2009
    @iMedved2009
    Не люблю людей
    потому что вы получаете запрос вида where status = 'active' or uid=2 or uid=6; и получаете все варианты.

    1. Использовать whereIn
    ->where('status',  '=' , 'active')
    ->whereIn('uid',  [2,6])
    ->get();


    2. Использовать обертку что бы получить запрос вида where status = 'active' and (uid=2 or uid=6)
    ->where('status',  '=' , 'active')
    ->where(function($builder){
      $builder->where('uid',  '=', '2')
          ->orWhere('uid',  '=', '6');
    })
    ->get();
    Ответ написан
    Комментировать
  • Как получить данные из связанной таблице по условию(Laravel)?

    iMedved2009
    @iMedved2009
    Не люблю людей
    Вы плохо прочитали доку, конкретно часть про querying relations
    $countries = Country::whereHas('cities', function($builder){
        return $builder->where('population', '>', 100000);
    })
    ->with(['cities' => function($builder){
        return $builder->where('population', '>', 100000)->orderBy('population', 'asc');
    }])
    ->get();
    Ответ написан
  • Как вывести значения из бд в зависимости от даты?

    iMedved2009
    @iMedved2009
    Не люблю людей
    Внезапно для такого достаточно документации.
    $items = User::when($request->get('login'), function($query, $login){ $query->where('login', $login) })
                    ->when($request->get('date_start'), function($query, $date_start){ $query->where('date_start', '>=', $date_start) })
                    ->when($request->get('date_end'), function($query, $date_end){ $query->where('date_end', '<=', $date_end) })
                    ->get();
    Ответ написан
    Комментировать
  • Как сделать запрос на поиск id городов?

    iMedved2009
    @iMedved2009
    Не люблю людей
    1. Зачем csrf при get запросе?
    2. Вместо url('/search') лучше использовать named routes и route('search')
    3. Надо забыть про $_GET и isset($_GET). У вас есть $request->get() и $request->has()
    4. Можно забыть про $request->has() у вас есть query()->when()
    5. Зачем вы делаете all()? Вы дергаете все записи потом это фильтруете? Зачем вам тогда БД?

    Итого:
    $items = Trip::when($request->get('day_date'), function($query, $date){ $query->where('date', $date); })
                    ->when($request->get('city_departure'), function($query, $departure_id){ $query->where('departure_id', $departure_id); })
                    ->when($request->get('city_arrival'), function($query, $landing_id){ $query->where('landing_id', $landing_id); })
                    ->get();
                return view('search')->with(['mass' => $items]);
    Ответ написан
    21 комментарий
  • В laravel view функция render для массива?

    iMedved2009
    @iMedved2009
    Не люблю людей
    Как бы если вам надо обработать массив - вам некуда не деться от того или иного обхода этого массива. Не вопрос вы можете сделать:

    $result = '';
    foreach ($comments as $comment){
        $result .= view('comment')->with('comment', $comment)->render();
    }


    но если вы сделаете свой вариант с доп.вьюхой а откроете папку compiled куда ларка складывает скомпилированные вьюхи - вы увидите ровно тот же код.
    Ответ написан
    2 комментария
  • Как вывести товары с категориями на одной странице?

    iMedved2009
    @iMedved2009
    Не люблю людей
    $categrories = Category::query()
                ->with(['products', 'products.ingredients', 'products.options'])
                ->get();
    
    @foreach($categrories as $categrory)
    {{$category->name}}
    @foreach($categrory->products as $product)
    {{$product->name}}
    @endforeach
    @endforeach
    Ответ написан
    1 комментарий
  • Как валидировать обязательно-необязательное поле и вернуть предыдущее значение в форму?

    iMedved2009
    @iMedved2009
    Не люблю людей
    То есть напрямую изменить одно поле в массиве входящих данных?

    есть решение в какой нибудь сервис провайдер запихнуть макрос ибо реквест у нас macroable, аля

    Illuminate\Http\Request::macro(
        'mergeGently', function($array){
    // где делаем магию аля проверки и прочее.
    });

    после чего будет работать $request->mergeGently($array);

    Как его туда прокинуть?

    app/Exceptions/Handler.php
    public function register()
        {
            $this->renderable(function (ValidationException $exception) {
                return redirect($exception->redirectTo ?? url()->previous())
                    ->withInput(Arr::except($exception->validator->getData(), $this->dontFlash))
                    ->withErrors($exception->errors(), $exception->errorBag);
            });
        }

    В принципе после этой правки все эксепшены с валидацией будут содержать ваши merge из prepareForValidation и не надо дублировать merge. Но стоит проверить как это будет реагировать на json запросы. мне лень

    З.Ы. Чего то сообразил - можно же легче - просто переопределить метод invalid у app/Exceptions/Handler.php
    Ответ написан
    2 комментария
  • Как при помощи group_concat получить данные из связанной таблицы?

    iMedved2009
    @iMedved2009
    Не люблю людей
    Post::where('status', 1)
        ->join('post_tag', 'posts.id', '=', 'post_tag.post_id')
        ->join('tags', 'tags.id', '=', 'post_tag.tag_id')
        ->select('posts.*', DB::raw('group_concat(tags.name) as tags_name'))
        ->groupBy('posts.id', 'posts.name', 'posts.content')->get();


    как вариант
    Post::where('status', 1)
        ->select('posts.*', DB::raw('select group_concat(tags.name) as tags_name from post_tag join tags on tags.id=post_tag.tag_id where post_tag.post_id = posts.id'))->get();
    Ответ написан
    1 комментарий
  • Как сгенерировать уникальный id в момент массовой вставки в базу данных?

    iMedved2009
    @iMedved2009
    Не люблю людей
    1. ну mariadb вроде как поддерживает из коробки функции в default то есть по факту
    Schema::table()....
    
    $table->string('uuid')->default(DB::raw('UUID()'));
    
    });
    должно сработать.

    2. Есть еще один вариант - $elem->{$elem->getKeyName()} = DB::raw('uuid()');

    З.Ы. MySQL 8 - тоже поддерживает. MySQL < 8 - нет (можно через триггеры). Postgres - да. Как вы наверное поняли очень блин важно сразу указывать точно что у вас там вертится, а не начинать новый сезон угадайки. ИбО БыВаЮт ВсЯкИе РаЗлиЧия.
    Ответ написан
    2 комментария
  • Как передать идентификатор в popup?

    iMedved2009
    @iMedved2009
    Не люблю людей
    Вынести popup в отдельный файл
    <div class="popUp popUp-product" id="product-popup-{{$product->id}}">

    <div class="products">
                        @foreach($products as $product)
                                    <div class="product">
                                    ...................
                                    @include('popup.file', ['product' => $product])
                                    </div>
                        @endforeach
    Ответ написан
  • В чем преимущества Route Model Binding?

    iMedved2009
    @iMedved2009
    Не люблю людей
    К посту jazzus который не поленился и написал все что должен был сказать я, когда предлагал route model binding, добавлю

    1. А нахрен в этом конкретном случае делать loadRelation('reviews') - оно автоматом подгрузится при использовании во вьюхе $post->reviews. Eager loading имеет смысл когда вы грузите кучу моделей и у них надо подгрузить отношение - что бы избежать N+1. А в этом случае какое N+1 мы избегаем? Это еще имело смысл в случае loadRelation('reviews.user') - но просто loadRelation('reviews') - нет. Ну и всегда остается вариант когда вы with запихиваете на момент resolve model.

    2. Вариант проверки статуса вполне возможно вообще выносить на уровень middleware для фронта через глобал скоуп, я так понимаю у вас этот статус сродни soft deletes

    3. На счет количества файлов и разноса функционала. Я так понимаю у вас table-driven development. Ради интереса наберите Domain-Driven Development в ютубе и посмотрите как там. ну к примеру https://www.youtube.com/watch?v=7HXIrEsmlzM&ab_cha...
    Ответ написан
    34 комментария
  • Как получить модели сравнив суммы полей отношений?

    iMedved2009
    @iMedved2009
    Не люблю людей
    public function scopePayedOrders(Builder $builder):Builder{
    return $builder->whereRaw('(select sum(incomes.sum) from incomes where incomes.order_id = orders.id) > (select sum(products.sum) from products where incomes.order_id = orders.id)');
    }
    
    $items = Orders::payedOrders()->get();


    Можно конечно через join.
    Ответ написан
    5 комментариев