Laravel URL facade temporarySignedRoute to external url - php

I'm using Laravel 8 to generate a temporary signed route and pass some params, but I'd like my URL to take me to some URL of my choosing rather than a page in my project.
For context, my Laravel 8 project is an API, so there are no views, my API is then consumed by a front-end project written in Nuxt.
I've tried adding my URL to the first arg of temporarySignedRoute but it says that my route isn't found.
$verifyURL = URL::temporarySignedRoute(
'https://example.com/account/verify', Carbon::now()->addHours(24), ['contact' => 5, 'team' => 'john']
);
What am I missing or what workaround is there here?
UPDATE
So it turns out that I don't need to take the user to an external URL, but it seems that the wrong URL is being generated by URL::temporarySignedRoute.
The start of my generated URL is (for example) https://example.com/api/contact/verify and I need the URL to be https://api.example.com/api/contact/verify
So the same domain, except a sub-domain.
It looks like the APP_URL isn't being read because I changed it and it has no impact, and besides, this is used elsewhere, so I tried updating the URL with:
$verifyURL = URL::temporarySignedRoute(
'contact.verify', Carbon::now()->addHours(24), ['contact' => 5, 'team' => 'john]
);
// fix for wrong URL
$verifyURL = str_replace('example.com', 'api.example.com', $verifyURL);
However, this appears to have an invalid signature when the link provided by $verifyURL is clicked? How can I get the api part at the beginning?

URL::temporarySignedRoute() has a fourth parameter called $absolute which is a boolean. So if you want to prepend a custom url rather than the default url used by Laravel, this is the variable to change.
The default value for $absolute is true. Therefore in order to prepend your own custom url, be sure to change it to false first as below:
$verifyURL = URL::temporarySignedRoute(
'contact.verify', Carbon::now()->addHours(24), ['contact' => 5, 'team' => 'john], false // The $absolute value
);
Then concatenate your custom url:
$your_custom_url . $verifyURL;

First step, in the AppServiceProvider boot method, you need to register custom URL signing:
public function boot()
{
// This allows us to generate a temporary url for report downloading
Storage::disk('reports')->buildTemporaryUrlsUsing(function ($path, $expiration, $options) {
return URL::temporarySignedRoute(
'report.download',
$expiration,
array_merge($options, ['path' => $path])
);
});
}
To create the URL:
Storage::disk('reports')->temporaryUrl($pathname, Carbon::now()->addSeconds(10))
To download the file, this is my controller:
<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Storage;
use URL;
class ReportDownloadController extends Controller
{
public function download(Request $request)
{
if (!URL::signatureHasNotExpired($request)) {
return response('The URL has expired.');
}
if (!URL::hasCorrectSignature($request)) {
return response('Invalid URL provided');
}
return Storage::disk('reports')->download($request->get('path'));
}
}

Related

Laravel Resource controller

How do I tell my API to display a particular result based on another column?
e.g. localhost:8000/api/gadgets/{{id}}
Normally it returns the particular information of the specific gadget with that ID and localhost:8000/api/gadgets/{{imei_code}} does not return any value or an error whereas imei_code is a column that I needed to pass as a GET request...
I'm using the normal resource controller
public function show(Gadgets $gadget)
{
$response = ['data' => new GadgetResource($gadget), 'message' => 'specific gadget'];
return response($response, 200);
}
Also I need help on how I can create like a search function in the controller.
You can`t do two similar URLs. I think your route for URL
localhost:8000/api/gadgets/{{imei_code}}
isn`t work. Also the order of the routes is important and route that defined firstly will be have higer priority then route that defined secondly.
Because your routes /api/gadgets/{{id}} and /api/gadgets/{{imei_code}} is similar in this case only the one described earlier will be processed.
You can define another router and handler, for example:
localhost:8000/api/gadgets
That will return a list of gadgets by default and you can add filters for imei_code. For example:
localhost:8000/api/gadgets?imei_code=123
And your handler for the new route may be writed something like that:
public function showList(Request $request): GadgetResource
{
if ($imeiCode = $request->query('imei_code')) {
$list = Gadget::query()->where('imei_code', $imeiCode)->get();
} else {
$list = Gadget::query()->take(10)->get();
}
return GadgetResource::collection($list);
}
Or like alternative solution you can create diferent route for searching of gadgets exactly by imei_code to get rid of any route conflicts
localhost:8000/api/gadgets/by_imei/123
public function findByImei(Request $request): GadgetResource
{
$imeiCode = $request->route('imei_code');
$item = Gadget::query()->where('imei_code', $imeiCode)->first();
return new GadgetResource($item);
}
You can specify the model key by scoping - check docs
Route::resource('gadgets', GadgetController::class)->scoped([
'gadget' => 'imei_code'
]);
Than, when Laravel try to bind Gadget model in Controller - model will will be searched by key imei_code.
This code equvalent of
Route::get('/gadget/{gadget:imei_code}');
Try to change response
public function show(Gadgets $gadget)
{
$response = ['data' => new GadgetResource($gadget), 'message' => 'specific gadget'];
return response()->json($response);
}

Silex getBaseUrl and getBasePath empty

I'm sort of new to Silex and learning. I'm trying to return the base url inside one of my route controllers to return the new path after inserting a row into a database. No matter what I try it's returning an empty string though. Here's part of that function:
$app->match('/item', function(Request $request) use ($app) {
$method = $request->getMethod();
switch ($method) {
//POST
case 'POST': //insert
$data = array(
'item' => $request->get('item'),
'description' => $request->get('description'),
'quantityOnHand' => $request->get('quantityOnHand'),
'reorderPoint' => $request->get('reorderPoint'),
'supplier_id' => $request->get('supplier_id')
); //before to get supplier_id???? Or do it in ios
$app['db']->insert('inventory', $data);
$newId = (int) $app['db']->lastInsertId(); //cast int
$location = $request->getBaseUrl().'/inventory/id/'.$newId;
return $app->json(array('status' => 201, 'id'=>$newId, 'location' =>$location), 201);
break;
}
}
Everything in the $location variable is working except the base path. Am I missing something? I'm injecting the $request into the controller. When I run this it returns /inventory/item/101 for the location, without my base url.
Based on comments, it seems that what the OP is looking for is the hostname, not the base url, so the getHost method should be used.
Remember, though, that to generate URLs easily you should use the UrlGenerator instead of crafting it manually. Silex has a default provider for this service.

YII framework user friendly URL

My yii PHP project has UserController and it has an action called actionView. I can access user view page using following URL
mysite.com/user/view/id/1
I want to change that one to
mysite.com/username
How Can I do it.
I know that i can simply create rule to be more user friendly to get url such as
mysite.com/user/username
But url scheme with database resource name as direct param (mysite.com/username) is whole different story.
Url rule:
array(
'<username:\w+>'=>'user/view',
)
Note that in such scheme, you must also create rules for all your controllers and place above rule at the end, so better prefix it with user:
array(
'user/<username:\w+>'=>'user/view',
)
Resulting url will be example.com/user/username
In action:
public function actionView($username) ...
Update:
To make rule which reacts on any input variable create custom url rule class, here is some example, modify to your needs:
class PageUrlRule extends CBaseUrlRule
{
public function createUrl($manager, $route, $params, $ampersand)
{
// Ignore this rule for creating urls
return false;
}
public function parseUrl($manager, $request, $pathInfo, $rawPathInfo)
{
// Ignore / url or any controller name - which could conflict with username
if($pathInfo == '/')
{
return true;
}
// Search for username or any resource in db
// This is for mongo so it should be tuned to your db,
// just check if username exists
$criteria = new EMongoCriteria();
$criteria->url->$lang = $url;
$criteria->select(['_id']);
$criteria->limit(1);
$model = PageItem::model();
$cursor = $model->findAll($criteria);
// Create route, instead of $url id can be used
$route = sprintf('content/page/view/url/%s', urlencode($url));
// If found return route or false if not found
return $cursor->count() ? $route : false;
}
}
Then place this rule in beginning of urlmanager config
'rules' => [
[
'class' => 'application.modules.content.components.PageUrlRule'
],
// Other rules here
Important: If user has username same as your controller, it will match username and controller will be inaccessible. You must forbid registering users with same names as controllers.

Unable to generate a URL

I am currently trying to create a link on the index page that'll allow users to create an item. My routes.php looks like
Route::controller('items', 'ItemController');
and my ItemController looks like
class ItemController extends BaseController
{
// create variable
protected $item;
// create constructor
public function __construct(Item $item)
{
$this->item = $item;
}
public function getIndex()
{
// return all the items
$items = $this->item->all();
return View::make('items.index', compact('items'));
}
public function getCreate()
{
return View::make('items.create');
}
public function postStore()
{
$input = Input::all();
// checks the input with the validator rules from the Item model
$v = Validator::make($input, Item::$rules);
if ($v->passes())
{
$this->items->create($input);
return Redirect::route('items.index');
}
return Redirect::route('items.create');
}
}
I have tried changing the getIndex() to just index() but then I get a controller method not found. So, that is why I am using getIndex().
I think I have set up my create controllers correctly but when I go to the items/create url I get a
Unable to generate a URL for the named route "items.store" as such route does not exist.
error. I have tried using just store() and getStore() instead of postStore() but I keep getting the same error.
Anybody know what the problem might be? I don't understand why the URL isn't being generated.
You are using Route::controller() which does generate route names as far as I know.
i.e. you are referring to "items.store" - that is a route name.
You should either;
Define all routes specifically (probably best - see this blog here)
Use Route::resource('items', 'ItemController'); see docs here
If you use Route::resource - then you'll need to change your controller names
The error tells you, that the route name is not defined:
Unable to generate a URL for the named route "items.store" as such route does not exist.
Have a look in the Laravel 4 Docs in the Named Routes section. There are several examples that'll make you clear how to use these kind of routes.
Also have a look at the RESTful Controllers section.
Here's an example for your question:
Route::get('items', array(
'as' => 'items.store',
'uses' => 'ItemController#getIndex',
));
As The Shift Exchange said, Route::controller() doesn't generate names, but you can do it using a third parameter:
Route::controller( 'items',
'ItemController',
[
'getIndex' => 'items.index',
'getCreate' => 'items.create',
'postStore' => 'items.store',
...
]
);

how to pass parameter on redirect in yii

I am using Yii framework for my project;
I am redirecting page after success of insertion in database to another controller using
$this->redirect($this->createUrl('controller/action'));
During the redirection is it possible to pass any parameters just like in render,
$this->render('selectRefiner', array('param' => $data)
Try:
$this->redirect(array('controller/action', 'param1'=>'value1', 'param2'=>'value2',...))
api yii 1, api yii 2
try this:
Yii::$app->response->redirect(['site/dashboard','id' => 1, 'var1' => 'test']);
You can only pass GET parameters in the Yii 2 redirect(). However, I had a similar situation and I resolved it by using Session storage.
Naturally, you can access current Session via Yii::$app->session. Here is an example of using it in two separate controller actions:
public function actionOne() {
// Check if the Session is Open, and Open it if it isn't Open already
if (!Yii::$app->session->getIsActive()) {
Yii::$app->session->open();
}
Yii::$app->session['someParameter'] = 'Bool/String/Array...';
Yii::$app->session->close();
$this->redirect(['site/two']);
}
public function actionTwo() {
if (isset(Yii::$app->session['someParameter']) {
$param = Yii::$app->session['someParameter'];
} else {
$param = null;
}
$this->render('two', [
'param' => $param
]);
}
So now you should be able to access $param inside the two view.
For more information, please refer to the official class documentation.
To redirect into same action with the all parameters that already have this works for me.
$this->redirect($_PHP['SELF']);

Categories