Multiple optional parameter ordering issues - php

I want Result like:
Route::get('blogs', 'Blogs#index')->name('blogs');
Route::get('blogs/{section?}/{category?}', 'Blogs#index');
example:
Blogs/
Blogs/section
Blogs/category
Controller :
public function index($section= '', $category= '', Request $request)
{
}
When i pass second para controller take it as first ( section )

The only way you could do this is to check if the input matches a section or category and then call the right controller.
For example:
Route::get('blogs/{slug}', function ($slug) {
// Check if this is a section
if (SectionModel::where('slug', $slug)->first()) {
return \App::call('\App\Http\Controllers\Sections#index');
}
// Check if this is a category
if (CategoryModel::where('slug', $slug)->first()) {
return \App::call('\App\Http\Controllers\Categories#index');
}
// Section or category doesn't exist
abort(404);
});

The order matters. Use this instead:
Route::get('blogs/{section?}/{category?}', 'Blogs#index');
Route::get('blogs', 'Blogs#index')->name('blogs');
UPDATE:
Why not pass as GET parameter the things that you are looking for? Doing so, you just need to check inside the index() function if you have any of them, and act according to them:
Route::get('blogs', 'Blogs#index')->name('blogs');
example:
Blogs?section=any-section&category=any-category
Controller:
public function index(Request $request): Response
{
if ($request->section) {/**/}
if ($request->category) {/**/}
// ...
}

Related

PHP/Laravel, url with multiples arguments

I'm building a Laravel app, and I need to use an URL that looks like that :
/api/ads?page=Actuel&formatsQuery[]=side&formatsQuery[]=leaderboard&deviceQuery=mobile
I have 3 parameters (page, formatsQuery (as an array), and deviceQuery).
Do you now how to hold his in routing and controller in order to have the correct value inside the controller's fonction?
I tried this :
routes/api.php
//request to get ads for given parameters
Route::get('/ads', [MediaController::class, 'findAds']);
and this (MediaController.php) :
public function findAds($page, $formatsQuery, $deviceQuery) {
echo $page;
if(sizeof($formatsQuery) <= 0 || sizeof($formatsQuery) > 3){
return $this->unvalidParametersError();
}
//transform format to position depending on deviceQuery
$position = [];
$res = [];
foreach ($formatsQuery as $format) {
$res = Media::where('position', $format)->inRandomOrder()->first()->union($res);
}
echo $res;
return $res;
}
then I test it with this :
public function test_findAds()
{
$ads = Ad::factory()
->has(Media::factory()->count(3), 'medias')
->count(3)->create();
$response = $this->get('/api/ads?page=Actuel&formatsQuery[]=side&formatsQuery[]=leaderboard&deviceQuery=mobile');
$response->assertStatus(200);
}
You are using a GET request to fetch your data. GET request is a type of request that you send parameters in URL using ? after URL and separating parameters with &. You can find out more about HTTP methods here.
In laravel using request parameters is so simple. First of all you need to add Request $request to your method prototype like this:
use Illuminate\Http\Request;
public function findAds(Request $request)
Then you can simply use $request->parameter to get the values. So you need to change your code like this:
public function findAds(Request $request){
$page = $request->page;
$formatsQuery = $request->formatsQuery;
$deviceQuery = $request->deviceQuery;
// Your code
}
And as #matiaslauriti mentioned in the comments you don't need to put [] after formatsQuery[] to send an array in GET request. Using the same key more than one time automatically makes an array for you.

How to send response from another function without redirecting Laravel

I have a route like this
Route::get('/downloadReport', 'ReportsController#downloadPdf')->name('downloadReport');
In ReportsController in the function downloadPdf I want to switch respond function as based on input parameter reportType
public function downloadPdf(Request $request){
$id = $request->input('reportType');
// some statements are there
switch($id){
case 1:
$this->createReportType1($jobId, $cusName);
break;
}
}
and the response should be delivered to the user via this function
public function createReportType1($jobId, $cusName){
$pdf = PDF::loadView('reports.reports',
compact(
'jobId',
'cusName'
)
);
return $pdf->download('invoice.pdf');
}
but I didn't get any output by doing this.. what is the reason and how should I achieve this without returning a value from createReportType1 to downloadPdf function
Try this (I add return keyword):
case 1:
return $this->createReportType1($jobId, $cusName);

Protect routes dynamically, based on id (laravel, pivot table)

This topic has been discussed a lot here, but I don't get it.
I would like to protect my routes with pivot tables (user_customer_relation, user_object_relation (...)) but I don't understand, how to apply the filter correctly.
Route::get('customer/{id}', 'CustomerController#getCustomer')->before('customer')
now I can add some values to the before filter
->before('customer:2')
How can I do this dynamically?
In the filter, I can do something like:
if(!User::hasAccessToCustomer($id)) {
App::abort(403);
}
In the hasAccessToCustomer function:
public function hasCustomer($id) {
if(in_array($id, $this->customers->lists('id'))) {
return true;
}
return false;
}
How do I pass the customer id to the filter correctly?
You can't pass a route parameter to a filter. However you can access route parameters from pretty much everywhere in the app using Route::input():
$id = Route::input('id');
Optimizations
public function hasCustomer($id) {
if($this->customers()->find($id)){
return true;
}
return false;
}
Or actually even
public function hasCustomer($id) {
return !! $this->customers()->find($id)
}
(The double !! will cast the null / Customer result as a boolean)
Generic approach
Here's a possible, more generic approach to the problem: (It's not tested though)
Route::filter('id_in_related', function($route, $request, $relationName){
$user = Auth::user();
if(!$user->{$relationName}()->find($route->parameter('id')){
App::abort(403);
}
});
And here's how you would use it:
->before('id_in_related:customers')
->before('id_in_related:objects')
// and so on

Laravel 4 Route Paramater use only some on given links

I understand that when you do this in Laravel:
Route::get('news/read/{year}/{month}/{date}/{title}/{id}', 'PageController#index_page');
We can use all {var} name as parameters in the controller. But how if I only want to use {id} and {title} instead of all of them in the controller?
This is currently my controller:
public function index_page($year=null, $month=date, $date=null, $title=null, $id=null) {
$plugin_files = $this->addJqueryPlugin(array('unslider'));
$data['css_files'] = $this->addCSS(array('styles'));
$data['js_files'] = $this->addJS(array('main'), false);
$data['css_plugin'] = $plugin_files['css_files'];
$data['js_plugin'] = $plugin_files['js_files'];
if (is_null($id)) {
$data['title'] = 'Homepage';
$this->layout->content = View::make('page.home', $data);
}
else {
$data['isModal'] = true;
$data['title'] = ucwords(str_replace("-", " ", $title . '--' . $id));
$this->layout->content = View::make('page.home', $data);
}
}
I tried putting only $title and $id but it reads from {year} and {month} instead. Only solution I can think of is change the order of the route to news/read/{title}/{id}/{year}/{month}/{date}, but I'm trying to keep the format like the previous one, is it possible?
Firstly, this seems wrong
public function index_page($year=null, $month=date, $date=null, $title=null, $id=null)
Remember that the order of default parameters must be as last parameters of function - check PHP Manual example here for details. I assume you misspelled $month=date for $month='some_default_date_value' ?
Second, answering your questions, you've got at least 2 options here:
A. routing to different methods for different parameter count or order
//Routes
//different routes for different params
Route::get('news/read/{year}/{month}/{date}/{title}/{id}', 'PageController#indexFull');
Route::get('news/read-id/{id}/{title}', 'PageController#indexByIdAndTitle');
Route::get('news/read-some-more/{month}/{date}/{id}/{title}/{year}', 'PageController#indexByWeirdParamsOrder');
//Controller
//different methods for different routes
public function indexByIdAndTitle($id, $title){ return $this->indexFull($id,$title); }
public function indexFull($id, $title, $year=null, $month=null, $date=null) { ... }
public function indexByWeirdParamsOrder($month, $date, $id, $title, $year) { ... }
B. changing the parameters order in route and using optional param / default value
//Routes
Route::get('news/read/{id}/{title}/{year?}/{month?}/{date?}', 'PageController#indexFull');
//Controller
public function indexFull($id, $title, $year=null, $month=null, $date=null) { ... }
Last but not least, check the Laravel docs for routing and parameters.

How does codeigniter know how to pass parameters from controller to the model

I am starting to learn codeigniters active record and i am querying my database using parameters passed from the controller to the model.
First i am passing the id from the controller to the model and that works.
Controller
function bret($id){
$this->load->model('school_model');
$data = $this->school_model->get_city_and_population($id);
foreach ($data as $row)
{
echo "<b>Name Of The City</b>...........". $row['Name'];
echo "<br/>";
echo "<b>Total Population</b>...........".$row['Population'];
}
}
Model
function get_city_and_population($id){
$this->db->select('Name,Population');
$query = $this->db->get_where('city', array('ID'=>$id));
return $query->result_array();
}
I went ahead and put in multiple parameters expecting to fail but this works but i am not so sure why it worked or what worked.
Controller
public function parameters($id,$name,$district){
$this->load->model('school_model');
$data = $this->school_model->multiple_parameters($id,$name,$district);
foreach ($data as $row)
{
echo "<b>Total Population</b>...........".$row['Population'];
}
}
Model
function multiple_parameters($id,$name,$district){
$this->db->select('Population');
$query = $this->db->get_where('city', array('ID'=>$id,'Name'=>$name,'District'=>$district));
return $query->result_array();
}
In my multiple parameters example i visited http://example.com/env/at/index.php/frontpage/parameters/7/Haag/Zuid-Holland/
Here,i know the name Haag is in id 7 and the district is Zuid-Holland
Here are my questions.How does codeigniter know how to pass the parameters from the url to the model and secondly,what if i was slightly wrong like 7/Haag/Zuid-Hollandes/,how would i show the user that,that url is wrong and fallback to a default value instead of showing blank when the parameters are wrong?.
//In codeiginter URI contains more then two segments they will be passed to your function as parameters.
//if Url: http://example.com/env/at/index.php/frontpage/parameters/7/Haag/Zuid-Holland/
//Controller: forntpage
public function parameters($id,$name,$district){
echo $id.'-'$name.'-'.$district;
}
//and if you are manually getting url from segment & want to set default value instead of blank then use following:
public function parameters(
$this->load->helper("helper");
$variable=$this->uri->segment(segment_no,default value);
//$id=$this->uri->segment(3,0);
}
//or
//Controller: forntpage
public function parameters($id='defaultvalue',$name='defaultvalue',$district='defaultvalue'){
echo $id.'-'$name.'-'.$district;
}
That's just simple uri mapping in CI, or uri param binding if you will.
When you have a method like:
public function something($param1, $param2) {
// get from: controller/something/first-param/second-param
}
That means your uri segments are passed as arguments to your controller method.
The above method could be written as:
public function something() {
$param1 = $this->uri->segment(3);
$param2 = $this->uri->segment(4);
// segment 1 is the controller, segment 2 is the action/method.
}
You need to understand that you have to manually check if the uri segments are exactly what you want them to be, as CI doesn't do anything else than this mapping.
Next, if you want to have some defaults, following statement is true:
public function something($param1 = 'some default value', $param2 = 'other value') {
// get from: controller/something/first-param/second-param
}
That is, if a url like: /controller/something is passed along, you will still get your default values back. When controller/something/test is passed, your first param is overridden by the one from the url (test).
That's pretty much it.

Categories