Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

simangae's avatar

Return Data from Database with vue

Hi, I have two tables that has one to one relationship, when I try to access data from 2nd table, I get the "TypeError: Cannot read property 'bio' of null" .

Here my controller

return User::with('profile')->latest()->get();

RelationShip

public function profile(){ return $this->hasOne('App\StudentInfo'); }

Axios

axios.get("api/user").then(({ data }) => (this.users = data));

Table

{{ user.name }} {{ user.email }} {{ user.phone }} {{ user.photo }} {{ user.profile.bio}} //This gives me error when I remove It's working fine
                   <td>
                       <a href="">
                            <i class="material-icons">mode_edit</i>
                       </a>
                       <a href="">
                            <i class="material-icons">delete</i>
                       </a>
                   </td>

               </tr>
0 likes
53 replies
tykus's avatar

Cannot read property 'bio' of null"

Clearly user.profile is null.

Your relationship assumes that there is a user_id foreign key on the table associated with the StudentInfo model, is this correct?

simangae's avatar

Yes There is a user_id foreign key.. If I access like this {{user.profile}} the profile object is showing with all it's properties however if I change it to {{user.profile.bio}} I get an error.

created_at: "2018-10-03 06:33:47"
email: "[email protected]"
email_verified_at: null
id: 11
name: "test 2"
phone: "0739764608"
photo: "user.png"
profile: {id: 1, user_id: 11, phone: null, dob: "21 July 1989", id_number: "928525554555", gender: "male",…}
type: "admin"
updated_at: "2018-10-03 06:33:47"



tykus's avatar

Can you wrap that output in triple backticks --- ``` on its own line before the content and closed on its own line after?

petritr's avatar

Looks like:

address: "2nd Street↵Hillside" bio: "Some info here" user_id: 13

this is not returned as json(in correct form), that's why you cant access it @simangae

simangae's avatar

Its Actually array like this

[{id: 13, name:"Joseph WhatNot"......}

profile{ address: address: "2nd Street", bio:"Some info here" user_id: 13}

]

petritr's avatar

@simangae you try to access it as it is was json, that's why it's not working. :)

D9705996's avatar

You can change

return User::with('profile')->latest()->get();

To

return User::with('profile')->latest()->first();

This will give you the newest user only.

If you need to show multiple users in you frontend you are going to have to loop through the JSON array that is returned to get each user in you html/blade/vue

marty12321's avatar

the response object has property data:

axios.get('api/user') .then(response => { console.log(response.data); this.users = response.data }) .catch(error => console.log(error.response))

in controller: $users = User::All();

    return response()->json($users, 200);
D9705996's avatar

Using @marty12321 axios code to put the users in your data object you can do this in your template

<ul>
  <li v-for="user in users" :key="user.id">
    {{ user.profile.bio }}
  </li>
</ul>

This will output each users bio in a list. Change the template to meet your needs

simangae's avatar

@marty12321 I'm still getting the same error.. User::all() does not return the profile $users = User::with('profile')->latest()->get();

my controller

        return response()->json($users, 200);


 axios.get("api/user").then(response =>{this.users = response.data
              }).catch(error => console.log(error.response));


Table

 <tr v-for="user in users" :key="user.id">
                       <td></td>
                      <td>{{ user.name }}</td>
                       <td>{{ user.email }}</td>
                       <td>{{ user.phone }}</td>
                       <td>{{ user.photo }}</td>
                       <td>{{ user.profile.bio}}</td>

                       <td>
                           <a href="">
                                <i class="material-icons">mode_edit</i>
                           </a>
                           <a href="">
                                <i class="material-icons">delete</i>
                           </a>
                       </td>

                   </tr>```
petritr's avatar

@simangae in the controller:

return response()->json(  User::all()->with('profile')->get() );

Then you can access it as you want to: {{ user.profile.bio}}, you can hear the rest as you had it before.

D9705996's avatar

Can you share a formatted content of the output of

.then(response => {
  console.log(response.data);
}
D9705996's avatar

@petritr - Your suggestion won't change the response as axios will make a JSON request so larvael will return JSON by default and also misses the latest ordering of the question

return response()->json(  User::all()->with('profile')->latest()->get() );

is equivalent to

return User::with('profile')->latest()->get();

We really need to see the data axios is returning to identify the issue

petritr's avatar

@D9705996 i just find more visual and easy to read when i do it as i did.

return response()->json( User::with('profile')->get() );

simangae's avatar

@D9705996

The output in the console

created_at: "2018-10-03 06:44:50"
email: "[email protected]"
email_verified_at: (...)
id: 13
name: "Joseph WhatNot"
phone: "0834602415"
photo: "user.png"
   profile: Object
   address: "2nd Street↵Hillside"
   bio: "Some info here"
   course: (...)
    created_at: "2018-10-03 06:44:50"
    dob: "21 feb 2000"
    gender: "male"
    id: 2
    id_number: "93444245556"
    phone: null
    updated_at: "2018-10-03 06:44:50"
    user_id: 13
simangae's avatar

@petritr return response()->json(User::all()->with('profile')->get());

Returns "Method Illuminate\Database\Eloquent\Collection::with does not exist.",…}

But when I change it to return response()->json(User::with('profile')->get());

it's working but I stilll can't access profile props

D9705996's avatar

@simangae - Sorry to be a pain the console.log didnt really help as it lost the structure. Can you change console.log to

console.log(JSON.stringify(data));

Make sure you include the full content from the console.log, including any brackets.

I would also keep your return User::with('profile')->latest()->get();. I don't think this is the issue as your backend doesn't look like the problem

petritr's avatar

@simangae what happens when you the following?

<tr v-for="user in users)">
      <td>{{ user.name }}</td>
      <td>{{ user.profile.bio}}</td>
</tr>

@simangae check now

simangae's avatar

@D9705996

[{"id":13,"name":"Joseph WhatNot","email":"[email protected]","email_verified_at":null,"phone":"0834602415","type":"admin","photo":"user.png","created_at":"2018-10-03 06:44:50","updated_at":"2018-10-03 06:44:50","profile":{"id":2,"user_id":13,"phone":null,"dob":"21 feb 2000","id_number":"93444245556","gender":"male","course":"MCA","address":"2nd Street\nHillside","bio":"Some info here","created_at":"2018-10-03 06:44:50","updated_at":"2018-10-03 06:44:50"}}]

petritr's avatar

@simangae what happens when you do this:

<table class="table dashboard">
<tr v-for="user in users)">
      <td>{{ user.name }}</td>
      <td>{{ user.profile.bio}}</td>
</tr>
</table>
petritr's avatar

@simangae can you past all the vue component code here ? This must work, maybe you have another error too.

D9705996's avatar

@simangae - Thank you for the data it really helps. I confirms you are getting an array of users back from the API

Below shows that HTML and VueJS code that should work

<tr v-for="user in users" :key="user.id">
  <td></td>
  <td>{{ user.name }}</td>
  <td>{{ user.email }}</td>
  <td>{{ user.phone }}</td>
  <td>{{ user.photo }}</td>
  <td>{{ user.profile.bio}}</td>
  <td>
    <a href="">
      <i class="material-icons">mode_edit</i>
    </a>
    <a href="">
      <i class="material-icons">delete</i>
     </a>
  </td>
</tr>

new Vue({
  el: '#app',
  data () {
    return {
      users: []
    }
  },
  mounted () {
    axios
      .get('/api/user')
      .then(response => (this.users = response.data))
  }
});
petritr's avatar
petritr
Best Answer
Level 15

@simangae try this:

<template>
    <div class="table-responsive">

        <table class="table dashboard">
            <tr v-for="user in users">
                <td>{{ user.name }}</td>
                <td>{{ user.profile.bio }}</td>
            </tr>
        </table>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                users: [],
            }
        },
        methods: {

            read() {
                axios.get('/api/users').then(({ data }) => {
                    //console.log(data)
                    this.users= data;

                })
                    .catch((err) => console.error(err));
            },
        },
        mounted() {
            this.read();
        }
    }
</script>
1 like
petritr's avatar

@D9705996 ha :) Yes your example will work too, my is a bit cleaner/best practice again :)

Next

Please or to participate in this conversation.