i have this route:
web.php:
Route::get('main',[HomePageController::class,'show']);
that pass this function:
HomePageController.php
class HomePageController extends Controller
{
function show()
{
$data = Classes::all();
return view('index',['classes'=>$data]);
}
}
and i want to pass another function in the same route but i keep getting "Undefined variable"
whenever i try to do this:
web.php
Route::get('main',[HomePageController::class,'show']);
Route::get('main',[HomePageController::class,'showfeeds']);
HomePageController.php
class HomePageController extends Controller
{
function show()
{
$data = Classes::all();
return view('index',['classes'=>$data]);
}
function showfeeds()
{
$data = Feeds::all();
return view('index',['feeds'=>$data]);
}
}
what am i doing wrong here?
You could use single route but send Classes and Feeds to single view (as you intended):
Route:
Route::get('main',[HomePageController::class,'show']);
Controller:
class HomePageController extends Controller
{
function show()
{
$classes = Classes::all();
$feeds = Feeds::all();
return view('index', compact('classes', 'feeds'));
}
}
Related
I'm new to laravel and to php oop. My main goal is to call createLogs() everytime a function is called without putting the call method in each function because it's a hassle. I need help please.
I made a controller called WebLogs with a function called createLogs() that inserts data to a table. I want it to be auto-called whenever another function is called. I tried using this solution and put it in Controller class because WebLogs extends Controller class, and all my other controllers extends Controller class, but the solution doesn't seem to work.
So my Controller class now looks like this:
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
// Added this function from the solution I mentioned
public function __call($method, $arguments) {
echo 'hello world';
echo '<br><br>';
echo $method;
if(method_exists($this, $method)) {
return call_user_func_array(array($this,$method),$arguments);
}
}
}
Example controller:
class DashboardController extends Controller
{
public function index()
{
(new WebLogs)->createLogs(); //I don't want to call this for every function
return view('dashboard');
}
public function showSomething()
{
(new WebLogs)->createLogs();
return view('something');
}
public function updateSomething()
{
(new WebLogs)->createLogs();
return redirect()->back()->with('message','yeey');
}
}
How the functions from DashboardController are being called from web.php:
Route::get('/', [DashboardController::class, 'index'])->name('dashboard');
Route::get('/something', [DashboardController::class, 'showSomething'])->name('something');
Route::post('/something/update', [DashboardController::class, 'updateSomething'])->name('something.update');
Create app\Classes\WebLogs.php with content:
<?php
namespace App\Classes;
class WebLogs {
public function __construct() {
return "WebLogs class with construct function was initialized.";
}
public function createLogs($routeName,$routePath) {
$status = 0;
logger('WebLogs class is running:');
logger([$routeName,$routePath]);
// Save to database here
// ...
return $status;
}
}
Then, create an AutoCreateLogs middleware, it will save as app\Http\Middleware\AutoCreateLogs.php:
$ php artisan make:middleware AutoCreateLogs
With content:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Classes\WebLogs;
class AutoCreateLogs
{
public function handle(Request $request, Closure $next)
{
$route = Route::current();
$routePath = $route->uri;
$routeName = $route->action['as'];
$w = new WebLogs;
$w->createLogs($routeName,$routePath);
return $next($request);
}
}
And use this middleware like this:
Route::middleware([AutoCreateLogs::class])->group(function () {
Route::get('/', [App\Http\Controllers\DashboardController::class, 'index'])->name('dashboard');
Route::get('/something', [App\Http\Controllers\DashboardController::class, 'showSomething'])->name('something');
Route::post('/something/update', [App\Http\Controllers\DashboardController::class, 'updateSomething'])->name('something.update');
Route::get('/something/{value}', [App\Http\Controllers\DashboardController::class, 'getSomething'])->name('get.something');
});
With app\Http\Controllers\DashboardController.php:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class DashboardController extends Controller
{
public function index()
{
$page = 'index';
return view('welcome', ['page'=>$page]);
}
public function showSomething()
{
$page = 'showSomething';
return view('welcome', ['page'=>$page]);
}
public function updateSomething()
{
$page = 'updateSomething';
return response()->json(['page'=>$page]);
}
public function getSomething(Request $request)
{
$page = 'getSomething';
return view('welcome', ['page'=>$page]);
}
}
Then, empty storage\logs\laravel.log, and run with example route
http://laravel-me.com/something/value99
It will show the successful result:
[2022-02-18 22:56:09] local.DEBUG: WebLogs class is running:
[2022-02-18 22:56:09] local.DEBUG: array (
0 => 'get.something',
1 => 'something/{value}',
)
Read more about middleware: https://laravel.com/docs/8.x/middleware
I'm trying to concatenate two class spesific variables in controller and pass it to all views without repeating the same variable in every controller methods.
Example code:
class ProductsController extends Controller
{
private $global_path; //Comes from .env
private $sub_folder = '/products_folder';
public function __construct()
{
//Frontend Image Path - to pass into all views
$frontend_path = $this->global_path.$this->sub_folder;
}
}
I want to pass '$frontend_path' to all blade views created in the controller without repeating it in every single method like
return view('example_view', compact('frontend_path');
I tried View::share... but couldn't do it.
The '$sub_folder' variable doesn't have the same value in all controllers.
Is there a way to make it possible?
For your code, I think you can change it to
class ProductsController extends Controller
{
public $frontend_path;
public function __construct() {
$this->frontend_path = env('GLOBAL_PATH') . '/products_folder';
}
public function index()
{
$x = $this->frontend_path;
return view('index', compact('x'));
}
}
and directly use it like $this->frontend_path or like below SELF::$frontend_path
class ProductsController extends Controller
{
public static $frontend_path;
public function __construct() {
SELF::$frontend_path = env('GLOBAL_PATH') . '/products_folder';
}
public function index()
{
$x = SELF::$frontend_path;
return view('index', compact('x'));
}
}
or
class ProductsController extends Controller
{
public static $frontend_path;
public function __construct() {
SELF::$frontend_path = env('GLOBAL_PATH') . '/products_folder';
view()->share('frontend_path', SELF::$frontend_path);
}
public function index()
{
return view('index');
}
}
in view
{{ $frontend_path }}
I have a question about Laravel.
I have by example index.blade.php. In this file I want include the sidebar who is located on the file sidebar.blade.php.
But now I want to send a variable from my controller(SidebarController) to the sidebar view: sidebar.blade.php.
Like this:
class SidebarController extends Controller
{
public function news_widget() {
$posts = Post::take(5)->orderBy('updated_at', 'DESC')->take();
}
}
How can I do that?
You can use following
class SidebarController extends Controller
{
public function news_widget() {
$posts = Post::take(5)->orderBy('updated_at', 'DESC')->take();
return view('index', array('data'=>$posts));
}
}
And within index.blade.php include sidebar.blade.php
#include('sidebar',$data)
Try this
class SidebarController extends Controller
{
public function news_widget() {
$posts = Post::take(5)->orderBy('updated_at', 'DESC')->take();
return View::make('sidebar')->with('posts', $posts);
}
}
In web.php I have this route which opens a form:
$this->namespace('Users')->prefix('users')->group(function (){
$this->get('/create' , 'UserController#create');
});
And this route returns an array of countries. I use that array to fill a select box via ajax in the form.
Route::namespace('API')->prefix('api')->group(function () {
$this->get('/get-country-list', 'LocationsController#index');
});
Controller:
app\Http\Controllers\API\LocationsController
class LocationsController extends Controller
{
public function index()
{
return DB::table('countries')->pluck("name","id")->all();
}
...
app\Http\Controllers\Users\UserController
class UserController extends Controller
{
public function create()
{
return view('panel.users.home.create.show');
}
...
How can I call LocationsController#index in create() function?
what is the best method?
you can try return redirect(route('...')); instead of return view() in actions.
update
Because you just want to get Countries list instead of redirection. So do small tuning, separate the data manipulating function from the action function:
protected function getCountries() {
return DB::table('countries')->pluck("name","id")->all();
}
function index(Request $request) {
return $this->getCountries();
}
function create(Request $request) {
$countries = $this->getCountries();
return view('panel.users.home.create.show', compact('countries'));
}
I think you should try a different approach. What you seem to be trying to do is reuse this cumbersome query:
DB::table('countries')->pluck('name', 'id')->all();
That's good! However your index() function is a controller endpoint and which returns a response and isn't really suitable for being reused in other controller endpoints. When I am in a similar situation I usually do one of two things,
1. Extract the code to a protected method and use it in both controller endpoint methods
class UserController extends Controller
{
public function index()
{
return $this->countryNames();
}
public function create()
{
// $countryNames = $this->countryNames():
return view('panel.users.home.create.show');
}
public function countryNames()
{
return DB::table('countries')->pluck('name', 'id')->all();
}
}
2. Create a method on the model, in your case this would involve using the model instead of the DB facade.
class UserController extends Controller
{
public function index()
{
return Country::names();
}
public function create()
{
// $countryNames = Country::names();
return view('panel.users.home.create.show');
}
}
I have this route: Route::controller('/', 'PearsController'); Is it possible in Laravel to get the PearsController to load a method from another controller so the URL doesn't change?
For example:
// route:
Route::controller('/', 'PearsController');
// controllers
class PearsController extends BaseController {
public function getAbc() {
// How do I load ApplesController#getSomething so I can split up
// my methods without changing the url? (retains domain.com/abc)
}
}
class ApplesController extends BaseController {
public function getSomething() {
echo 'It works!'
}
}
You can use (L3 only)
Controller::call('ApplesController#getSomething');
In L4 you can use
$request = Request::create('/apples', 'GET', array());
return Route::dispatch($request)->getContent();
In this case, you have to define a route for ApplesController, something like this
Route::get('/apples', 'ApplesController#getSomething'); // in routes.php
In the array() you can pass arguments if required.
( by neto in Call a controller in Laravel 4 )
Use IoC...
App::make($controller)->{$action}();
Eg:
App::make('HomeController')->getIndex();
and you may also give params
App::make('HomeController')->getIndex($params);
You should not. In MVC, controllers should not 'talk' to each other, if they have to share 'data' they should do it using a model, wich is the type of class responsible for data sharing in your app. Look:
// route:
Route::controller('/', 'PearsController');
// controllers
class PearsController extends BaseController {
public function getAbc()
{
$something = new MySomethingModel;
$this->commonFunction();
echo $something->getSomething();
}
}
class ApplesController extends BaseController {
public function showSomething()
{
$something = new MySomethingModel;
$this->commonFunction();
echo $something->getSomething();
}
}
class MySomethingModel {
public function getSomething()
{
return 'It works!';
}
}
EDIT
What you can do instead is to use BaseController to create common functions to be shared by all your controllers. Take a look at commonFunction in BaseController and how it's used in the two controllers.
abstract class BaseController extends Controller {
public function commonFunction()
{
// will do common things
}
}
class PearsController extends BaseController {
public function getAbc()
{
return $this->commonFunction();
}
}
class ApplesController extends BaseController {
public function showSomething()
{
return $this->commonFunction();
}
}
if you were in AbcdController and trying to access method public function test() which exists in OtherController you could just do:
$getTests = (new OtherController)->test();
This should work in L5.1