Reputation: 6062
I recently dove into the world of laravel (version 5.4). While initially confused, the concept of MVC makes a lot of sense in writing large applications. Applications that you want to be easily understood by outside developers.
Using laravel for this has greatly simplified coding in PHP and has made the language fun again. However, beyond dividing code into its respective models, views, and controllers, what happens if we need to divide controllers to prevent them from growing too large?
A solution that I have found to this is to define one controller each folder and then fill that controller with traits that further add functionalities to the controller. (All-caps = folder):
CONTROLLER
HOME
Controller.php
TRAITS
additionalFunctionality1.php
additionalFunctionality2.php
additionalFunctionality3.php
...
ADMIN
Controller.php
TRAITS
additionalFunctionality1.php
additionalFunctionality2.php
additionalFunctionality3.php
...
Within routes/web.php
I woud initialize everything as so:
Route::namespace('Home')->group(function () {
Route::get('home', 'Controller.php@loadPage');
Route::post('test', 'Controller.php@fun1');
Route::post('test2', 'Controller.php@fun2');
Route::post('test3', 'Controller.php@fun3');
});
Route::namespace('Admin')->group(function () {
Route::get('Admin', 'Controller.php@loadPage');
Route::post('test', 'Controller.php@fun1');
Route::post('test2', 'Controller.php@fun2');
Route::post('test3', 'Controller.php@fun3');
});
With me being new to laravel, this seems like a simple and elegant way to organize my logic. It is however something I do not see while researching laravel controller organization.
The Question
Is there an issue, both in the short-run and in the long-run, of organizing my data like this? What is a better alternative?
Example Controller:
<?php
namespace App\Http\Controllers\Message;
use DB;
use Auth;
use Request;
use FileHelper;
use App\Http\Controllers\Message\Traits\MessageTypes;
use App\Http\Controllers\Controller;
class MessageController extends Controller
{
// Traits that are used within the message controller
use FileHelper, MessageTypes;
/**
* @var array $data Everything about the message is stored here
*/
protected $data = []; // everything about the message
/**
* @var booloean/array $sendableData Additional data that is registered through the send function
*/
protected $sendableData = false;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('access');
}
/**
* Enable sendableData by passing data to the variable
*
* @param array $data Addition data that needs to registrered
* @return MessageController
*/
protected function send ($data = []) {
// enable sendableData by passing data to the variable
$this->sendableData = $data;
return $this;
}
/**
* Enable sendableData by passing data to the variable
*
* @param string $type The type of message that we will serve to the view
* @return MessageController
*/
protected function serve ($type = "message") {
$this->ss();
$this->setData(array_merge($this->sendableData, $this->status[$type]));
$this->data->id = DB::table('messages')->insertGetId((array) $this->data);
}
/**
* Set the data of the message to be used to send or construct a message
* Note that this function turns "(array) $data" into "(object) $data"
*
* @param array $extend Override default settings
* @return MessageController
*/
protected function setData(array $extend = []) {
$defaults = [
"lobby" => Request::get('lobbyid'),
"type" => "text",
"subtype" => null,
"body" => null,
"time" => date("g:ia"),
"user" => Auth::User()->username,
"userid" => Auth::User()->id,
"day" => date("j"),
"month" => date("M"),
"timestamp" => time(),
"private" => Request::get('isPrivate') ? "1" : "0",
"name" => Request::get('displayname'),
"kicker" => null
];
$this->data = (object) array_merge($defaults, $extend);
// because a closure can not be saved in the database we will remove it after we need it
unset($this->data->message);
return $this;
}
/**
* Send out a response for PHP
*
* @return string
*/
public function build() {
if($this->data->type == "file") {
$filesize = @filesize("uploads/" . $this->data->lobby . "/" . $this->data->body);
$this->data->filesize = $this->human_filesize($filesize, 2);
}
// do not send unneccessary data
unset($this->data->body, $this->data->time, $this->data->kicker, $this->data->name, $this->data->timestamp);
return $this->data;
}
/**
* Send out a usable response for an AJAX request
*
* @return object
*/
public function json() {
return json_encode($this->build());
}
}
?>
Upvotes: 3
Views: 2703
Reputation: 15971
Laravel architecture is simple enough for any size of the application.
Laravel provides several mechanisms for developers to tackle the fatty controllers in your Application.
Middlewares
for authentications. Requests
for validations and manipulating data.Policy
for your aplication roles.Repository
for writing your database queries.Transformers
for your APIs
to transform data.It depends on your application. if it is too large and have different Modules or functionalities then you should use a modular approach. A nice package is available for making independent modules here
Hope this helps.
Upvotes: 3
Reputation: 278
I think you should do a little differently ! First you should use your traits at the same levels as the controllers since traits are not controllers, your tree should look more like :
Http
Controller
Controller.php
Home
YourControllers
Admin
Your admin controllers
Traits
Your Traits
Next your routes need to be more like that :
Route::group(['prefix' => 'home'], function()
{
Route::get('/', 'Home\YourController@index')->name('home.index');
}
Route::group(['prefix' => 'admin', 'middleware' => ['admin']], function()
{
Route::get('/', 'Admin\DashboardController@index')->name('dashboard.index');
}
You can use many kink or routes like :
Route::post('/action', 'yourControllers@store')->name('controller.store');
Route::patch('/action', 'yourControllers@update')->name('controller.update');
Route::resource('/action', 'yourController');
The Resource route creates automatically the most used your, like post, patch, edit, index.. You just need to write the action and the controller called with its action. You can check out your toutes with this command : php artisan route:list
Laravel also has many automated features, like the creation of a controller with this command : php artisan make:controller YourController.
For the routes the prefix creates portions of url, for example all the routes inside the route group with the prefix 'admin' will lool like : www.yourwebsite.com/admin/theroute, and can also be blocked for some users with a middleware.
To get familiar with laravel i suggest you follow the laravel 5.4 tutorial from scratch by Jeffrey Way on Laracasts, he's awesome at explaining and showing how laravel works. Here is a link : https://laracasts.com/series/laravel-from-scratch-2017
Hope it helps, ask me if you want to know anything else or have some precisions, i'll try to answer you !
Upvotes: 0