Laravel - get id from the right database record - laravel

I have laravel project. When I click my view button, I want to see full description of my record. But I don't know how to pass the right id. My database table is called - csstable.
I have model:
<?php
class CssTable extends Eloquent
{
protected $table = 'csstable';
}
View button on each post (I get all of my posts from database, so each of them have id):
<div class="view">
<a href="{{ action('CssController#show') }}" ></a>
</div>
CssController with this show function:
public function show()
{
$csstable = CssTable::all();
return View::make('cssposts/right_post', compact('csstable'));
}
My Route:
Route::get('/css/id_of_right_post', 'CssController#show' );
Right_post, where I want information from description column from row, with id, that i clicked (In this field, I see just last record's description:
<h1 style="color:#fff">{{ $css->description }}</h1>
I have tried to put something like this
public function show($id)
{
$csstable = CssTable::find($id);
return View::make('cssposts/right_post', compact('csstable'));
}
But then there is an error - missing 1 argument in show function. So I want to know, how to pass correct id!

The way to do this involves three steps. First let's go for the route:
Route::get('css/{id}', 'CssController#show');
The {id} there means it's a matching parameter - it'll match a full URI segment (basically anything between slashes) and use that to pass into he method passed. So on to the controller:
class CssController
{
public function show($id)
{
$csstable = CssTable::findOrFail($id);
return View::make('cssposts/view', compact('csstable));
}
}
That controller method accepts a (required) single parameter. You can call it whatever you want, but here I'm going for id as it's an ID for a model. Finally, the last part of the puzzle is how to link to such a route:
// view button for each csstable
<div class="view">
{{ link_to_action('CssController#show', $item->title, array($item->getKey())) }}
</div>
As you can see, I'm using the link_to_action helper, but your method with <a href="{{{ action('CssController#show', array($item->getKey())) }}}"> will work too. After the controller action name, you pass an array that contains all of the parameters in the URI to fill in (in order). In our case we have one parameter, to it's an array with one item. I think in these cases you could also use a string and Laravel will turn it into an array with one element for you. I prefer to be explicit.
Hopefully that's helped you work out how to use the parameter-based routing system in Laravel.

Related

Use vue to access a Laravel model method in a v-for loop

I am learning how to use vue with laravel. I have basic loops working well to pull direct model relationships, but I can't figure out how to access model methods in a loop. Many of my Larvel models have basic information formulated with a method pulling data from related models. I've tried to research it and think the answer might be some combination of eager loading, preformating the answer as a json response or maybe something with axios, but the snipits I've found aren't clear on what goes where, or what needs to be in place for them to work correctly. I've tried both eager loading and using a json response and neither has worked. I can access methods in simple vue components that are just text, but not in a loop where the variable isn't part of the page.
Example: I want to use Vue to display a list of ingredients on a recipe's page. The ingredient "title" is a method pulling the information from a related model.
RecipeController.php
public function show(Recipe $recipe)
{
$ingredients = $recipe->ingredients;
$view = $this->view('recipes.show');
//(variable in the view, variable defined in current function)
$view->with('recipe', $recipe);
$view->with('ingredients', $ingredients);
return $view;
}
Recipe.php
public function ingredients()
{
return $this->hasMany('App\Models\Ingredient', 'recipe_id', 'recipe_id');
}
Ingredient.php
public function title()
{
$title = $this->item->title();
return $title;
}
public function vueTitle()
{
$title = Ingredient::title()->get();
return response()->json($title );
}
Recipes/show.php
<div>
<ul>
<li
is="test-li"
v-for="ingredient in {{ $ingredients }}"
v-bind:key="ingredient.ingredient_id"
v-bind:title= "ingredient.vueTitle"
v-bind:id="ingredient.ingredient_id"
></li>
</ul>
</div>
I'd prefer to reuse the same methods, but created a new one to try converting to json first but that didn't work (or I'm doing it wrong). I tried eager loading, but it either did nothing, or generated an error (Call to a member function on null) if I tried to eager load the specific method. I've tried various combinations of binding and not binding the title component. I've also tried title= "{{ingredient->title()}}" but that syntax errors.
How can I get the result of the Laravel method in a Vue loop?
After more searching, I found this post which described how to add an accessor to a model. Doing so allowed me to access my custom method as if it were a standard direct relationship. It was a straightforward modification and will reduce complexity in a number of places. I made the following modifications:
Ingredient.php
Added the get..Attribute() function and appended the array
...
protected $table = 'ingredients';
...
protected $appends = array('title');
// Access methods as direct relationships
public function getTitleAttribute()
{
return $this->title();
}
Recipes/show.php
Bound the title prop to the ingredient title as if it were a direct relationship.
<div>
<ul>
<li
is="test-li"
v-for="ingredient in {{ $ingredients }}"
v-bind:key="ingredient.ingredient_id"
v-bind:title= "ingredient.title"
v-bind:id="ingredient.ingredient_id"
></li>
</ul>
</div>
Another example, hope one may find it helpful:
Model.php
/**
* Accessor for Age.
*/
protected $appends = ['age'];
public function getAgeAttribute()
{
return Carbon::parse($this->attributes['dob'])->age;
}
VueFile.vue
<td>
<span v-bind:age="user.age"> {{user.age}} </span>
</td>

Is there any way to show post from permalink in laravel?

Normally we show single post using below method.
This is the route <a href="{{ action('TestController#index',$post ->slug) }}">
and Route::get('/test/{slug}','TestController#index');
This is the controller method
public function index(Blog $slug)
{
return $slug;
}
But I don't need like that. I have generated permalink and save it into database in slug field. Now i want to show post from this permalink. See my table
How can i do t?
just put the slug column in href.
title of post
I hope be useful

how construct route pattern for an unknown number of tags - Laravel & Conner/Taggable

I have a blog and a quotationfamous sayings repository on one site.
The quotations are tagged and the entries are tagged too.
I use this rtconner/laravel-tagging package.
Now, what I want to do is to display ALL Quotation models which share the same tags as article.
The Eloquent syntax is simple, as the original docs provide an example:
Article::withAnyTag(['Gardening','Cooking'])->get();
possible solution
Optional routing parameters. The asker-picked answer in this question gives a solution:
//in routes.php
Route::get('/{book?}/{chapter?}/{topic?}/{article?}', 'controller#func');
//in your controller
public function func($book = null, $chapter = null, $topic = null, $article = null) {
...
}
my problem
In my app the shared tags might count more than 3 or 5. I will soon get an example with even 10 tags. Possibly more
My question
Does it mean that I have to construct an URL with 10 optional routing parameters? Do I really need sth like this:
Route::get('quotations/tags/{tag1?}/{tag2?}/{tag3?}/{tag4?}/{tag5?}/{tag6?}/{tag7?}', 'controller#func');
my question rephrased
I could create a form with only a button visible, and in a hidden select field I could put all the tags. The route would be a POST type then and it would work. But this solution is not URL-based.
I think you could process the slashes, as data:
Route::get('quotations/tags/{tagsData?}', 'controller#func')
->where('tagsData', '(.*)');
Controller:
public function controller($tagsData = null)
{
if($tagsData)
{
//process
}
}
Ok, this is my solution. As I have a tagged model, I dont't need to iterate through tags in url to get the whole list of tags.
The enough is this:
// Routes file:
Route::get('quotations/all-tags-in/{itemtype}/{modelid}', 'QuotationsController#all_tagged_in_model');
Then in my controller:
public function all_tagged_in_topic($itemtype, $id) {
if($itemtype == 'topic') {
$tags = Topic::find($id)->tags->pluck('name')->all();
$topic = Topic::find($id);
}
if($itemtype == 'quotation') {
$tags = Quotation::find($id)->tags->pluck('name')->all();
$quotation = Quotation::find($id);
}
// dd($tags);
$object = Quotation::withAnyTag($tags)->paginate(100);;
And it is done.
Now, the last issue is to show tags in the URL.
TO do that, the URL should have an extra OPTIONAL parameter tags:
// Routes file:
Route::get('quotations/all-tags-in/{itemtype}/{modelid}/{tags?}', 'QuotationsController#all_tagged_in_model');
And in the {url?} part you can just write anything which won't break the pattern accepted by route definition.
In your view you might generate an URL like this:
// A button to show quotes with the same set of tags as the article
// generated by iteration through `$o->tags`
<?php
$manual_slug = 'tag1-tag2-tag3-tag4`;
?>
<a href="{{ URL::to('quotations/all-tags-in/article/'.$o->id.'/'.$manual_slug) }}" class="btn btn-danger btn-sm" target="_blank">
<i class="fa fa-tags icon"></i> Tagi:
</a>

Laravel : How to hide url parameter?

Here the scenario is I want to pass a variable which will be send from one page to another and in next page it's gonna store through a form. So I have passed the variable from first page to second page through the URL. But I want to hide the parameter in the URL. How do I do it?
Here is my route :
Route::get('/registration/{course_id}',[
'uses'=>'AppController#getregistration',
'as'=>'registration'
]);
And Controller :
public function getregistration($course_id)
{
return view('index')->with('course_id',$course_id);
}
And first page this is how I send the value to first page:
<li> A </li>
Post Method
Route
Route::post('/registration',['uses'=>'AppController#getregistration','as'=>'registration']);
View
{!!Form::open(array('url' => '/registration')) !!}
{!! Form::hidden('course_id', '1') !!}
{!! Form::submit('registration') !!}
{!! Form::close() !!}
Controller
public function getregistration(Request $request)
{
$course_id = $request->input('course_id');
return view('index')->with('course_id',$course_id);
}
Get method
use encryption method, it will show encrypted id in url
View
<li> A </li>
Controller
public function getregistration($course_id)
{
$course_id = Crypt::decrypt($course_id);
return view('index')->with('course_id',$course_id);
}
here is no way you hide parameter in url, rather then you convert parameter value encrypt or hash is up to you,
other-way is save value in session first, then call the value from session without define parameter in url.
because laravel route only working to pattern of url /string /id, post get. dynamic value you must be writing / getting using pattern method.
Thanks.
You cannot hide a parameter in URL. If you don't want to show the ID then try using SLUG. I hope you understand what is a SLUG. If you don't then here it is. If you course title is My new Course Title then its slug would be my-new-course-title. And make sure it is unique like an ID in the table. It is also good for SEO, readable and looks good.

Laravel Sub-menu Within View

Hi I am very new to Laravel and MVC frameworks in general and am looking to create a list of links (in a view within a template) that links to some content. I am using this to display a list of nine people and to display their profile description when the link is clicked on. I have created a model of what the page looks like at http://i.imgur.com/8XhI2Ba.png. The portion that I am concerned with is in blue. Is there a way to route these links to something like /about/link2 or /about?link2 while maintaining the same exact page structure but modifying the ‘link content’ section (on the right of the link menu) to show the specific link's content? I would greatly appreciate it if someone could point me in the right direction, as I have literally no clue where to go with this!
There are a couple ways you can go about doing this.
Templates
Create your route.
Im assuming a lot about your app here but hopefully you get the picture. If you need help with anything in particular, be sure to update your question with the code youve tried so it will be easier to help you.
Route::get('about/{page}', function($page)
{
$profile = Profile::where('name', $page)->first();
return View::make('about')->with('profile', $profile);
});
Modify Template.blade.php
Put this line where you wish for About.blade.php to appear.
#yield('content')
Create your view which will extend your template
#extends('Template')
#section('content')
<h2>User Profile</h2>
<ul>
<li>Name: {{ $profile->name }}</li>
<li>Last Updated: {{ $profile->updated_at }}</li>
</ul>
#stop
AJAX
This solution will utilize AJAX to grab the data from the server and output it on the page.
Route for initial page view
Route::get('about', function($page)
{
$profiles = Profile::all();
return View::make('about')->with('profiles', $profiles);
});
Feel free to follow the same templating structure as before but this time we need to add some javascript into the template to handle the AJAX. Will also need to id everything which needs to be dynamically set so we can easily set it with jquery.
#extends('Template')
#section('content')
<h2>Links</h2>
#foreach($profiles as $profile)
{{ $profile->name }}
#endforeach
<h2>User Profile</h2>
<ul>
<li>Name: <span id="profile_name">{{ $profile->name }}</span></li>
<li>Last Updated: <span id="profile_updated_at">{{ $profile->updated_at }}</span></li>
</ul>
<script>
function setProfile(a)
{
$.ajax({
method: 'get',
url: 'getProfile',
dataType: 'json',
data: {
profile: $(a).data('id')
},
success: function(profile) {
$('#profile_name').html(profile.name);
$('#profile_updated_at').html(profile.updated_at);
},
error: function() {
alert('Error loading data.');
}
});
}
</script>
#stop
Route to handle the AJAX request
Route::get('getProfile', function()
{
$profile_id = Input::get('profile');
$profile = Profile::find($profile_id);
return $profile->toJson();
});
Now, the page should not have to reload and only the profile information should be updated.
Making some assumptions here as no code posted and assuming you're using the latest version of Laravel, Laravel 5.
Lets say you have a table in your database named users and you have a Model named Users (Laravel 5 comes with the Users model as default, see app/Users.php). The users will be the base of our data for the links.
Firstly, you want to register a route so you can access the page to view some information. You can do this in the routes file. The routes file can be found here: app/Http/routes.php.
To register a route add the following code:
Route::get('users', ['uses' => 'UserController#index']);
Now what this route does is whenever we hit the URL http://your-app-name/public/users (URL might be different depending on how you have your app set up, i.e. you may not have to include public) in our web browser it will respond by running the index method on the UserController.
To respond to that route you can set up your UserController as so:
<?php namespace App\Http\Controllers;
class UserController extends Controller {
public function index()
{
}
}
Controllers should be stored in app/Http/Controllers/.
Now lets flesh out the index method:
public function index()
{
// grab our users
$users = App\Users::all();
// return a view with the users data
return view('users.index')->with('users');
}
This grabs the users from the database and loads up a view passing the users data.
Here's what your view could look like:
<!DOCTYPE html>
<html>
<head>
<title>Users Page</title>
</head>
<body>
#foreach($users as $user)
<a href="{{ URL::route('user', ['id' => $user->id]) }}">
{{ $user->username }}
</a>
#endforeach
</body>
</html>
The view code will loop through each user from the $users data we passed to the view and create a link to their user page which is different for each user based on their id (their unique identifier in the DB)
Due to the way I've named it, this would be found in app/views/users/index.blade.php - if you save files ending in blade.php you can use Laravel's templating language, blade.
Now you need to finally set up another route to respond to a user page, for example http://your-app-name/public/user/22.
Route::get('user/{id}', ['uses' => 'UserController#show']);
Then add the show method to UserController
public function show($id)
{
// this will dump out the user information
return \App\User::find($id);
}
Hope that helps a little! Wrote most of it off the top of my head so let me know if you get any errors via comment.
This question is very bare, and it is difficult to actually help your situation without you showing any code. Just to point you in the right direction though, here is what you would need.
A Model called People, this is how you will access your data.
A controller. In this controller you will do the following
Get the ID of the profile you want from the functions parameters
Find that persons information e.g. People::find($person_id);
return the profile view with that persons data e.g. return view('profile')->with('person', $person);
In your view you can then use that data on that page e.g. {{ $person->name }}
For the page that needs to display the links to the people you would have a method in your controller which..
Get all the people data e.g. People::all();
Return a view with that data return view('all-people')->with('people', $people);
You will then need a route to access an individual person. The route will need to pass the persons ID into a controller method e.g.
Route::get('get-person/{id}',
[ 'as' => 'get-person',
'uses' => 'PeopleController#getPerson' ]);
You can then use this route in your view to get the links to each person
#foreach($people as $person)
{{$person->name}}
#endforeach
This would produce the list of links you want.

Resources