RomainB's avatar
Level 13

How to clarify my controller code. Controller without Model.

Hi.

I've got a controller to manage endpoint for uploading image from TinyMCE.

For now its just two functions: store and index.

Index return a json list of images contained in the img folder:

    public function index()
    {
        $dir = public_path('img/posts/');
        $list_uploaded_img = [];
        if(is_dir($dir)){
            if($open = opendir($dir)){
                while (($file = readdir($open)) !== false){
                    $img_path = $dir.$file;
                    if(is_file($img_path)){
                        $name = pathinfo($file, PATHINFO_FILENAME);
                        $list_uploaded_img[] = ['title' => $name, 'value' => asset('img/posts/'.$file)];
                    }
                }
                closedir($open);
            } else {
                return response("500: Can't open folder", 500);
            }
        } else {
                return response("500: It's not a folder, or it doesn't exist", 500);
        }  
        return response()->json($list_uploaded_img);
    }

The function will grow up to handle subdirectories, filter image-only files, and so on... I want to clarify the controller to something like that:

    public function index()
    {
        return getListOfImage('dir');
    }

Image is not an Eloquent Model so I can't just add function to it. What is the best place to paste my getListOfImage function and how to include it in my Controller?

0 likes
2 replies
bobbybouwmann's avatar
Level 88

I would probably create a separated service class that does all of this for me. So something like this

// controller
public function __construct(ImageServices $imageService)
{
    $this->imageService = $imageService;
}

public function index()
{
    $images = $this->imageService->getListOfImages('dir');

    // return response
}

Then you can have a class in the app/Services directory for example that will handle all this logic. You can also put the storing and so on in that class. This way your controllers are still clean ;)

RomainB's avatar
Level 13

Thanks for the advice.

I've never used Services or Service Provider until now.

So my next question is: what the architecture to have?

I viewed the Jeffrey Way course on Service Provider and read the documentation. About Service Provider they say: Within the register method, you should only bind things into the service container

So my ImageService Class should be in Service folder and a ImageServiceProvider should bind this class?

I'm pretty confused about Services and Services Providers...

[EDIT] For now I just created a ImageService, without Provider bindings:

<?php
namespace App\Services;

class UploadFileService
{
    public function getListOfFiles($dir, $format = 'TinyMCE', $with_extensions = 'ALL')
    {
        $list_uploaded_files = [];
        if(is_dir($dir)){
            if($open = opendir($dir)){
                while (($file = readdir($open)) !== false){
                    $img_path = $dir.$file;
                    if(is_file($img_path)){
                        $name = pathinfo($file, PATHINFO_FILENAME);
                        $list_uploaded_files[] = ['title' => $name, 'value' => asset('img/posts/'.$file)];
                    }
                }
                closedir($open);
            } else {
                return response("500: Can't open folder", 500);
            }
        } else {
                return response("500: It's not a folder, or it doesn't exist", 500);
        }
        return response()->json($list_uploaded_files);
    }

    public function storeFile($file)
    {
        $name = $file->getClientOriginalName();
        $extension = $file->getClientOriginalExtension();
        $dir = public_path().'\img\posts\';
        $file->move($dir, $name);
        
        return asset('img/posts/'.$name);
    }
}

And Laravel resolves in my controller:

<?php

namespace App\Http\Controllers\AdminZone;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Services\UploadFileService;

class StoredFileController extends Controller
{
    public function __construct(UploadFileService $UploadFileService)
    {
        $this->middleware('auth');
        $this->UploadFileService = $UploadFileService;
    }
    
    public function index()
    {
        $images = $this->UploadFileService->getListOfFiles(public_path('img/posts/'));

        return $images;
    }

    public function store(Request $request) 
    {
        $uploaded_image_path = $this->UploadFileService->storeFile($request->file('file'));
        
        return response()->json(['location' => $uploaded_image_path]);
    }

For basic Service, I guess it's sufficient

Please or to participate in this conversation.