简体   繁体   中英

Trying to create project for specific product id laravel-8

  1. A user have many products and product have own id 2)And A product have many projects I have trouble to make ProjectController Note: if you need more details you can ask. This is my user model user.php
public function Products(){
        return $this->hasMany('App\Models\Product');

    }

    public function Project(){
        return $this->hasMany('App\Models\Project');
    }

This is my Product model product.php

public function User(){
        return $this->belongsTo(User::class);
    }

    public function Project(){
        return $this->hasMany('App\Models\Project');
    }

This is my project model project.php

public function User(){
        return $this->belongsTo(User::class);
    }

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

Here product table have user_id as forignId and project table have user_id and product_id as forign key This is project table project.php

$table->unsignedBigInteger ('user_id');
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->foreignId('product_id')->nullable();

This is here I have troubles in ProjectController.php

class ProjectController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        // $projects = Project::where('user_id',auth()->user()->id)->latest()->paginate(20);
        $projects = Project::where('user_id',auth()->user()->id)->where('product_id')->latest()->paginate(20);



        return view('projects.index', compact('projects'))
            ->with('i', (request()->input('page', 1) - 1) * 5);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('projects.create');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request,$id)
    {
        $request->validate([
            'chapter_name' => 'required',
            'sub_section_name' => 'required',
            'title_1' => 'required',
            'description_1' => 'required',
            'image_1' => 'required',
            'image_2' => 'required',
            'image_3' => 'required',
            'title_2' => 'required',
            'description_2' => 'required',
            'title_3' => 'required',
            'description_3' => 'required',
            'video_1' => 'required',
            'video_2' => 'required',
            'video_3' => 'required',
        ]);

        // $input = $request->all();
        $input['user_id'] = auth()->user()->id;
        $input['product_id'] = $id;

        Project::create($input);

        return redirect()->route('project.index')
                        ->with('success','Product created successfully.');

    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Project  $project
     * @return \Illuminate\Http\Response
     */
    public function show(Project $project)
    {
        // $category = $project->category;
        return view('projects.show', compact('project'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Project  $project
     * @return \Illuminate\Http\Response
     */
    public function edit(Project $project)
    {
        return view('projects.edit', compact('project'));
    }
    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Project  $project
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Project $project)
    {
        // $user_id =  Auth::user()->id ;

        $request->validate([
            'chapter_name' => 'required',
            'sub_section_name' => 'required',
            'title_1' => 'required',
            'description_1' => 'required',
            'image_1' => 'required',
            'image_2' => 'required',
            'image_3' => 'required',
            'title_2' => 'required',
            'description_2' => 'required',
            'title_3' => 'required',
            'description_3' => 'required',
            'video_1' => 'required',
            'video_2' => 'required',
            'video_3' => 'required',
        ]);

        $input = $request->all();

        $project->update($input);

        return redirect()->route('project.index')
                        ->with('success','Product updated successfully');
    }
    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Project  $project
     * @return \Illuminate\Http\Response
     */
    public function destroy(Project $project)
    {
        $project->delete();

        return redirect()->route('projects.index')
            ->with('success', 'Project deleted successfully');
    }

    public function importProject()
    {
        Excel::import(new ProjectsImport, request()->file('file'));

        return back()->with('success','Project created successfully.');
    }

    public function export()
    {
        return Excel::download(new UsersExport, 'projects.xlsx');
    }
}

This is user table user.php

 Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->foreignId('current_team_id')->nullable();
            $table->text('profile_photo_path')->nullable();
            $table->timestamps();
        });

This is products table products.php

 Schema::create('products', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->text('detail');
            $table->string('color');
            $table->string('image');
            $table->string('logo');
            $table->unsignedBigInteger('user_id');
            $table->timestamps();
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        });

This is project table project.php

Schema::create('projects', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('chapter_name', 255)->nullable();
            $table->string('sub_section_name', 500)->nullable();
            $table->string('title_1', 255)->nullable();
            $table->string('description_1', 5000)->nullable();
            $table->string('image_1', 255)->nullable();
            $table->string('image_2', 255)->nullable();
            $table->string('image_3', 255)->nullable();
            $table->string('title_2', 255)->nullable();
            $table->string('description_2', 5000)->nullable();
            $table->string('title_3', 255)->nullable();
            $table->string('description_3', 255)->nullable();
            $table->string('video_1', 255)->nullable();
            $table->string('video_2', 255)->nullable();
            $table->string('video_3', 255)->nullable();
            $table->unsignedBigInteger ('user_id');
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            // $table->foreignId('product_id')->nullable();
            $table->unsignedBigInteger('product_id')->references('id')->on('products')->onDelete('cascade');
            $table->timestamp('created_at')->useCurrent();
            $table->timestamp('updated_at')->nullable();
        });

Thanks for help

Below are 2 possible causes of your error.

  1. The uploaded file request()->file('file') lucks a column with header name id .

If this is the case you may wish to perform some sort of header validation during the import process. ie:

<?php

namespace App\Imports;

use App\Models\Project;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithHeadingRow;

class ProjectsImport implements ToCollection, WithHeadingRow
{
    use Importable;

    private const HEADING_NAMES = [
        'chapter_name',
        'sub_section_name',
        'title_1',
        'description_1',
        'image_1',
        'image_2',
        'image_3',
        'title_2',
        'description_2',
        'title_3',
        'description_3',
        'video_1',
        'video_2',
        'video_3',
        'id'
    ];

    private const HEADING_ROW = 0;

    public function collection(Collection $rows)
    {

        if (
            (count($columnHeadings = array_keys($rows[self::HEADING_ROW])) == count(self::HEADING_NAMES))
            && (array_diff($columnHeadings, self::HEADING_NAMES) === array_diff(self::HEADING_NAMES, $columnHeadings))
        ) {
            redirect()
                ->back()
                ->withErrors([
                    "import" => "Incorrect excel sheet headers."
                        . " "
                        . "Expected:"
                        . " " . json_encode(self::HEADING_NAMES)
                ]);
        }

        // If validation fails, it won't reach the next statement.

        foreach ($rows as $row) {
            Project::create([
                'chapter_name' => $row['chapter_name'],
                // ...
            ]);
        }
    }

    public function headingRow(): int
    {
        return self::HEADING_ROW;
    }
}
  1. You're using header names to access the data yet by default $row indexes are used instead. ie: $row[0] instead of $row['chapter_name'] .

If this is the case you may wish to implement the WithHeadingRow concern.

Laravel Excel | Heading Row

In case your file contains a heading row (a row in which each cells indicates the purpose of that column) and you want to use those names as array keys of each row, you can implement the WithHeadingRow concern.

ie:

<?php
use App\Models\Project;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;

class ProjectsImport implements ToModel, WithHeadingRow
{
    public function model(array $row)
    {
        return new Project([
            'chapter_name' => $row['chapter_name'],
            // ...
        ]);
    }
}

Addendum

If the uploaded file doesn't have the actual 'product_id' s but instead has the product names , you could perform some sort of preprocessing to replace product names with their respective 'product_id' s.

In addition, you could use some row validation to ensure that the product names exist in the database.

A. Validate product names making sure that they exist.

Laravel Excel | Row Validation without ToModel

<?php

namespace App\Imports;

use App\Models\Project;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithHeadingRow;

class ProjectsImport implements ToCollection, WithHeadingRow
{
    use Importable;

    public function collection(Collection $rows)
    {
        Validator::make($rows->toArray(), [
            // Table Name: 'products'. Table Column Name: 'name'. Excel Sheet Header Name: 'product_name'.
            '*.product_name' => ['required', 'exists:products,name'],
        ])->validate();

        // If validation fails, it won't reach the next statement.

        foreach ($rows as $row) {
            Project::create([

                'chapter_name' => $row['chapter_name'],
                // ...
            ]);
        }
    }
}

B. Perform some sort of preprocessing to replace product names with their respective 'product_id's

Laravel Excel | Mapping rows

By adding WithMapping you map the data that needs to be added as row. This way you have control over the actual source for each column.

ie:

<?php

namespace App\Imports;

use App\Models\Project;
use App\Models\Product;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMapping;

class ProjectsImport implements ToCollection, WithHeadingRow, WithMapping
{
    use Importable;

    public function collection(Collection $rows)
    {

        Validator::make($rows->toArray(), [
            '*.chapter_name' => 'required',
            '*.sub_section_name' => 'required',
            '*.title_1' => 'required',
            '*.description_1' => 'required',
            '*.image_1' => 'required',
            '*.image_2' => 'required',
            '*.image_3' => 'required',
            '*.title_2' => 'required',
            '*.description_2' => 'required',
            '*.title_3' => 'required',
            '*.description_3' => 'required',
            '*.video_1' => 'required',
            '*.video_2' => 'required',
            '*.video_3' => 'required',
            '*.product_name' => ['required', 'exists:products,name'],
            '*.product_id' => ['required', 'numeric', 'exists:products,id'],
        ])->validate();

        foreach ($rows as $row) {
            Project::create([

                'chapter_name' => $row['chapter_name'],
                'product_id' => $row['product_id']
                // ...
            ]);
        }
    }

    public function map($row): array
    {
        $mappedRow = $row;

        $mappedRow['product_id'] = (isset($row['product_name'])
            && ($product = Product::firstWhere('name', $row['product_name'])))
            ? $product->id
            : null;

        return $mappedRow;

        // From this point, your rules() and model() functions can access the 'product_id'
    }
}

Addendum 2

It appears that your second where clause in index method is lucking ( ProjectController ).

    // ...
    public function index()
    {
        // $projects = Project::where('user_id',auth()->user()->id)->latest()->paginate(20);
        $projects = Project::where('user_id',auth()->user()->id)->where('product_id')->latest()->paginate(20); ❌

        return view('projects.index', compact('projects'))
            ->with('i', (request()->input('page', 1) - 1) * 5);
    }
   // ...

A where clause requires at least 2 parameters . One 'product_id' parameter is passed for your case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM