How can I hide user_id from URL using yii framework? - php

I am using the yii framework and have different user accounts. When I want to have a look at the view page of user 4 I have to enter an url like www.mydomain.com/user/4 for update I have www.mydomain.com/user/update/4.
Is there a way so that I can hide the user id from the url line?
How can I set a route like www.mydomain.com/user/username and www.mydomain.com/user/update/username? Do I have to modify the routes?
What if the username contains an # symbols?

If each user has a unique username, you can describe a route that doesn't show their user id by putting this custom routing rule in config/main:
'urlManager' => array(
'rules' => array(
'user/<username:\S+>' => 'users/view',
)
)
The \S+ should accept "#". Then pass that username to controllers/UsersController like so:
public function actionView($username) {...}
Instead of www.mydomain.com/user/update/username I would use www.mydomain.com/user/<username>/update and put this in the above urlManager rules array:
'user/<username:\S+>/update' => 'users/update',
and this in UsersController:
public function actionUpdate($username) {...}
You can also generate a unique, random number for each user before creation and route based on that number.

I think it's better to encrypt your id before passing it. And decrypt it when you reach there. There are many ways of generating such random/encrpted ids. For more security you should not give name like 'user', that you did. Try to modify that even. Hope you got the point...:)

Related

How to use Yii2 Sluggable Behavior without showing id number?

I have read the question on using SluggableBehavior in Yii2
and in my trial case I can generate url like article/1/First-Article using the rule in urlManager
'article/<id:\d+>/<slug>' => 'article/view',
and using
\yii\helpers\Url::to(['article/view', 'id'=>$model->id, 'slug'=>$model->slug])
to create url.
In my real case, I use ['article/view', 'hash'=> $model->hash, 'slug'=>$model->slug] to generate url. My rule is
'article/<hash:[\d-\w]+>/<slug>'=>'article/view'
My url is like article/1e482d69129d760e9494b2c6e86eba2b/First-Article.
I want to only show url like article/First-Article, i.e. not showing the hash code in the url. Is there a way to achieve this? Thanks a lot!
According to Yii docs, if your specify SluggableBehavior's attribute property with an array of model attributes, it will implode (concatenate) them in order to generate uniqueness for the slug. In your case, this implementation perfectly satisfies your desired slug concatenated composition (e.g. First-Article-1);
Internally SluggableBehavior will perform it's generateSlug method to generate unique slug from your attributes composition defined in attribute property. Since generateSlug uses - delimiter by default, it perfectly fits your requirements in order to generate desired url slug.
Take a look into this:
public function behaviors()
{
return [
[
'class' => SluggableBehavior::className(),
'attribute' => ['slug', 'id'],
...
]
];
}
EDIT:
This is your URL Rule: 'article/<slug>' => 'article/view'
and
Generating appropriate link: Url::to(['article', 'slug' => $model->slug . '-' . $model->id])

Cake PHP 3 Paring Routing with a table

I have been trying to get pretty url with the router with Cake.
www.mysite.com/category/slug
www.mysite.com/slug
www.mysite.com/category/
I think there is no formula to get exactly what I want so I want explicitly match each url. I want my route table to look like this
id | url | controller | action | param
So when someone goes to
www.mysite.com/mysubcategory/my-title-of-page
I want it to cross reference "mysubcategory/my-title-of-page" with the url column and proceed. What is the best way to do this?
My guess would be to be to direct all traffic to a Route Controller
Router::connect('/*', array('controller' => 'Routes', 'action' => 'redirs'));
But when it redirects i want it to show the pretty url in the browser, i dont want it to show articles/view/12
thank you
You could either dynamically create your routes with the information retrieved from the database, or use a custom route class that looks up the table. If you only have a few routes, then you may want to use the former.
In your routes.php simply read your table and connect the routes, it should be as simple as that. Here's a very basic example:
use Cake\ORM\TableRegistry;
$Routes = TableRegistry::get('Routes');
$routes = $Routes->find();
foreach ($routes as $route) {
Router::connect(
$route->url,
[
'controller' => $route->controller,
'action' => $route->action
],
[
'pass' => [$route->param]
]
);
}
For something dynamic, check for example Mapping slugs from database in routing

Laravel using named routes

Regarding the use of named routes, these 2 lines allow me to access the same page so which is correct?
// Named route
Route::get('test/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
// Much simpler
Route::get('apples', 'TestController#getApples');
Is there any reason I should be using named routes if the latter is shorter and less prone to errors?
Named routes are better, Why ?
It's always better to use a named route because insstsead of using the url you may use the name to refer the route, for example:
return Redirect::to('an/url');
Now above code will work but if you would use this:
return Redirect::route('routename');
Then it'll generate the url on the fly so, if you even change the url your code won't be broken. For example, check your route:
Route::get('apples', 'TestController#getApples');
Route::get('apples', array('as' => 'apples.show', 'uses' => 'TestController#getApples'));
Both routes are same but one without name so to use the route without name you have to depend on the url, for example:
return Redirect::to('apples');
But same thing you may do using the route name if your route contains a name, for example:
return Redirect::route('apples.show');
In this case, you may change the url from apples to somethingelse but still your Redirect will work without changing the code.
The only advantage is it is easier to link to, and you can change the URL without going through and changing all of its references. For example, with named routes you can do stuff like this:
URL::route('apples');
Redirect::route('apples');
Form::open(array('route' => 'apples'));
Then, if you update your route, all of your URLs will be updated:
// from
Route::get('test/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
// to
Route::get('new/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
Another benefit is logically creating a URL with a lot parameters. This allows you to be a lot more dynamic with your URL generation, so something like:
Route::get('search/{category}/{query}', array(
'as' => 'search',
'uses' => 'SearchController#find',
));
$parameters = array(
'category' => 'articles',
'query' => 'apples',
);
echo URL::route('search', $parameters);
// http://domain.com/search/articles/apples
The only reason to name the route is if you need to reference it later. IE: from your page in a view or something, check whether you are in that route.

How to set custom Route with alias as controller

The CMS i'm developing using Cakephp 2.0 has two main Controllers:
Pages
Categories
I'm trying to set the route.php to have the following behavior:
If the user request a Page, the URL should be something like:
http://www.something.com/pages-alias/article-name/id/whatever
If the user address a Category, the URL should be something like:
http://www.something.com/categories-alias/category-name/id/whatever
Please notice that following categories and pages i've used "alias".
To clarify with an example, the URLs for a website of a local restaurant will be:
http://www.something.com/course/wild-boar/68/2013-07-18
Where "course" will substitute "page". And
http://www.something.com/menu/valentine-day/8/2014-01-30
Where "menu" will substitute "category".
The View should not be explicited in the URL nor the Routing rules.
Both the cases will have the view automatically choosen by the controller after some internal check (having subcategory, having only one page or more pages, and so on) so that will be overridden by the controller.
I've got some clues about the use of sort-of "alias" to build the routing rules but unfortunately the documentation was not clear enough to me about how to manage the object to create my own custom route.
So, can someone try to explain it with some example different from the ones available in the CakePhP 2.x documentation?
Thanks in advance to anyone that can be helpful.
For reference i'll paste here the links i've already read:
Routing - Cakephp 2.0 Documentation
Bakery Article from Frank (i suppose this is for the v1.3)
That is what you want probably:
Router::connect(
'/:category_alias/:category_name/:id/:whatever',
array('controller' => 'Article', 'action' => 'view'),
array('pass' => array('category_alias','category_name','id','whatever'),
'id' => '[0-9]+')
);
ofc you can delete this validator for id.. or add more validators :)
Then you can use function in ArticleController.php
public function view($category_alias, $category_name, $id, $whatever) {}

Custom lithium routing scenario

I've been tasked with rewriting an existing website with large pre-existing link catalog. For argument's sake, let's assume we can't do anything that would change the link catalog. Here's a few examples of the link structure we're working with:
An item page would be:
www.domain.com/widgets/some-totally-awesome-large-purple-widget
A category sub page page would be:
www.domain.com/widgets/purple-widgets
A category parent page page would be:
www.domain.com/widgets/
A custom page may be:
www.domain.com/some-random-page
The various page types are too numerous to write individual Routers for.
Using Router::connect I can easily account for the first and second scenarios using something like:
Router::connect('/{:pageroot}/{:pagekey}', 'Pages::index');
In turn, the Pages::index method looks for entries in our database with the "key" of '/widgets/purple-widgets'.
However, the framework defaults to the '/{:controller}/{:action}/{:args}' route for pages like the third and fourth. I know that this is the correct behavior for the framework. Also, best practice would state that I should write the site to match this behavior. But, that isn't an option here.
What I need is a Router that would allow the third and fourth examples to function the same as the first. All examples should be sent to the Pages::index controller, which in turn queries a database using the URL path as a key.
If you don't have any convention in the URL for what is what, between page, item and category. I'd go with a very generic router.
Router::connect('/{:category}/{:page}/{:item}', 'Pages::any');
Router::connect('/{:category}/{:page}', array('Pages::any', 'item' => null));
Router::connect('/{:category}', array('Pages::any', 'page' => null, 'item' => null));
And in Pages::any() to search for the correct stuff. Is that category a page after all (example 4)? Is that page an item (example 1)?
or
You store the URL somewhere (e.g. a mapping table in the database) and use the pattern version of a lithium Route.
Router::connect(new Route(array(
'pattern' => '#^/(?<path>.+)$#',
'params' => array('controller' => 'pages', 'action' => 'any'),
'keys' => array('path' => 'path'),
// extra stuff, if the path is `tata`, it skips this route and uses
// any of the following ones that matches.
'handler' => function($request) {
if ($request->params['path'] == 'tata') {
return false;
} else {
return $request;
}
}
)));
From that point, you'll get the full URL.
You probably should write a smart Router Helper which is maybe able to process your request based on your db defined routes.
Take a look into: net/http/Router.php
especially connect(), parse() and match()
I would start to write some kind of anonymous function and progress it to a testable Class which is located in /extension.. ?

Categories