This has to do with routing. So for getting parameters via url, you basically pass the data to the url following the route format you set.
This is working with links. I created the route, passed the data into the url, and used the request method to get the parameter for use in the controller. like URL::site("site/$color/$size")
What if I am constructing the url by form submission? For example, if I want to create a basic search query.
How do I get my form submission to look like this search/orange/large and not like this search.php?color=orange&size=large when I submit a form via get method.
By definition, the GET method puts the submitted information as URL parameters. If you specifically want to end up with a URL like site/$color/$size, you can use the POST-REDIRECT-GET pattern.
A partial example, from a controller on one of my sites (there is a submit button on the page named clear_cache_button):
public function action_index()
{
$session = Session::instance();
$is_post = (Request::current()->post('submit_button') !== NULL);
$is_clear_cache = (Request::current()->post('clear_cache_button') !== NULL);
$p = Database::instance()->table_prefix();
$people = DB::query(Database::SELECT, "
SELECT *
FROM `".$p."Tabe`;
")->cached(600, $is_clear_cache)->execute()->as_array('RegID');
if ($is_clear_cache)
{
HTTP::redirect(Request::current()->uri());
}
...
...
...
}
You can use Route filters (v3.3) or callbacks (3.1, 3.2) and set route params manually.
You can do it this way...
public function action_index()
{
// this will only be executed if you submmitted a form in your page
if(Arr::get($_POST,'search')){
$errors = '';
$data = Arr::extract($_POST,array('color','size'));
// you can now access data through the $data array:
// $data['color'], $data['size']
// perform validations here
if($data['color']=='') $error = 'Color is required';
elseif($data['size']=='') $error = 'Size is required';
if($error==''){
$this->request->redirect('search/'.$data['color'].'/'.$data['size']);
}
}
// load your search page view here
echo 'this is the search page';
}
Hope this helps you out.
Related
I'm trying to find the correct way to lay this out in laravel so that I can hit one GET route which calls a single function, but within that function I want to use data from a mysql table to determine which blade to show.
Say this URL is visited with a query string parameter:
www.testsite.com?email=testEmail.com
I hit this route (But not sure how to accept the parameter)
Route::get('register', 'Data\DataController#DataForm')
->name('Data.register');
I have a mysql table called dataTable set up like so
email | type
-------------------------
test1#mail.com A
test2#mail.com B
test3#mail.com C
What's the best way to incorporate the email parameter so that I can hit the single route and single function, then use the email/type columns from mysql to determine the appropriate blade to show?
public function DataForm(Request $request)
{
//query table based on query string parameter 'email'
$email = dataTable::where('email', /*email parameter?*/)->first();
if($email['type']== A){
return view('data.typeA');
}elseif($email['type']== B){
return view('data.typeB');
}elseif($email['type']== C){
return view('data.typeC');
}
}
You can add it as a route parameter :
Route::get('register/{email}', 'Data\DataController#DataForm')->name('Data.register');
And then inside controller :
public function DataForm($email)
{
// Abort to 404 if $email is not a valid email address
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
abort(404);
}
$typeData = Model::where('email', $email)->first();
// Email not found in the database
if(!$typeData){
abort(404);
}
switch ($typeData->type) {
case 'A':
return view('data.typeA');
case 'B':
return view('data.typeB');
case 'C':
return view('data.typeAC');
default:
abort(404);
}
}
Using a slash in the route you should be able to pass it like this:
Route::get('register/{email}', 'Data\DataController#DataForm')
->name('Data.register');
Then in your function you can just use the variable $email and it contains the email in the URL. But not sure if this URL is OK, using a slash instead of '?email=' for the passing of the parameter.
More on there here:
https://laravel.com/docs/5.7/routing#required-parameters
You'd need more logic than this, obviously:
public function DataForm(Request $request)
{
$type = (dataTable::where('email', $request->query->get('email'))->first())['type'];
return view('data.type'.$type);
}
As others said you could auto type in Request $request; however you don't have to. You can keep the function definition without the passed parameter, and use the helper functions instead:
if(request()->has('email')) {
$email = request()->input('email');
// Do stuff
} else {
// No email supplied
}
I can have the following urls
www.example.com/accounts/
www.example.com/accounts/signup
www.example.com/accounts/signup/validate
www.example.com/accounts/login
for each case, accounts becomes my controller, and index, signup, signup and login becomes my actions (or methods) respectively. I have to render different views based on what my actions are. Here is an example of what my code looks like
index
$url_segments = explode('/', $url);
$controller = !empty($url_segments[0]) ? $url_segments[0] : 'home';
array_shift($url_segments); // removes the controller name from array
$action = isset($url_segments[0]) && !empty($url_segments[0]) ? $url_segments[0] : 'index';
array_shift($url_segments); // removes the action name from array
$controller = ucfirst($controller);
$controller = new $controller($url_segments);
$controller->$action();
controller class
class Accounts{
private $url_segments;
public function __construct() {
$this->url_segments = $url_segments;
}
public function index() {
// index code here
}
public function login() {
// login code here
}
public function signup() {
if (!isset($this->url_segments[0])) {
// url entered was: example.com/signup
} else if (isset($this->url_segments[0]) && $this->url_segments[0] == 'validate') {
// url entered was: example.com/signup/validate
}
}
}
from how my code appeared above, it can be seen that as parameters keep adding after the controller and action part of the url I'll need to keep using conditional statements to run the proper code as in the case of /signup/ and signup/validate. Is this method of using conditional statement to load view based on parameters efficient or is there a better way of doing this.
I would recommend you to make use of a routing system like Symfony Routing. There you could add a new Route for every url and redirect them to your specific controller.
Example Route:
$routes = new RouteCollection();
$routes->add('/accounts_signup', route('POST', "/accounts/signup", 'App\Controller\AccountController:signup'));
return $routes;
This route would call the signup method in the AccountController calss when www.example.com/accounts/signup get called with a post request.
I recommend you to use something like this. Even if this might be a bit complicated for the beginning, after reading (and understanding) the docs this will safe you a lot of time and it will make your code more readable as well.
I want to redirect 2 different page from this controller function along with value.Here is my code. It works but both of time url become same.what shuld I do?
//in routes.php
Route::post('/','mycontroller#check');
// in controller.php
public function check(Request $request)
{
$c_email = $request->email;
$c_pass=$request->pass;
$c_type=$request->select;
$var=DB::select("SELECT * FROM reg where email = '$c_email' and Password = '$c_pass' and type = '$c_type'");
if ($var) {
return view('farmer')->with('user',$var);
// return redirect('farmer')->with('user',$var);
}
else {
$msg="Invalid login";
return view('index')->with('show',$msg);
}
}
If you want to actually redirect u can use the redirect() helper as statet in the official docs https://laravel.com/docs/5.3/redirects
You can also pass data
redirect('/my-route')->with(['user' => $var]);
The passed data can then be accesses through the session helper
$var = session('user')
HOWEVER, it seems like you have major issues in your code. Your password does not seem to be encrypted. Also there's no reason to use plain sql instead of eloquent here.
The route that is shown in the browser is defined in your
Route::post('/','mycontroller#check');
If you just return different views, the route does not change. You need to redirect to other views.
If you redirect to other routes you will ofcourse need to add / define them.
Route::get('/my-route', function() {}); // or post etc.
I have a filter that runs on all my controllers..
in preFilter I have:
protected function preFilter($filterChain){
Yii::app()->params->controller = Yii::app()->controller->id;
Yii::app()->params->action = Yii::app()->controller->action->id;
return true;
}
in the postFilter i have:
protected function postFilter($filterChain){
$this->controllerName = Yii::app()->params->controller ;
$this->actionName = Yii::app()->params->action;
$this->CheckTrigger();
return true;
}
The function CheckTrigger() refers to Yii::app()->params->controller and Yii::app()->params->controller.
So here is the issue.. If i have a redirect in my action this brakes. If i comment out my redirect it starts working again. It seems that when the redirect is called the Pre and Post Filter actions are also called but the Post filter is never called before the redirect is initiated.. Is there a way to ensure that the post filter is called before a redirect? Am i missing something here?
many thanks..
Try this redirect code in your controller action:
$this->redirect('url here', false);
I'm using Cake 2.1, and with it comes the new JsonView. What I'd like to do is POST to a method in my controller and render an html fragment so that I can return it as a value in json.
Previously I'd do something like this:
public function ajaxSubmit() {
if (!$this->request->is('ajax')) {
$this->redirect('/');
} else {
$this->autoRender = $this->layout = false;
$message = 'Please enter a message';
$this->set('message');
$errorFragment = $this->render('/Elements/errors/flash_error');
$toReturn = array('errorFragment' => $errorFragment);
return json_encode($toReturn);
}
}
Which only sends back the html fragment of that particular flash_error element such that I can't have multiple key => values being sent back in a standard json object. I want to be able to send both html fragments and just plain text as json.
So my question really is, how can I render an HTML element and set it with a (key=>value pair) to be sent back as json from my controller using the JsonView that Cake 2.1 provides? I already have set in my routes file Router::parseExtensions('json'); and I'm including the RequestHandler component inside of my AppController.
You shouldn't need a separate action for AJAX when using data views. Use can use the same action as your non AJAX submit.
However assuming that you wish to use a different action for AJAX because I don't know what your other action looks like, you can write something like this in app/View/ControllerName/json/ajaxSubmit.ctp.
<?php
$errorFragment = $this->element('errors/flash_error');
$toReturn = array('errorFragment' => $errorFragment);
echo json_encode($toReturn);
Then change your action to this
public function ajaxSubmit() {
if (!$this->request->is('ajax')) {
$this->redirect('/');
} else {
$message = 'Please enter a message';
$this->set('message');
}
}
See "Using a data view with view files" in the documentation.