laravel routes and controller view architecture - php

I am working with Laravel for a new project, and I am wanting to setup a new URL,
/project/create
I thought this would be as easy as doing the following,
<?php
class Project_Controller extends Base_Controller {
public function action_create()
{
return "Step 1";
}
}
However this returns a 404, can you not just setup an url base on /controller/action is this not the case, will I have to do this,
Route::get('/project/create', function()
{
return View::make('project.index');
});
or similar for every URL/request the site needs?

You can do controller routing.
Option 1:
// Register a specific controller
Route::controller('project');
Option 2 (not recommended in Laravel 3 as known to be buggy sometimes):
// Register all controllers and all routes
Route::controller(Controller::detect());
You can see more options about routing and controller routing here

Related

How to configure symfony to work with Vue.js in HTML5 History mode

I have followed the tutorial on how to integrate Vue into Symfony (3.3), and it's working just fine.
I'd like to however use vue-router in HTML5 History mode, so with "real" urls instead of hashes. The problem is while that works well when initially loading the index page, that it won't work to open a page with a Vue URL that symfony doesn't know, cause symfony will throw a 404 error and not load the index view with the Vue app.
I'd like to only use symfony for specific route prefixes, like /blog, /api, and for all other routes load the index route that does nothing but load the vue app, but I don't really know where to start.
I assume I either have to change the .htaccess (currently using the exact one that came with the symfony installation) or somehow "catch" routes symfony doesn't know and redirect to the index page - however I'm stuck here since I'd want routes that are not found within the range of the few route prefixes I want symfony to use to still throw a 404 error.
For those who prefer using annotations [Symfony 3.x, 4.x]
You could use the following Routing in Symfony.
class DefaultController extends Controller
{
/**
* #Route("/", name="homepage")
* #Route("/{route}", name="vue_pages", requirements={"route"=".+"})
*/
public function indexAction(Request $request)
{
return $this->render('default/index.html.twig', []);
}
}
And In VueJS, you can Vue-Router to display a 404 page for routes not found via a wildcard as shown below,
import '...'; // import required components
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'homepage',
component: home
},
{
path: '/hello',
name: 'hello',
component: hello
},
{
path: '*', // wildcard
name: 'notfound',
component: notfound
}
]
});
You could check this Reference tutorial and the source code for a step-by-step setup.
Tested with Symfony 3.x, 4.x, VueJS 2.5.x, VueRouter 3.x
Had the Same issue. Symfony is simultaneously delivering a Vue driven frontend and implementing an Rest-API. I solved it using some sort of PageNotFound-Fallback, so basically every route that was not found by the Symfony Router will be forwarded/redirected to the Frontend. So the FrontendController looks like this:
class FrontendController extends Controller{
public function indexAction(Request $request)
{
$base=$request->getBaseUrl();
return $this->render('default/index.html.twig',['basePath'=>$base]);
}
public function pageNotFoundAction()
{
return $this->forward('AppBundle:Frontend:index');
}
}
With an additional configuration in the routing.yml (see: Redirect with Event Listener for all "No route found 404 Not Found - NotFoundHttpException")
pageNotFound:
path: /{path}
defaults: { _controller: AppBundle:Frontend:pageNotFound, path: '' }
requirements:
path: .*
Finally, the VueRouter needs to be configured, so it keeps the correct environment, simply by adding the base Property in the Router constructor. If the frontend component is not displayed correctly, you can use router.push('some-route') to manually adjust it.
Keep in mind that there will be no more 404 Errors, since they are all forwarded to the frontend, which can lead to bad scenarios using ajax on page load...
Altough it feels like a hack, I hope this helps. Open for better solutions.
EDIT Symfony version 3.4.3, Vue version 2.5.1

Ignore route in Laravel 5.1

I want to create dynamic pages CMS for my Laravel app. Admin is allowed to provide any URI for any page, so for example, he can create page with one/two/three URI and http://example.com/one/two/three will point to this site. I already figured out it's possible to add single route for multiple level URLs like this:
get('{uri}', 'PageController#view')->where('uri', '.+');
Now, I also want to have /{username} URLs to point to users profiles. That means, if I need to make it work together. For me, the perfect code would be something like this:
get('{username}', 'ProfileController#view');
get('{uri}', 'PageController#view')->where('uri', '.+');
Then, in ProfileController I'd like to make my route go further just like it wasn't there. Something like this:
// ProfileController
public function view()
{
$user = User::whereUsername($username)->first();
if ($user === null) {
// Go to the next route.
}
}
Can it be done with Laravel?
I can think of another solution, just to have dynamic routing controller for both usernames and page uris mapping, but I would prefer to have it as separate routes.
You can resolve a new PageController instance out of the Service Container if $user is null.
// ProfileController
public function view()
{
$user = User::whereUsername($username)->first();
if ($user === null) {
// Go to the next route.
$params = []; // If your view method on the PageController has any parameters, define them here
$pageController = app(PageController::class);
return $pageController->callAction('view', $params)
}
}
This way, the {username} route will stay but will show custom content defined by the admin.
Edit:
If you don't want to call a controller manually, you could analyze the current URL segments and check for an existing user before you define your route. In order to not make your routes.php file too complex, I'd add a dedicated service class that analyzes your URL segments:
App\Services\RouteService.php:
<?php
namespace App\Services;
class RouteService {
public static function isUserRoute()
{
if(count(Request::segments()) == 1)
return !! User::whereUsername(Request::segment(1))->first();
}
return false;
}
}
routes.php:
<?php
use App\Services\RouteService;
if(RouteService::isUserRoute())
{
get('{username}', 'ProfileController#view');
}
get('{uri}', 'PageController#view')->where('uri', '.+');
I have not tested this, but it should work. Adjust the RouteService class to your needs.
I'm using the first approach in my CMS and it works realy well. The only difference is that I have written a Job that handles all incoming requests and calls the controller actions respectively.

How to use wild card in admin routing in laravel 5

I am using code that is below for admin routing in laravel.
Route::group(['prefix' => 'admin'], function() {
Route::get('/', 'Admin\AdminController#home');
Route::get('/users/userList', 'Admin\UserController#userList');
Route::get('/users/detail', 'Admin\UserController#detail');
Route::get('/posts/view', 'Admin\PostController#view');
Route::get('/posts/edit', 'Admin\PostController#edit');
Route::get('/posts/add', 'Admin\PostController#add');
});
This is working fine for me. But when I add new functions in code for that I have to write routing in routes file. For example: If I want to add edit functionality in users controller, for that I have to add new route like .
Route::get('/users/edit', 'Admin\UserController#edit');
So I have to add routing for each function.
I want to know How to use wild card for admin routing so that I have to write routing only for controller not for each function for example.
Route::group(['prefix' => 'admin'], function() {
Route::get('/', 'Admin\AdminController#home');
Route::get('/users/:any', 'Admin\UserController#:any');
Route::get('/posts/:any', 'Admin\PostsController#:any');
});
wild card replace the function name, and auto ridirect to that function.
You could use implicit controllers that will do what you need.
First declare a route for your implicit controller
Route::controller('users', 'UserController');
Then, on your controller, you have to follow a convention for naming your routes with HTTP verbs used to access them (get for GET, post for POST, any for both)
class UserController extends Controller {
public function getIndex()
{
//
}
public function postProfile()
{
//
}
public function anyLogin()
{
//
}
}
A note about composed method name from documentation
If your controller action contains multiple words, you may access the action using "dash" syntax in the URI. For example, the following controller action on our UserController would respond to the users/admin-profile URI:
public function getAdminProfile() {}

laravel - home route

I'm learning Laravel, and for my first project I'd like to create my portfolio. However, the first task I have to do is confusing me.
So I created my templates, layout.blade.php and home.blade.php. That makes sense to me, but now how do I tell Laravel, or how do I route to home.blade.php?
I'm looking for an explanation rather then just code. I'm trying to learn.
Actually, a view in MVC application is just a part of the application and it's only for presentation logic, the UI and one doesn't call/load a view directly without the help of another part (controller/function) of the application. Basically, you make a request to a route and that route passes the control over to a controller/function and from there you show/load the view. So it's not a tutorial site and it's also not possible to explain about MVC here, you should read about it and for Laravel, it's best place to understand the basics on it's documentation, well explained with examples, anyways.
In case of Laravel, you should create a controller/class or an anonymous function in your apps/routes.php file and show the view from one of those. Just follow the given instruction step by step.
Using a Class:
To create a route to your Home Controller you should add this code in your app/routes.php
// This will call "showWelcome" method in your "HomeController" class
Route::any('/', array( 'as' => 'home', 'uses' => 'HomeController#showWelcome' ));
Then create the HomeController controller/class (create a file in your controllers folder and save this file using HomeController.php as it's name) then paste the code given below
class HomeController extends BaseController {
public function showWelcome()
{
// whatever you do, do it here
// prepare some data to use in the view (optional)
$data['page_title'] = 'Home Page';
// finally load the view
return View::make('home', $data);
}
}
If you have {{ $title }} in your home.blade.php then it'll print Home Page. So, to use a view you need a controller or an anonymous function and load the view from the controller/function.
Using an anonymous function:
Also, you can use an anonymous function instead of a controller/class to show the view from directly your route, i.e.
Route::any('/', function(){
// return View::make('home');
// or this
$data['page_title'] = 'Home Page'; // (optional)
return View::make('home', $data);
});
Using this approach, whenever you make a request to the home page, Laravel will call the anonymous function given in/as route's callback and from there you show your view.
Make sure to extend the the master/main layout in sub view (home):
Also, remember that, you have following at the first line of your home.blade.php file
#extends('layouts.layout')
It looks confusing, you may rename the main layout (layout.blade.php) to master.blade.php and use following in your home.blade.php instead
#extends('layouts.master')
Read the doc/understand basics:
You should read Laravel's documentation properly, (check templates to understand blade templating) and also read some MVC examples, that may help you too understand the basics of an MVC framework (you may find more by googling) and some good posts about MVC on SO.
Check it routing in Laravel.
You need to use route file and controllers
Create needed function in your Controller file and create a template file for example
class UserController extends BaseController {
/**
* Show the profile for the given user.
*/
public function showProfile($id)
{
$user = User::find($id);
return View::make('user.profile', array('user' => $user));
}
}
you need to create view file views/user/profile.blade.php
View::make('user.profile', array('user' => $user)) == views/user/profile.blade.php
And you should read it http://laravel.com/docs/responses and also this http://laravel.com/docs/quick#creating-a-view

PHP Laravel extending resource routing

Laravel routing functionality allows you to name a resource and name a controller to go with it. I am new to Laravel and would like to know if anyone knows how to extend the resources method in the route class provided.
Basically say I have: (which works fine)
/invoices
But say I want:
/invoices/status/unpaid
How is this achievable?
To see the basics of what I am doing check:
http://laravel.com/docs/controllers#resource-controllers
Resource controllers tie you into a specific URLs, such as:
GET|POST /invoices
GET|PUT /invoices/{$id}
GET /invoices/create
and so on as documented.
Since, by convention, GET /invoices is used to list all invoices, you may want to add some filtering on that:
/invoices?status=unpaid - which you can then use in code
<?php
class InvoiceController extends BaseController {
public function index()
{
$status = Input::get('status');
// Continue with logic, pagination, etc
}
}
If you don't want to use filtering via a query string, in your case, you may be able to do something like:
// routes.php
Route::group(array('prefix' => 'invoice'), function()
{
Route::get('status/unpaid', 'InvoiceController#filter');
});
Route::resource('invoice', 'InvoiceController');
That might work as the order routes are created matter. The first route that matches will be the one used to fulfill the request.

Categories