Yii2 get access only using pretty URLs - yii2

I'm using URL manager like the following:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'verses/view/<id:\d+>' => 'verses/view',
],
],
It works fine to make access using mysite.com/verses/view/158. The problem is, it is still possible to access the same content using non pretty URL i.e using plain get parameter such as mysite.com/verses/view?id=158. I need any way to restrict the access using the pretty URL.
I have tried the following couples of rules separately, but nothing I have gotten:
'verses/view<?id=>' => 'Error404',
'verses/view?id=<\d+>' => 'Error404',

What is the point of such restriction?
Anyway, one way to do it is something like this:
public function actionView($id)
{
if (strpos(\Yii::$app->request->getUrl(), '?') !== false) {
throw new \yii\web\BadRequestHttpException;
}
// ... the rest of action
}
No changes in UrlManager needed.

Try using UrlManager parameter enableStrictParsing = true.
What happens. UrlManager checks all rulls and they all do not match the request. Thus, by default it checks all default rules. Among default rules it finds the rule with ?id= and preforms routing to that one.
So, in order to avoid that route, you need to list all possible routes in the UrlManger rules and make enableStrictParsing = true. The routes not listed in the config rules parameter will be ignored.

Related

Dynamic Pretty URL's in Yii2 using get Parameters

I am trying to generate dynamic URL's using yii2 routing, but I didnt find any proper example for what I am looking for
I have a page which has list of users. If I click on any user name it gets redirected to particular user's profile page.
The URL for profile page is like
https://www.example.com/frontend/web/users/profile?id=1&name=xyz
I want to show this URL as https://www.example.com/xyz where xyz is users name.
I have seen examples of pretty URL's but couldnt find any specific example.
How to such dynamic URL's. Please help.
You cannot fully remove static link from link. You can leave profile and remove other. Then your link will be https://www.example.com/profile/xyz
First of all add to config:
'urlManager' => [
'showScriptName' => false,
'enablePrettyUrl' => true,
'rules' => [
'profile/<name>' => 'users/profile',
...
],
Change your action:
public function actionProfile($name) {
$user= User::findOne(['name'=>$name]);

Yii2 - Understanding urlManager

I have these possible urls:
Having country at beginning:
peru/blog/search/my-search
peru/blog/tag/my-tag
peru/blog/my-blog-post
peru/blog/
peru/
Without Country at beginning:
blog/search/my-search
blog/tag/my-tag
blog/my-blog-post
blog/
/
How it works:
As I understand url management there are 2 processes:
When you write an url on the browser. In this case Yii tries to convert this url into a route and params.
When you are creating an url using Yii::$app->urlManager->createAbsoluteUrl, in example.
According to these, I am writing some rules in the urlManager, first the general config:
'urlManager' => [
'class' => 'yii\web\UrlManager',
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => []
]
Now the rules:
'<country:peru|france>/<module:[\w\-]+>/tag/<tag:[\w\-]*>' => '<module>/index',
'<country:peru|france>/<module:[\w\-]+>/search/<search:[\w\-]*>' => '<module>/index',
'<country:peru|france>/<module:[\w\-]+>/<slug:[\w\-]*>' => '<module>/index',
'<country:peru|france>/<module:[\w\-]+>' => '<module>/index',
'<module:[\w\-]+>/tag/<tag:[\w\-]*>' => '<module>/index',
'<module:[\w\-]+>/search/<search:[\w\-]*>' => '<module>/index',
'<module:[\w\-]+>/<slug:[\w\-]*>' => '<module>/index',
'<module:[\w\-]+>' => '<module>/index',
As you notice from the rules, I pass a parameter "module" in the url, and I want that one to be used as controller.
In the case of country I had to add some possible matches, if not I was not able to make it work.
With the above rules, It works when I input a "pretty" url on the browser like:
http://example.com/blog/search/my-search
But my issue starts If try to create an url:
Yii::$app->urlManager->createAbsoluteUrl(["blog/index", "module" => "blog"]
Rule: '<module:[\w\-]+>' => '<module>/index'
Url Expected: http://example.com/blog
Url Generated: http://example.com/blog?module=blog
It seems it does not fall in the rule, not sure.
If I try to create an url:
Yii::$app->urlManager->createAbsoluteUrl(['blog/index', 'module' => 'blog', 'slug' => 'my-post'])
Rule: '<module:[\w\-]+>/<slug:[\w\-]*>' => '<module>/index'
Url Expected: http://example.com/blog/my-post
Url Generated: http://example.com/blog/my-post?module=blog
From these 2 cases, I notice it is adding the controller to the url
Questions:
In my rule I use I think it collides with predefined variables like: , . I have tried change it, but still same issue.
In the case of country I had to add possible options: Peru, france to make it work, if not it did not work, how can I make it work without those options?
The url match depends on the amount of query params or does it count controller and action too?
How can I make empty parameters be ignored for the rules, when creating an url?
Why is adding controller to the url?
Is the rules order correct?
I think I found a solution to all my questions:
So far I have not found predefined keywords for rules: <controller>, <action>, <module> are just name of variables, if someone knows something different, please let me know.
Yii URL manager (and probably any URL manager) can only match the amount of parameters we send and match it against rules, not the variable names, so if we send:
http://example.com/peru
http://example.com/es
Yii only understands that we are sending one parameter, so if in the rules we have:
'<language:[\w\-]*>' => 'language/index'
'<country:[\w\-]*>' => 'country/index'
Yii will use the first rule that matches, so in this case would be <language> rule which will match. Then Yii will pass a variable $language with "peru" as value to LanguageControlle, which is wrong.
So in order to help Yii we have to add patterns to help it use correct rule, we could add a pattern to match only any value with 2 characters or specific values list like:
<language:es|en> => 'language/index'
<country:[\w\-]*> => 'country/index'
In this case if we have "peru" as value, it will not match first rule, so it will use second one.
Answered above.
Ignore empty parameters, we can use + instead of * in the rules, in that way empty parameters will not match.
Remove the controller, we need to add a rule at the end:
'' => 'site/index'
Question ordering, it should start with the rules with most parameters and inside that group order them from the less generic to more generic rules.
At the end my rules are:
'<base:es|en>/<module:ideas|user|blog>/tag/<tag:[\w\-]*>' => '<module>/index',
'<base:es|en>/<module:ideas|user|blog>/search/<search:[\w\-]*>' => '<module>/index',
'<base:es|en>/<module:ideas|user|blog>/<slug:[\w\-]*>' => '<module>/index',
'<base:es|en>/<module:ideas|user|blog>' => '<module>/index',
'<base:es|en>/<slug:contact>' => 'site/index',
'<base:es|en>' => 'site/index',
'<module:ideas|user|blog>/tag/<tag:[\w\-]*>' => '<module>/index',
'<module:ideas|user|blog>/search/<search:[\w\-]*>' => '<module>/index',
'<module:ideas|user|blog>/<slug:[\w\-]*>' => '<module>/index',
'<module:ideas|user|blog>' => '<module>/index',
'<slug:contact>' => 'site/index',
'' => 'site/index',
I hope this saves time to someone in the future.
The problem is how you create URL. If <module> is available in route pattern (value in rules array), then you don't need to pass it manually. It will be detected from route.
Sou you should create your URLs like this:
Yii::$app->urlManager->createAbsoluteUrl(['blog/index', 'slug' => 'my-post'])
Yii::$app->urlManager->createAbsoluteUrl(['blog/index']);

Yii2 -- Pretty Url -- Domain to Controller/Action with parameters

What will be the rules for my pretty url if I have the following scenario:
links like this where parameters may vary.
domain/?bt=<token>&e=<email>
or
domain/?lt=<token>&e=<email>
then should be processed in a controller/action. ie. mycontroller/get
Also, parameters should be accessible by $_GET inside the action.
the simplest way is based on the use of urlHelper
use yii\helpers\Url;
$myUrl = Url::to(['your_controller/your_action', 'bt' => 123, 'e' => 'myemail#gmail.com']);
Using the urlHelper function Url::to .. the url you need is properly formed depending of the urlManager configuration you have set in your config file
and the param a manager as show in the sample like entry in an array.
The post or get method is related to the type of metho you have in your ulr call if not other values are specified the url is formed as a get
and you can obtain the values you need in $_GET['bt'] and $_get['e']
http://www.yiiframework.com/doc-2.0/yii-helpers-url.html
http://www.yiiframework.com/doc-2.0/yii-web-urlmanager.html
http://www.yiiframework.com/doc-2.0/guide-runtime-routing.html
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<controller:\w+>/<id:\d+>' => '<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
'' => 'call-backs/get',
'unsubscribes' => 'unsubscribes/get',
],
],
#scaisEdge, thank you for answering my question. maybe my question isn't that clear but this is the solution I made for my question after a hard find of clues and tips online.
All I wanted was that when a user clicks on a link, hitting the main page/main domain, it will go to my yii project (intended to be a webservice or an API like one) then will be handled by a precise controller and action.
'' => 'call-backs/get'
the code above answers the question. Cheers.

The default remember_me token in Laravel is too long

TL;DR How can I use my own way of generating the remember_me token?
I have an old site, written without any framework, and I have been given the job to rewrite it in Laravel (5.4.23). The DB is untouchable, cannot be refactored, cannot be modified in any way.
I was able to customise the Laravel authentication process using a different User model, one that reflect the old DB. But when it comes to the "Remember me" functionality, I have an issue with the length of the token.
The old site already uses the "Remember me" functionality but its DB field has been defined as BINARY(25). The token generated by the SessionGuard class is 60 characters long.
My first attempt was to try and find a way to shorten the token before writing it into the DB, and expand it again after reading it from the DB. I couldn't find such a way (and I'm not even sure there is such a way).
Then I looked into writing my own guard to override the cycleRememberToken (where the token is generated). I couldn't make it work, I think because the SessionGuard class is actually instantiated in a couple of places (as opposed to instantiate a class based on configuration).
So, I am stuck. I need a shorten token and I don't know how to get it.
Well, I was on the right track at one point.
I had to create my own guard, register it and use it. My problem, when I tried the first time, was that I did not register it in the right way. Anyway, this is what I did.
I put the following in AuthServiceProvides
Auth::extend('mysession', function ($app, $name, array $config) {
$provider = Auth::createUserProvider($config['provider']);
$guard = new MyGuard('lrb', $provider, app()->make('session.store'));
$guard->setCookieJar($this->app['cookie']);
$guard->setDispatcher($this->app['events']);
$guard->setRequest($this->app->refresh('request', $guard, 'setRequest'));
return $guard;
});
I change the guard in config/auth.php as
'guards' => [
'web' => [
'driver' => 'mysession',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
and finally my new guard
class MyGuard extends SessionGuard implements StatefulGuard, SupportsBasicAuth
{
/**
* #inheritdoc
*/
protected function cycleRememberToken(AuthenticatableContract $user)
{
$user->setRememberToken($token = Str::random(25));
$this->provider->updateRememberToken($user, $token);
}
}

urlManager rules not working on modules Yii2

I am trying to make some url rules in Yii 2 so I can access an action from the controller like this:
controller/action/1 -> controller/action (with a parameter)
I tried some rules but they won't work in my modules (www.example.com/midend, www.example.com/backend).
So, if I want to access www.example.com/controller/action/1 it's works just fine but if I want to access www.example.com/midend/controller/action/1 it return 404.
These are the rules for modules:
'<module:\w+>/<controller:\w+>/<action:\w+>/<id:\w+>' => '<module>/<controller>/<action>',
'<module:\w+>/<controller:\w+>/<action:\w+>' => '<module>/<controller>/<action>',
'<module:\w+>/<controller:\w+>/<id:\w+>' => '<module>/<controller>',
These are the rules without modules:
'<controller:\w+>/<action:\w+>/<id:\w+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
'<controller:\w+>/<id:\w+>' => '<controller>',
I already tried to replace <module:\w+> with midend.
Assuming your ids are integers, you should simply replace your rules by this one :
'<controller>/<action>/<id:\d+>' => '<controller>/<action>',
It will work for :
www.example.com/controller
www.example.com/controller/action
www.example.com/controller/action/1
www.example.com/module (assuming you have a default controller)
www.example.com/module/controller
www.example.com/module/controller/action
www.example.com/module/controller/action/1