I have one table, which i have divided in two section for each i have mention two action under controller, i wanted to separate validation rule for both action, so i don't want use common model rule.
Is there any way by which i can write rule in action.
I have user controller there i have defined two action called frontuser and backenduser.
my action in controller
public function actionfrontuserCreate()
{
// want to write rule here
}
public function actionbackenduserCreate()
{
// want to write rule here
}
Thanks
Hi i hope i can help you:
rules should be declared in the model even if the model is shared between one or more controllers with different kind of actions ...
but you do not want a rule to be executed in all of those actions so you specify wich actions can take that rule using scenarios, i leave you an example:
array('password_repeat', 'required', 'on'=>'register'),
code above only makes pasword_repeat required on scenario register
then in your controller you will specify wich scenario will be used...
$modelA = User::model()->findByPk(1); // $model->scenario = 'update'
$modelB = new User(); // $model->scenario = 'insert'
$modelB->scenario = 'light'; // custom scenario
if ($modelB->validate()) { ...
i hope this solve your issue, for bonus i suggest to check default yii scenarios insert, update, delete ....
Validation rules go in the model not in the controller. What you want to do is use scenarios.
When you put a rules in the model you can do something like:
array('username', 'required', 'on'=>'frontUserCreate'),
By using the 'on'=>'...' part you can tell in what scenario the rule must be applied.
In your controller when you create a new model you should give the scenario as a parameter:
public function actionfrontuserCreate()
{
$model = new User('frontUserCreate');
if (isset($_POST['User']) {
....
}
$this->render('viewname', array('model'=>$model));
}
Related
I would like to validate the get parameter where i passed throug the route to my controller.
api/route
get /order/{id} -> OrderController::order
public function order($id) {
// validation here (rules= require,between 1 and 1000)
return Order::find($id);
}
how can I validate inside my controller without creating a separate request class?
which validation class do i have to import? (this one: Illuminate\Support\Facades\Validator ? )
Is this a good or common solution?
As #lagbox already wrote, you can check all of your questions inside the Laravel documentation.
Validation inside the controller
use Illuminate\Http\Request;
class MyController extends Controller
{
public function order(Request $request, int $id)
{
$validated = $this->validate([
// .. put your fields and rules here
]);
}
}
If your controller extends the base controller, that is shipped with every Laravel installation you have direct access to the validator via $this->validate.
With injecting the $request you have access to the fields that are send (POSTed) to your server.
If this is a good solution heavily depends on the projects size and other factors. It is definitely a good solution to start with. If your project grows and you need to have the same validation logic in various places you can again think about additional Form Request Validation.
To apply certain rules to the route parameter, f. ex. id, you can use Regular Expression Constraints.
Futher processing of request data
I personally would leave the validation inside the controller (or a form request class).
If there is any problem with the request data, then it should fail there and not continue to the service class.
You could say this is a kind of fail fast approach. Why moving more and more inside your code, if your request items might have an error (are not valid)?
$id is always present so required validation always passes.
So you only need to check between 1 and 1000 condition.
I think using regex constraints in the route is a good idea here.
Route::get('/order/{id}','OrderController#order')
->where(['id'=> '1000|^[1-9]{0,2}[1-9]$']);
If id is less than 1 or more than 1000 or any other random string it won't match the route and if there isn't any other matching routes too, it gives 404 error.
If you really want to validate the route parameter in the controller, you can use this:
$validator = \Illuminate\Support\Facades\Validator::make(['id' => $id],
[
'id' => 'required|integer|between:1,1000'
]
);
$validator->validate();
I am trying to create a dynamic router for my symfony application where on a base of some condition I want to set the prefix of a route, the condition based prefix is working as I use the statically coded condition, see my router with dummy route, main symfony route for Bundle
(config/routes/annotation.php)
<?php use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
return function (RoutingConfigurator $routes) {
$resultRout = $routes->import('#MyCustomBundle/Controller/Test/', 'annotation')
->defaults(['_locale' => '%locale%'])
->requirements(['_locale' => '%app_locales%']);
// get $validate value from database
if ($validate) {
$resultRout->prefix('/{_locale}/app/{default_path}/');
} else {
$resultRout->prefix('/{_locale}/site/{new_path}/');
}
};
The issues I face are:
1: I need to clear route caching every time for different route condition. Is there a way to stop route caching?
2: I want to access database so that I can create $validate as per the DB values. How to load entity manager?
Also if there is a better way to achieve this type of routing please suggest.
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.
I'm trying to make a cms like app using Yii. The functionality is going to be something like:
http://www.example.com/article/some-article-name
What I am trying to do is have everything go the method actionIndex() in the ArticleController.php, and have that one method determine how to handle the action. So my question is how can I route all actions to one method in a controller in Yii?
In your case, I think it'll be better to use either a filter or a beforeAction method.
Filter way:
Filter is a piece of code that is configured to be executed before and/or after a controller action executes.
Sample:
class SomeController extends Controller {
// ... other code ...
public function filters() {
return array(
// .. other filters ...
'mysimple', // our filter will be applied to all actions in this controller
// ... other filters ...
);
}
public function filterMysimple($filterChain) { // this is the filter code
// ... do stuff ...
$filterChain->run(); // this bit is important to let the action run
}
// ... other code ...
}
beforeAction way:
This method is invoked right before an action is to be executed (after all possible filters.) You may override this method to do last-minute preparation for the action.
Sample:
class SomeController extends Controller {
// ... other code ...
protected function beforeAction($action) {
if (parent::beforeAction($action)){
// do stuff
return true; // this line is important to let the action continue
}
return false;
}
// ... other code ...
}
As a side note, you can access the current action within a controller this way also : $this->action , to get the value of id: $this->action->id:
if($this->action->id == 'view') { // say you want to detect actionView
$this->layout = 'path/to/layout'; // say you want to set a different layout for actionView
}
Add this in the beginning of urlManager rules in the config:
'article/*' => 'article',
Your rules will have to be similar to the following :-
'rules' => array(
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => 'article/index',
),
This will pass all requests to the actionIndex function in the ArticleControllerPHP Class if the Controller and/or Action does not exist.
I'm guessing you just wanna throw in a bunch of static pages in your "view" folder and have them selected and rendered automatically without adding an action for each of them in your controller.
The above suggested filters() and beforeAction() and even __construct() do not work for this purpose (filters and beforeaction do not fire up at all if the action does not exist, and __construct is very messy because if you put your functionality in __construct - at that point Yii doesnt even know which controller/action/view it should call)
however, there is a simple workaround which involves URL manager
in your config, in URL manager's rules, add one of the following lines (depending on your path settings)
'articles/<action:\w+>' => 'articles/index/action/<action>',
OR
'articles/<action:\w+>' => 'articles/index?action=<action>',
and then, in your articles controller just put up this (or similar) index action
public function actionIndex() {
$name = Yii::app()->request->getParam('action');
$this->render($name);
}
then you can call pages like /articles/myarticle or /articles/yourarticle without putting up any function in your controller. All you would need to do is just add a file named myarticle.php or yourarticle.php in your views/articles folder, and type your html content inside those files.
In Symfony2 it is possible to define 2 different #routes to get one same Controller and Action?
The thing is: how do you check in that unique action what path or route does the user come from?
Example: Imagine we have an action called "createUserAction" that can be reached both from #routes /common_register and /premium_register.
Inside the action I want to difference between the two kinds of users, to use different forms and create the users according to the route they have entered through (or in general, have a different behavour depending o it).
How do I do that?
In your action, just add additional special route parameter $_route to the method
public function createUserAction ($_route)
{
... //$_route will return the name of your route
}
Have you considered another approach? Just use a single route with a parameter:
/**
*#route ("/register/{type}", requirements={"type" = "common|premium"})
**/
public function createUserAction ($type) {
//use $type to decide what to do
}