Relationship not returning fields

Published 2 years ago by madsynn

Hello everyone, Hope you can help me.

Windows 10 / Homestead Laravel 5.1

I have a ecommerce project i am building and here is my problem.

I have the following tables:

  1. products
 Schema::create('products', function (Blueprint $table)
        {
            $table->increments('id');
            $table->string('status')->nullable();
            $table->string('availability')->default('Available');
            $table->string('slug')->nullable();
            $table->string('name')->nullable();
            $table->string('subtitle')->nullable();
            $table->string('manufacturer')->default('The Grace Company');
            $table->longText('details');
            $table->longText('description');

            $table->string('thumbnail')->nullable();
            $table->string('photo_album')->nullable();
            $table->dateTime('pubished_at')->index();
            $table->string('lang', 255);
            $table->timestamps();
            $table->softDeletes();
        });
  1. prices
    Schema::create('prices', function (Blueprint $table)
        {
            $table->increments('id');
            $table->integer('product_id')->unsigned()->index();
            $table->decimal('price', 11, 2)->default('0.00');
            $table->string('model', 12)->nullable();
            $table->string('sku', 12)->default('000000');
            $table->string('upc', 13)->default('000000');
            $table->bigInteger('quantity')->default('99');
            $table->string('alt_details');
            $table->timestamps();
            $table->softDeletes();
            $table->engine = 'InnoDB';
            $table->foreign('product_id')->references('id')->on('products')->onUpdate('cascade')->onDelete('cascade');

        });

I have the following relationships product.php

    public function productPrice() {      return $this->hasMany(Price::class);    }

price.php

 public function product()    {        return $this->BelongsToMany(Product::class);    }

My problem is i cannot get my pricing to store to the alternate table pricing here is my controller store function.

public function store(Request $request) {
$this->validate($request, [
'name' => 'required',
]);
$dest = 'testing/';
$name  = str_random(4) . '_' . $request->file('thumbnail')->getClientOriginalName();
$request->file('thumbnail')->move($dest, $name);
$product = $request->all();
$product['thumbnail'] = '/' . $dest . $name;
$product = Product::create($product);

if ($request->has('productPrices')) {
foreach ($request->productPrices as $price){
if (!empty($price['price'])){
$price = Price::create($request->all());
}
}
}

foreach ($request->categories as $category_id)
        {
            CategoryProduct::create(['category_id' => $category_id, 'product_id' => $product->id]);
        }

FlashAlert()->success('Success!', 'The Product Was Successfully Added');

        return \Redirect(getLang() . '/admin/products');
}

I can store the product just fine but i cannot get it to store the product pricing table data.

any help would be greatly appreciated.

Best Answer (As Selected By madsynn)
Snapey

Saving;

        //needs more thought about handling new prices. This just copes with editing existing ones
        foreach ($request->prices as $productPrice)
        {
            $price =  Price::findOrFail($productPrice['id'])

            $price->title       = $productPrice['title'];
            $price->price       = $productPrice['price'];
            $price->model       = $productPrice['model'];
            $price->sku         = $productPrice['sku'];
            $price->upc         = $productPrice['upc'];
            $price->quantity    = $productPrice['quantity'];
            $price->alt_details = $productPrice['alt_details'];
            $price->save();
        }

        //or, assuming $fillable correct on model..
        foreach ($request->prices as $productPrice) {
            Price::where('id',$productPrice['id'])->update($productPrice);
        }
primordial

Should a price belong to many products?

try changing price.php

 public function product()    {        return $this->BelongsTo(Product::class);    }

change controller/store

...
$product = Product::create($product);

if ($request->has('productPrices')) {
foreach ($request->productPrices as $price){
if (!empty($price['price'])){
$product->prices()->create($price);
}
...

Good luck.

madsynn

Thank you for the help @primordial

Ok I was able to get it to start saving but the same data is getting saved in all the fields.

        if(!empty($request->price)){
            foreach($request->price as $productPrice){

                $price = new Price();
                $price->product_id = $product->id;
                $price->price =  $productPrice;
                $price->upc =  $productPrice;
                $price->model =  $productPrice;
                $price->quantity =  $productPrice;
                $price->sku =  $productPrice;
                $price->alt_details =  $productPrice;
                $product->prices()->save($price);
                //dd($price);
            }
        }
madsynn

@Snapey @primordial Ok here is my complete store method, I am having trouble with 2 areas any help would be appreciated.

  1. pricing stores the same data in all fields
  2. album is not storing fields only the file
public function store(CreateProductRequest $request)
    {


//      /**
//       * Validate the submitted Data
//       */
        $this->validate($request, [
            'name' => 'required',
//          'manufacturer' => 'required',
//          'price' => 'required',
//          'details' => 'required',
//          'quantity' => 'required',
//          'categories' => 'required',
//          'thumbnail' => 'required|image',
//      ]);


        if($request->hasFile('album')){
            foreach($request->album as $photo){
                if($photo && strpos($photo->getMimeType(), 'image') === false){
                    return \Redirect()->back();
                }
            }
        }


        /**
         * Upload a new thumbnail and thumbnail2
         */
        $dest  = 'uploads/products/today/';
        $name  = str_random(11) . '_' . $request->file('thumbnail')->getClientOriginalName();
        $request->file('thumbnail')->move($dest, $name);

        $name2 = str_random(11) . '_' . $request->file('thumbnail2')->getClientOriginalName();
        $request->file('thumbnail2')->move($dest, $name2);
        //$product = $request->all();
        $input = $request->all();

         //dd($input);

        $input['thumbnail'] = '/' . $dest . $name;

        $input['thumbnail2'] = '/' . $dest . $name2;




        $product = Product::create($input, $request->except(
            'attribute_name',
            'product_attribute_value',
            'price',
            'sku',
            'quantity',
            'model',
            'upc',
            'alt_details',
            'feature_name',
            'use_icon',
            'icon',
            'photo_src',
            'alt',
            'caption',
            'photoinfo',
            'linkto',
            'use_main',
            'use_thumb',
            'use_gallery'
        ));





        if(!empty($request->price)){
            foreach($request->price as $productPrice){

                $price = new Price();
                $price->product_id = $product->id;
                $price->price =  $productPrice;
                $price->upc =  $productPrice;
                $price->model =  $productPrice;
                $price->quantity =  $productPrice;
                $price->sku =  $productPrice;
                $price->alt_details =  $productPrice;
                $product->prices()->save($price);
                //dd($price);
            }
        }

//      if($request->has('productPrices')){
//          foreach($request->productPrices as $price){
//              if(!empty($price['price'])){
//                  $product->prices()->create($price);
//              }
//          }
//      }


        /**
         * Upload Album Photos
         */
        if($request->hasFile('album')){
            foreach($request->album as $photo){
                if($photo){
                    $name = str_random(11) . "_" . $photo->getClientOriginalName();
                    $photo->move($dest, $name);

                    AlbumPhoto::create([
                        'product_id' => $product->id,
                        'photo_src' => "/" . $dest . $name,
                        'alt' => $photo->alt,
                        'caption' => $photo->caption,
                        'photoinfo' => $photo->photoinfo,
                        'linkto' => $photo->linkto,
                        'use_main' => $photo->use_main,
                        'use_thumb' => $photo->use_thumb,
                        'use_gallery' => $photo->use_gallery
                    ]);
                }
            }
        }


        /**
         * Linking the categories to the product
         */

        foreach($request->categories as $category_id){
            CategoryProduct::create(['category_id' => $category_id, 'product_id' => $product->id]);
        }

        /**
         * Linking the options to the product
         */

        if($request->has('options')){
            foreach($request->options as $option_details){
                if(!empty($option_details['name']) && !empty($option_details['values'][0])){
                    $option = Option::create([
                        'name' => $option_details['name'],
                        'product_id' => $product->id
                    ]);
                    foreach($option_details['values'] as $value){
                        OptionValue::create([
                            'value' => $value,
                            'option_id' => $option->id
                        ]);
                    }
                }
            }
        }

        if(!empty($request->attribute_name)){
            foreach($request->attribute_name as $key => $item){
                $productVariant = new ProductVariant();
                $productVariant->attribute_name = $item;
                $productVariant->product_attribute_value = $request->product_attribute_value[$key];
                $product->productVariants()->save($productVariant);
            }
        }

        if(!empty($request->feature_name)){
            foreach($request->feature_name as $feature){
                $productFeature = new ProductFeature();
                $productFeature->feature_name = $feature;
                $product->productFeatures()->save($productFeature);

            }
        }

        FlashAlert()->success('Success!', 'The Product Was Successfully Added');
        return \Redirect(getLang() . '/admin/products');
    }

I added except the product create command for all the fields that belong to other tables but not really sure what the function of this is for but thought it was worth a try.

Snapey
Snapey
2 years ago (1,044,115 XP)

What does the data from the form look like? dd($request->price)

Snapey
Snapey
2 years ago (1,044,115 XP)

same data in all fields?

if(!empty($request->price)){
            foreach($request->price as $productPrice){

                $price = new Price();
                $price->product_id = $product->id;
                $price->price =  $productPrice;
                $price->upc =  $productPrice;
                $price->model =  $productPrice;
                $price->quantity =  $productPrice;
                $price->sku =  $productPrice;
                $price->alt_details =  $productPrice;
                $product->prices()->save($price);
                //dd($price);
            }
        }

because you put $productPrice in them all???

Snapey
Snapey
2 years ago (1,044,115 XP)

I added except the product create command for all the fields that belong to other tables but not really sure what the function of this is for but thought it was worth a try.

You need to do this if you have duplicate field names in product and price, otherwise the model just takes the fields that are $fillable and ignores everything else

madsynn

@Snapey y ok that has a typo i didnt see it should have been

if(!empty($request->price)){
            foreach($request->prices as $productPrice){

                $price = new Price();
                $price->product_id = $product->id;
                $price->price =  $productPrice;
                $price->upc =  $productPrice;
                $price->model =  $productPrice;
                $price->quantity =  $productPrice;
                $price->sku =  $productPrice;
                $price->alt_details =  $productPrice;
                $product->prices()->save($price);
                //dd($price);
            }
        }

But im not sure if that is correct. The foreach($request->prices as $productPrice){ in the part (->prices) is refering to my relationship in my product model. Am i doing this right?

Snapey
Snapey
2 years ago (1,044,115 XP)

What does prices look like?

you are clearly assigning the same variable to all the fields. Not sure why?

madsynn

@Snapey

You need to do this if you have duplicate field names in product and price, otherwise the model just takes the fields that are $fillable and ignores everything else

by fillable do you mean the fillable on all the models that are processing through the controller or just the main primary model. Does it look at them all the same or as all complete.

Example

├── models
     ├── Product  - $fillable = ['id', 'slug', 'ispromo', 'is_published', 'name', 'subtitle', 'details', 'description', 'status', 'thumbnail', 'photo_album', 'pubished_at',  'manufacturer', 'category_id'];
     ├── Price  - $fillable = ['product_id', 'price', 'model', 'sku', 'upc', 'quantity', 'alt_details', 'deleted_at'];
     ├── ProductFeature  - $fillable = ['feature_name', 'useicon', 'icon', 'created_at', 'updated_at'];
     ├── ProductFeature  - $fillable = ['attribute_name', 'attribute_value'];
     └── **ProductController = Combined $fillable from all above models?**

madsynn

@Snapey

dd($request->price)

array:1 [▼
  0 => "2865575"
]

dd($request->prices)

null

dd($request->all())

array:39 [▼
  "status" => "Available"
  "manufacturer" => "The Company"
  "office_status" => "Draft"
  "is_published" => "1"
  "ispromo" => "0"
  "name" => "name"
  "subtitle" => "subtitle"
  "categories" => array:1 [▶]
  "features_heading" => "features_heading"
  "details" => "details"
  "feature_name" => array:1 [▶]
  "useicon" => "1"
  "icon" => "icon-caret-right"
  "description" => "description"
  "video_url" => "video_url"
  "slug" => "slug"
  "caption" => array:1 [▶]
  "alt" => array:1 [▶]
  "photoinfo" => array:1 [▶]
  "use_main" => array:1 [▶]
  "use_thumb" => array:1 [▶]
  "use_gallery" => array:1 [▶]
  "model" => array:1 [▶]
  "price" => array:1 [▶]
  "quantity" => array:1 [▶]
  "sku" => array:1 [▶]
  "upc" => array:1 [▶]
  "alt_details" => array:1 [▶]
  "meta_title" => "meta_title"
  "meta_keywords" => "meta_keywords"
  "meta_description" => "meta_description"
  "facebook_title" => "facebook_title"
  "google_plus_title" => "google_plus_title"
  "twitter_title" => "twitter_title"
  "attribute_name" => array:1 [▶]
  "product_attribute_value" => array:1 [▶]
  "tracking" => "tracking"
  "datalayer" => "datalayer"
  "_token" => "8RyZcfEXXkAd2iq3Hl0sU193jQ3HtlEeLXQXUiiB"
]

Ok I am not getting how to get the price array returned or stored.

Looking at the above output of request->all it looks like all the data in the request is coming by itself and not in a array. how do i get all the price fields to be in an array when its submitted?

Snapey
Snapey
2 years ago (1,044,115 XP)

I'm not sure what you mean?

price is an array with a single value. Is that value not what you expected?

Why are you expecting more than one price?

madsynn

@Snapey

Ok to clarify each product has a main price but can have prices added for different versions of the product. The different versions have different data. So each product can have many different prices depending on the version or variation.

Here is the pricing table to show what i mean.

<table class="table table-striped table-hover table-bordered" id="product-pricing-table">
                        <thead>
                            <tr>
                                <th>Title:</th>
                                <th>Model:</th>
                                <th>Price:</th>
                                <th>Quantity:</th>
                                <th>SKU:</th>
                                <th>UPC:</th>
                            </tr>
                        </thead>
                        <tbody>
                            @if(isset($product) && $product->prices->count()<0)
                                @foreach($product->prices as $price)
                                    <tr class="alt">
                                        <td><input type="text" class="form-control" name="price[price_title]" value="{!! $price->model !!}" /></td>
                                        <td><input type="text" class="text-center form-control" name="price[model]" value="{!! $price->model !!}" /></td>
                                        <td><input type="text" class="text-center form-control currency" name="price[price]" value="{!! $price->price !!}" data-affixes-stay="false" data-prefix="$ " data-thousands="," data-decimal="." /> </td>
                                        <td><input type="text" class="text-center form-control" name="price[quantity]" maxlength="4" value="{!! $price->quantity !!}" /></td>
                                        <td><input type="text" class="text-center form-control" name="price[sku]" value="{!! $price->sku !!}" /></td>
                                        <td><input type="text" class="text-center form-control" name="price[upc]" maxlength="12" value="{!! $price->upc !!}" /></td>
                                    </tr>
                                    <tr class="alt">
                                        <td colspan="1" class="labelTextarea"><label>  <strong>Product Variation Details:</strong></label></td>
                                        <td colspan="5"> <textarea rows="3" class="form-control details-input" name="price[alt_details]" value="{!! $price->alt_details !!}"></textarea></td>
                                    </tr>
                                    <tr class="spacer invis"><td colspan="5"></td></tr>
                                @endforeach
                            @else
                                    <tr class="alt">
                                        <td><input type="text" class="form-control" name="price[price_title]" value="" /></td>
                                        <td><input type="text" class="text-center form-control" name="price[model]" value="" /></td>
                                        <td><input type="text" class="text-center form-control currency" name="price[price]" placeholder="$0.00" data-affixes-stay="false" data-prefix="$ " data-thousands="," data-decimal="." /></td>
                                        <td><input type="text" class="text-center form-control" name="price[quantity]" maxlength="4" /></td>
                                        <td><input type="text" class="text-center form-control" name="price[sku]" value="" /></td>
                                        <td><input type="text" class="text-center form-control" name="price[upc]" maxlength="12" value="636343" /></td>
                                    </tr>
                                    <tr class="alt">
                                        <td colspan="1" class="labelTextarea"><label><strong>Product Variation Details:</strong></label></td>
                                        <td colspan="5"><textarea rows="3" class="form-control details-input" name="price[alt_details]" placeholder="add the details or difference here:"></textarea></td>
                                    </tr>
                                    <tr class="spacer invis"><td colspan="5"></td></tr>
                            @endif
                        </tbody>
                    </table>

That is why the product relationship is set as hasMany and the price is belongsTo.

Sorry i should have clarified that first.

Snapey
Snapey
2 years ago (1,044,115 XP)

so the problem starts with the form. You can't have repeating sections using the same form field names as you will only get one set of results.

When editing existing records, I would probably name them after the price model id so that you can update the same record later

Its a while since I have done anything like this, but eg

<tr class="alt">
    <td><input type="text" class="form-control" name="price[{{ $price->id}}][price_title]" value="{!! $price->model !!}" /></td>
    <td><input type="text" class="text-center form-control" name="price[{{ $price->id}}][model]" value="{!! $price->model !!}" /></td>
    <td><input type="text" class="text-center form-control currency" name="price[{{ $price->id}}][price]" value="{!! $price->price !!}" data-affixes-stay="false" data-prefix="$ " data-thousands="," data-decimal="." /> </td>
    <td><input type="text" class="text-center form-control" name="price[{{ $price->id}}][quantity]" maxlength="4" value="{!! $price->quantity !!}" /></td>
    <td><input type="text" class="text-center form-control" name="price[{{ $price->id}}][sku]" value="{!! $price->sku !!}" /></td>
    <td><input type="text" class="text-center form-control" name="price[{{ $price->id}}][upc]" maxlength="12" value="{!! $price->upc !!}" /></td>
</tr>

Either the above, or have separate forms for each productPrice. The user changes one row and presses save (on that row) and this is persisted by a productPrice controller as a single record.

If you do it with the array as per the example, you should have an array of prices, each with an array of attributes.

Snapey
Snapey
2 years ago (1,044,115 XP)

by fillable do you mean the fillable on all the models that are processing through the controller or just the main primary model. Does it look at them all the same or as all complete.

What I mean is that if you pass the entire request to the model for saving, it is only allowed to pick the values from the request that are in its $fillable array.

Send this to the product model;

array:39 [▼
  "status" => "Available"                           // this one
  "manufacturer" => "The Company"                           // this one
  "office_status" => "Draft"
  "is_published" => "1"                         // this one
  "ispromo" => "0"                          // this one
  "name" => "name"                          // this one
  "subtitle" => "subtitle"                          // this one
  "categories" => array:1 [▶]
  "features_heading" => "features_heading"
  "details" => "details"                            // this one                         // this one
  "feature_name" => array:1 [▶]
  "useicon" => "1"
  "icon" => "icon-caret-right"
  "description" => "description"                            // this one
  "video_url" => "video_url"
  "slug" => "slug"                          // this one
  "caption" => array:1 [▶]
  "alt" => array:1 [▶]
  "photoinfo" => array:1 [▶]
  "use_main" => array:1 [▶]
  "use_thumb" => array:1 [▶]
  "use_gallery" => array:1 [▶]
  "model" => array:1 [▶]
  "price" => array:1 [▶]
  "quantity" => array:1 [▶]
  "sku" => array:1 [▶]
  "upc" => array:1 [▶]
  "alt_details" => array:1 [▶]
  "meta_title" => "meta_title"
  "meta_keywords" => "meta_keywords"
  "meta_description" => "meta_description"
  "facebook_title" => "facebook_title"
  "google_plus_title" => "google_plus_title"
  "twitter_title" => "twitter_title"
  "attribute_name" => array:1 [▶]
  "product_attribute_value" => array:1 [▶]
  "tracking" => "tracking"
  "datalayer" => "datalayer"
  "_token" => "8RyZcfEXXkAd2iq3Hl0sU193jQ3HtlEeLXQXUiiB"
]

(I may have missed a couple) The point being, that all the other fields are ignored.

By the way, there should never be a case of having id in the $fillable array

madsynn

@Snapey Thank you for helping me understand that.

So if the only values i can put in the create method how do i add the values that are in arrays?

array:39 [▼
  "status" => "Available"                           // this one
  "manufacturer" => "The Company"                           // this one
  "office_status" => "Draft"
  "is_published" => "1"                         // this one
  "ispromo" => "0"                          // this one
  "name" => "name"                          // this one
  "subtitle" => "subtitle"                          // this one
  "categories" => array:1 [▶]                //inArray How do I add it to the db:table 
  "features_heading" => "features_heading"
  "details" => "details"                            // this one                         // this one
  "feature_name" => array:1 [▶]                //inArray How do I add it to the db:table 
  "useicon" => "1"
  "icon" => "icon-caret-right"
  "description" => "description"                            // this one
  "video_url" => "video_url"
  "slug" => "slug"                          // this one
  "caption" => array:1 [▶]                //inArray How do I add it to the db:table 
  "alt" => array:1 [▶]                //inArray How do I add it to the db:table 
  "photoinfo" => array:1 [▶]                //inArray How do I add it to the db:table 
  "use_main" => array:1 [▶]                //inArray How do I add it to the db:table 
  "use_thumb" => array:1 [▶]                //inArray How do I add it to the db:table 
  "use_gallery" => array:1 [▶]                //inArray How do I add it to the db:table 
  "model" => array:1 [▶]                //inArray How do I add it to the db:table 
  "price" => array:1 [▶]                //inArray How do I add it to the db:table 
  "quantity" => array:1 [▶]                //inArray How do I add it to the db:table 
  "sku" => array:1 [▶]                //inArray How do I add it to the db:table 
  "upc" => array:1 [▶]                //inArray How do I add it to the db:table 
  "alt_details" => array:1 [▶]
  "meta_title" => "meta_title"
  "meta_keywords" => "meta_keywords"
  "meta_description" => "meta_description"
  "facebook_title" => "facebook_title"
  "google_plus_title" => "google_plus_title"
  "twitter_title" => "twitter_title"
  "attribute_name" => array:1 [▶]                 //inArray How do I add it to the db:table 
  "product_attribute_value" => array:1 [▶]                //inArray How do I add it to the db:table 
  "tracking" => "tracking"
  "datalayer" => "datalayer"
  "_token" => "8RyZcfEXXkAd2iq3Hl0sU193jQ3HtlEeLXQXUiiB"
]

Please sign in or create an account to participate in this conversation.