Laravel resource with parameter causing other routes to throw error - api

I am running into this issue where if I define a param in that first route, the second throws this error:
"Route pattern "/browse/{brand}/{{brand}}" cannot reference variable name "brand" more than once."
Route::resource('browse/{brand}', 'BrowseController');
Route::group(array('prefix' => 'service'), function() {
Route::resource('authenticate', 'AuthenticationController');
});
If I take out the param, of course that breaks the browse route, but then the auth route works.
Does anyone know the reason for this?

The reason is because Route::resource creates several (RESTful) route handlers for you in the background for the controller you specify:
http://laravel.com/docs/controllers#resource-controllers
Take a look at the table called: Actions Handled By Resource Controller
You can see that Laravel will already handle routes for you that take parameter that you can use to implement browsing.
I don't think that the intended usage for Route::resource is to be parametrized like you are trying to.
Of course you can always implement additional routes if those do not match your needs.

Related

NextJS multiple dynamic routes with different destionation

In my project I have the following requirement: having 2 routes that are dynamic but that are going to be drawn by different components.
More context:
I have a CMS that provides all the info and in most of the cases I'm going to read from a "page" model. This is going to be drawn by the Page component and its going to have a getServerSideProps that makes a call to a CMS endpoint to get that information
The endpoint and component are not the same for the other case with a dynamic route
Both types of routes are completely dynamic so I cannot prepare then in advance (or at least I'm trying to find another solution) since they come from the CMS
As an example, I can have this slugs
mypage.com/about-us (page endpoint & component)
mypage.com/resource (resources endpoint & component)
Both routes are configured using dynamic routes like this
{
source: '/:pages*',
destination: '/cms/pages'
}
The problem here is that it can only match one of the endpoints and the logic for both calling the endpoint and the component used to draw it are completely different
Is there a way of fallbacking to the next matched URL in case that there's more than one that matches similar to the return {notFound: true}?
Some solutions that I have are:
Somehow hardcode all the resources urls (since are less than pages) and pass them as defined routes instead of dynamic routes
Make some dirty code that will check if the slug is from a resource and if not fallback to a page and then return a Resource component or a Page component depending on that (this idea I like it less since it makes the logic of the Page component super dirty)
Thanks so much!

Vue page cannot open after refreshing the page

I added the routes dynamically to the router and I can visit all pages with router-view. However, when I try to refresh the page I cannot visit the page again although the URL is the same. It is http://localhost:8081/me.
this.$router.addRoute("Main", {
path: '/me',
name: 'Me',
component: () => import(`#/components/Me.vue`)
});
As I said, I can normally visit the page "Me", but when I refresh it, I cannot see its content anymore with the warning:
[Vue Router warn]: No match found for location with path "/me"
I tried to create router with createWebHistory("/") after reading the cause of the error but nothing seems to change. I will appreciate any help.
There are two reasons why this would happen.
First serving SPA application from the server.
Make sure that your back-end is set to serve index.html file for all routes since back-end server is unaware of the routes set by client-side router. Something like express-history-api-fallback-middleware can help is using Node.js/Express.js.
Second problem is that of using addRoute.
As you described, the problem could be that Vue router is taking routing decision before your code in components/common/LeftMenu.vue is getting executed which is responsible for calling addRoute(). Ensure that this code is called before routing decision is being made. Best way would be to move this logic in top-level application component. And, if you can move that to top-level components, that means you can try to declare all routes while defining the router.
Why that should be done?
Using addRoute is not necessarily an anti-pattern but having to rely on addRoute is often code smell. You would really need it in extremely rare scenarios. Routing is a high-level architectural concern for your application and thus better to be declared upfront somewhere at top-level module even before application is getting initialized. Low level components should not attempt to manipulate routing data structure (violation of DIP principles).
One scenario where you might be tempted to use addRoute is taking decision after some data manipulation by the component with addition of some API call. That seems legitimate need but then to address that there are better ways. Considering using route guards (guards support async resolution too!) and prevent user from entering the view till the guard is resolved successfully.

difference between app.use('/users', usersRouter); and require(./routes/users)(app)?

In the express tutorial from mozilla,
https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website
they write
var usersRouter = require('./routes/users');
app.use('/users', usersRouter);
In other tutorials, they write something like this,
require('./routes/authRoutes')(app);
Are the two pretty much equivalent?
Without seeing the code for the other tutorials that you mentioned I cannot be sure exactly how they consume the app object that is passed to the imported code, but I suspect that whatever code is implemented in the .routes/authRoutes module simply connects a router object to the specified app object. This would most likely be done in the same way as the code that you provided from the Mozilla Express tutorial.
In both cases, a route handler is being defined and then registered as a handler for any routes that match the specified route. In the case that you mentioned that route would be the /users route. So the usersRouter object would have a number of route handlers defined, for example, for routes /abc and /def. So registering the usersRouter object as a route handler for the /users route would mean that the routes /users/abc and /users/def would be handled.

Handling laravel api resource store and create endpoints

I have the following in my controller
class WrittersController extends Controller
{
public function index()
{
return view('backend.writters.dashboard');
}
public function store(Request $request){
//confused on when to use this
}
public function create(Request $request){
//add new user functionality
}
Now in my routes i would like to use the resource routes
Route::resource('writters','WrittersController');
Now the confusion comes in my vue axios http endpoints. I uderstand that i index is a get request but axios doesnt have a store or create point.
When should i use the store and create endpoints in the vuejs
UPDATE ON MY AXIOS. Am using axios via
axios.post("url") //how do i go about create and store here
The store function is called when you want to create i.e you will create and then store. So I usually call the create method from inside the store. I do this just to seperate the code and make it more readable. There is no store or create http requests. The store uses post request. So you will need to use post request with axios. Just use Route::resource in your web.php and then go to the terminal and check your routes with
php artisan routes (laravel 4)
php artisan route:list (laravel 5)
This will list all your registered routes and tell you which functions they use.
You use the other resources in the same way you used it for the get request.
Assuming your resource route looks like the following.
Route::resource('/mydata', 'MyDataController');
You would construct your requests in the following manner.
As you observed already, if you use axios.get('/mydata') you are routed to the index method. However if you use axios.post('/mydata'), Laravel will automatically route you to the store method.
If you want to use the create action you change the url to use axios.get('/mydata/create') and you are routed to the create method. Please note that the create action is not used for creating the record but rather for fetching the view where the user will create the record, e.g. a form. Then you will store the data entered in that form with a POST request.
If you want to use PUT (or PATCH) you use axios.put(/mydata/{some_id}) and you are routed to the update method.
So Laravel handles all the routing automatically for you depending on the type of request that is made (GET, POST, PUT/PATCH, DELETE). You only need to supply a parameter in the URL for those "Verbs" that require it.
Look at the documentation here link Look for the chart or table labeled "Actions Handled By Resource Controller" and you will see the various actions what verbs to access them with, and their respective URLs and Routes.
Also note that you can add custom methods to the resource controller if needed, but you will have to define the route. You do this by declaring the route in your routes file e.g. web.php before you declare the actual resource.
Say you want to add an new post method 'archived' to mark some record as being no longer active. You would do something like the following in your routes.
Route::post('/mydata/archived/{some_id}', 'MyDataController#archive');
Route::resource('/mydata', 'MyDataController');
As demonstrated above you can use axios.put() or axios.patch() and they will both be routed to the update method. There are times when you need to handle those requests differently. For example when using a autosave feature and I want to validate some form data when only one field has changed, I would use patch to validate just that single field as follows.
public function update(Request $request, $id)
{
if($request->isMethod('patch')){
$this->validateSingle($request);
}else{
$this->validateAll($request);
}
//....
}

Adding custom route to Zend REST controller

I am using Zend F/W 1.12 in order to build a REST server.
One of my requirements are to have an action that Is outside the boundaries of what Zend can recognize as a "Restfull" action. What I mean is that I would like to have an action that is called something like mymedia and would like tou routes requests that are directed to //mymedia . Currently, Zend understand it as the id to a getAction and off course this is not what I want.
Any help will be highly appreciated!
Thanks
The implementation of Zend_Rest_Route does not allow much customization but instead provides a rudimental routing scheme for out-of-the-box usage.
So if you need to change the way how URIs are interpreted you can extend Zend_Rest_Route, Zend_Controller_Router_Route_Module or Zend_Controller_Router_Route_Abstract class to create your own kind of routing.
Have a look at the match method of those classes and what they do - e.g. they populate the $_values property array (while respecting the $_moduleKey, $_controllerKey and $_actionKey properties).
You can then add it e.g. as the first route within your bootstrap class:
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$router->addRoute('myRoute', new My_Route($frontController));
$router->addRoute('restRoute', new Zend_Rest_Route($frontController));
See:
http://framework.zend.com/manual/1.12/en/zend.controller.router.html#zend.controller.router.basic
Routing is a simple process of iterating through all provided routes and matching its definitions to current request URI. When a positive match is found, variable values are returned from the Route instance and are injected into the Zend_Controller_Request object for later use in the dispatcher as well as in user created controllers. On a negative match result, the next route in the chain is checked.
I once wrote a custom route for zend framework 1 that can handle custom restful routes. it served me well until now. see https://github.com/aporat/Application_Rest_Controller_Route for more details.
for example, if you want to have a url such as /users/30/messages mapped correctly into a zend controller action, use this route in your bootstrap:
$frontController = Zend_Controller_Front::getInstance();
$frontController->getRouter()->addRoute('users-messages', new Application_Rest_Controller_Route($frontController, 'users/:user_id/messages', ['controller' => 'users-messages']));