Andrew
Andrew

Reputation: 1833

"Call to a member function store() on array" When Uploading a File using Laravel 8 with Jetstream - Vue & Intertia.js

I am having a problem uploading an image from a from a form in a vue file. I tried several ways to do this but it seems the file is not properly being set.

I receive data in my controller and try to store the file:

public function update(Request $request, $id) {

dd($request->all());

$this->validate($request, [
    'title' => ['required'],
    'dateofpd' => ['required'],
    'lengthofpd' => ['required'],
    'location' => ['required']
]);

$path = $request->file('filename')->store('uploads');

$pditem = ProfessionalDevelopmentItem::find($id);
$pditem->domain = $request->domain;
$pditem->domaincategory = $request->domaincategory;
$pditem->title = $request->title;
$pditem->dateofpd = $request->dateofpd;
$pditem->lengthofpd = $request->lengthofpd;
$pditem->location = $request->location;
$pditem->facilitatorname = $request->facilitatorname;
$pditem->facilitatorcredentials = $request->facilitatorcredentials;
$pditem->certificategranted = $request->certificategranted;
$pditem->certificateexpires = $request->certificateexpires;
$pditem->certificateexpiration = $request->certificateexpiration;
$pditem->reflection = $request->reflection;
$pditem->nameofinstitution = $request->nameofinstitution;
$pditem->coursename = $request->coursename;
$pditem->coursecode = $request->coursecode;
$pditem->hoursofinstruction = $request->hoursofinstruction;
$pditem->creditgranted = $request->creditgranted;
$pditem->bookname = $request->bookname;
$pditem->bookauthor = $request->bookauthor;
$pditem->bookyear = $request->bookyear;
$pditem->bookpublisher = $request->bookpublisher;
$pditem->otherdescription = $request->otherdescription;
$pditem->filename = $path;

$pditem->save();

return response('Successfully Updated the Professional Development Item.', 200);

}

the response back is an error on the line when it tries to store the file:

"message": "Call to a member function store() on array",
"exception": "Error",

Any thoughts on what I am dong wrong would be appreciated.

Upvotes: 1

Views: 4104

Answers (2)

yesnik
yesnik

Reputation: 4695

This error means that $request->file('filename') returns array. In our case it's because we allowed users to submit 2 files at once:

<form action="/upload" method="post" enctype="multipart/form-data">
    @csrf
    <input type="file" name="filename[]"><br>
    <input type="file" name="filename[]"><br>
    <input type="submit">
</form>

To fix this in Laravel 9 we added the type check of the variable in the controller's method:

public function upload(Request $request)
{
    $file = $request->file('filename');

    if (is_array($file)) {
        foreach ($file as $item) {
            $item->store('uploads');
        }
    } else {
        $file->store('uploads');
    }

    // ...
}

Upvotes: 0

Donkarnash
Donkarnash

Reputation: 12845

Try sending the uploaded file within FormData. Define a method in the Vue component to prepare the FormData with all data you want to send via ajax to the server

prepareFormData() {
    let data = new FormData;

    Object.keys(this.professionaldevelopmentitem).forEach(
        key => data.append(key, this.professionaldevelopmentitem[key]
    );

    return data;
}

Then use this method to get the FormData and send it as data to the server in addProfessionalDeveloomentItem and updataProfessionalDevelopmentItems

async addProfessionalDevelopmentItem() {
    document.getElementById("pdForm").reset();
    this.editMode = false;
    const res = await axios.post(
      "/api/professionaldevelopmentitems",
      this.prepareFormData()
    );

    if (res.status === 201) {
      Toast.fire({
        icon: "success",
        title: res.data,
      });
      document.getElementById("pdForm").reset();
      $("#manageProfessionalDevelopmentItem").modal("hide");
      Fire.$emit("modifiedPDItem");
    }
  },
  

  async updateProfessionalDevelopmentItems(data) {
    const res = await axios.put(
      `/api/professionaldevelopmentitems/${data.id}`,
      this.prepareFormData()
    );

    if (res.status === 200) {
      Toast.fire({
        icon: "success",
        title: res.data,
      });
      document.getElementById("pdForm").reset();
      $("#manageProfessionalDevelopmentItem").modal("hide");
      Fire.$emit("modifiedPDItem");
      this.editMode = false;
    }
}

Then you should get the uploaded file in the $request under key file $request->file('file')

Upvotes: 1

Related Questions