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

Mike P's avatar

Using functions inside the Eloquent query in a clean way, help

Hello,

Help me clean up the code? Need to call the function which has to be written separately, not in the Eloquent query.

I need to make a transform on the pagination object (apparently it can be done with through() method) in order to get the preview text for my list of Posts with some clean-up to the source text.

What I want is to put the function name in the query, not the function itself.

How do I write it separately and how do I call this function from query? I'm a bit confused with using $this-> on collection elements

This is my code:


use App\Http\Controllers\Controller;
use App\Models\Platforms;
use App\Models\Post;
use Illuminate\Support\Str;

public function index () {

$items = Post::where('platform_id', 1)
     ->with('category')
     ->with('platform')
     ->paginate(20)
     ->through(function ($item, $shorty = '') {

       if (!empty($item->body)) {

         $shorty = $item->body;

       } elseif (!empty($item->body_short)) {

         $shorty = $item->body_short;

       }

       $healthy = array(PHP_EOL, '!', '.', '?', ':');
       $yummy   = array(" ", "! ", ". ", '?', ': ');

       $item->previewText = Str::words(
         strip_tags(
           str_replace($healthy, $yummy, $shorty)
         ), 
       35);        

       return $item;
     
     });

   return view('platforms.index', compact('items'));

 }

}

0 likes
11 replies
Mike P's avatar

@MichalOravec After some reading I've come up with the following code:


// Model

use Illuminate\Database\Eloquent\Casts\Attribute;

class Post extends Model
{

    public function manipulateSymbols($text) {

          $healthy = array(PHP_EOL, '!', '.', '?');
          $yummy   = array(" ", "! ", ". ", '? ');

            $text = str_replace($healthy, $yummy, $text);

          return $text;

    }

    protected function bodyShort(): Attribute {
        
        return Attribute::make(
            get: function ($value, $attributes) {

                if (!empty($attributes['body'])) {

                    $value = $this->manipulateSymbols($attributes['body']);

                } else if (!empty($attributes['body_short'])) {

                    $value = $this->manipulateSymbols($attributes['body_short']);

                }           

                return strip_tags($value)
                );

            }
        );
    }

}
// Controller
public function index () {

$items = Post::where('platform_id', 1)
     ->with('category')
     ->with('platform')
     ->paginate(20);
}

The only thing I can't understand is that I don't see the modified attribute value in the returned Model collection. Although it works

Mike P's avatar

@Sinnbeck as usual, in my blade file:

@foreach($items as $item)
...
{{ $item->body_short }}
...
@endforeach

I also double checked the situation by making protected function bodyTest(): Attribute { ... and iterating like

@foreach($items as $item)
...
{{ $item->body_test }}
...
@endforeach

I know I'm just second month into PHP and Laravel, maybe I do something wrong

Mike P's avatar

@MichalOravec I've spent 10 minutes on the topic page, trying to find how to mark the post solved. Seems impossible. Source code also doesn't show anything on that

Mike P's avatar

@MichalOravec Yeah, I see it now. Posted a note to the forum guide on that, it has a bit outdated info

Please or to participate in this conversation.