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

mhmmdva's avatar

Method Illuminate\Database\Eloquent\Collection::getPercentage does not exist.

so I want to retrieve the largest percentage of all daily record data according to proposal_id, but I can only return 1 data like this:

class Logbook extends Model
{
    use HasFactory;

    protected $guarded = ['id'];
    protected $dates = ['date'];
    const LOGBOOK_PATH = 'public/data/logbooks';
    public function user()
    {
        return $this->belongsTo(User::class);
    }
    public function proposal()
    {
        return $this->belongsTo(Proposal::class);
    }

    public function getPercentage()
    {
        return Logbook::where('proposal_id', 1)->orderByDesc('percentage')->limit(1)->get(); // 
    }
}

logbook.migration

class CreateLogbooksTable extends Migration
{
 
    public function up()
    {
        Schema::create('logbooks', function (Blueprint $table) {
            $table->id();
            // relational
            $table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
            $table->foreignId('proposal_id')->constrained('proposals')->cascadeOnDelete();

            // detail
            $table->date('date')->nullable();
            $table->text('activity');
            $table->integer('percentage');
            $table->text('file')->nullable();
            
            $table->timestamps();
        });
    }
}

ProposalController

class ProposalController extends Controller
{
    

    public function index()
    {
        $this->authorize('isLecturer', auth()->user()); 

        return view('admin.lecturers.proposals.index', [
            'proposals' => Proposal::where('user_id', '=', Auth::user()->id)->get(),
        ]);
    }
}

views.blade.php

 <tbody>
     @forelse ($proposals as $proposal)
         <tr>
             <td>
                 <a href="javascript: void(0);" class="text-dark font-weight-bold">{{ $loop->iteration }}</a>
             </td>
             <td> {{ Str::limit($proposal->schema, 30, '...') }}</td>
             <td> {{ $proposal->created_at->format('Y') }}</td>
             <td> {{ Str::limit($proposal->title, 50, '...') }} </td>
             <td> {{ currency_IDR($proposal->total_budget) }}</td>
             <td>
                 <br> total records : {{ $proposal->logbook->count() }} <br>
                   percentage : {!! $proposal->logbook->getPercentage() !!} // example data : 80%
             </td>
             <td>
                 <div>
                     @can('isLecturer', auth()->user())
                         <a href="{{ route('lpp.proposal.edit', $proposal->slug) }}" class="btn btn-warning">
                             <i class="mdi mdi-pencil"></i>
                         </a>
                         <a href="{{ route('lpp.proposal.logbook.index', $proposal->slug) }}" class="btn btn-primary">
                             <i class="mdi mdi-history"></i>
                         </a>
                     @endcan
                 </div>
             </td>
         </tr>                
     @empty
         <tr>
             <td colspan="8" class="text-center">data is empty</td>
         </tr>
     @endforelse
 </tbody>

0 likes
8 replies
tisuchi's avatar

@mhmmdva It seems that you are not utilizing your relationships properly. I suggest you use relationship and find the related data instead of re-query.

For example, inside the Logbook class, you try to re-query again which is unnecessary.


    public function getPercentage()
    {
        return Logbook::where('proposal_id', 1)->orderByDesc('percentage')->limit(1)->get(); // 
    }
tisuchi's avatar

@mhmmdva Untested, but this might help you to solve the issue:

// In Proposal.php model
public function highestPercentageLogbook()
{
    return $this->hasOne(Logbook::class)->orderByDesc('percentage');
}
// In ProposalController.php
public function index()
{
    $this->authorize('isLecturer', auth()->user()); 

    return view('admin.lecturers.proposals.index', [
        'proposals' => Proposal::where('user_id', '=', Auth::user()->id)
                               ->with('highestPercentageLogbook')
                               ->get(),
    ]);
}
1 like
mhmmdva's avatar

@tisuchi

I've used it but it's erroring :

Object of class Illuminate\Database\Eloquent\Relations\HasOne could not be converted to string
mhmmdva's avatar

inside view returns like this

3 percentage : {"id":4,"user_id":2,"proposal_id":1,"date":"2023-10-13T17:00:00.000000Z","activity":"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Autem error dolore modi tempora maxime qui suscipit eos odit reiciendis doloremque.","percentage":60,"file":"public\/data\/logbooks\/file_path_101023024101.pdf","created_at":"2023-10-10T07:41:02.000000Z","updated_at":"2023-10-10T07:41:02.000000Z"}
tangtang's avatar
tangtang
Best Answer
Level 6

@mhmmdva may you try this for reference

// In Proposal.php model
public function highestPercentageLogbook()
{
    return $this->hasOne(Logbook::class)->orderByDesc('percentage');
}

public function getHighestLogbookPercentageAttribute()
{
    if ($this->highestPercentageLogbook) {
        return $this->highestPercentageLogbook->percentage;
    }

    return 0; // You can change this to your desired default value.
}

// In ProposalController.php
use Illuminate\Database\Eloquent\ModelNotFoundException;

public function index()
{
    $this->authorize('isLecturer', auth()->user()); 

    $proposals = Proposal::where('user_id', '=', Auth::user()->id)
        ->with(['highestPercentageLogbook' => function($query) {
            $query->orderByDesc('percentage');
        }])
        ->get();

    foreach ($proposals as $proposal) {
        $proposal->highestPercentageLogbook = $proposal->highestPercentageLogbook->first();
    }

    return view('admin.lecturers.proposals.index', [
        'proposals' => $proposals,
    ]);
}

// in blade
@foreach ($proposals as $proposal)
    @if ($proposal->highestPercentageLogbook)
        Percentage: {{ $proposal->highestPercentageLogbook->percentage }}
    @else
        No logbook found for this proposal.
    @endif
@endforeach

mhmmdva's avatar

@tangtang Call to a member function get() on null

 foreach ($proposals as $proposal) {
        $proposal->highestPercentageLogbook = $proposal->highestPercentageLogbook->first(); // error 
    }

why should we using this?

tangtang's avatar

@mhmmdva ah, I forgot to check that line, try to add this

foreach ($proposals as $proposal) {
        $highestLogbook = $proposal->highestPercentageLogbook; // this is the update line

        if ($highestLogbook) {
            $proposal->highestPercentageLogbook = $highestLogbook->first(); // change this code a bit
        }
    }
mhmmdva's avatar

@tangtang

like this is enough, because each logbook has a different proposal

$proposals = Proposal::where('user_id', '=', Auth::user()->id)
        ->with(['highestPercentageLogbook' => function ($query) {
            $query->orderByDesc('percentage');
        }])->get();

Please or to participate in this conversation.