Laravel 5.3 Method currentpage does not exist - laravel

My Pagination is not working in latest version of laravel 5.3,
I have used Paginate Method and i just wanted to know why current page method is not exist.
public function getIndex($author =null)
{
if(!is_null($author)){
$quote_author = Author::where('name', $author)->first();
if($quote_author){
$quotes = $quote_author->quotes()->orderBy('created_at','desc')->paginate(6);
}
else{
$quotes = Quote::orderBy('created_at','desc')->paginate(6);
}
return view('index',['quotes' => $quotes]);
}
$quotes = Quote::all();
return view('index',['quotes' => $quotes]);
}
<div class="pagination">
#if($quotes->currentpage() !==1)
<span class="fa fa-caret-left"></span>
#endif
#if($quotes->currentpage() !== $quotes->lastpage() && $quotes->hasPages())
<span class="fa fa-caret-right"></span>
#endif
</div>

The method name is currentPage() with a capital P.
You can learn about the other paginator methods in the documentation.
Also, in the instance the $author is null, you fall back to Quote::all() which is not paginated. Convert that to Quote::paginate(6) so that $quotes will always be an instance of a paginator.

Method name currentPage() P must be in capital letter

currentPage() is a method on the Paginator class. When you use all(), you get an instance of Collection.
What I think you want is $quotes = Quote::paginate($n); where $n is the number of results you want per page.

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>

displaying an array but it return empty

Good day, i have a laravel 5.8 project and i'm having a little problem
i have this code
public function doctor_details($doctor_id){
$doctor = DB::table('doctors')->select('specification')->where('doctor_id', $doctor_id)->get>first();
$specs_data = explode(',', $doctor_specs);
$specs_array = [];
foreach ($specs_data as $doctor_spec) {
$doctor_spec_result = DB::table('specializations')->where { return explode('speciality_id'',', $doctor_spec)->get();
foreach ($doctor_spec_result as $doctor_spec_res) {
$specs_array[] = $doctor_spec_res->speciality_name;
}
}
return view ('doctor_details', compact('doctor', 'specs_array'));
}
now if i do dd($doctor_spec_result); the result is
as you can see i'm getting an empty array but if i do dd($specs_data); the result is
as you can see there's definitely a data but i can't make it work
this is my blade
<div class="row">
<div class="col-lg-12">
<h3>{{ $doctor->doctor_name }}</h3>
</div>
<div class="col-lg-12">
#foreach( $specs_array as $spec_output )
<p>{!! $spec_output !!}</p>
#endforeach
</div>
</div>
I think you are trying to get an list only containing the values of the specification field for the particular rows queried, so that you can then get the specialty_names. You can use the pluck method on the builder to do this for you. If a search by doctor_id could return more than one result:
$doctor_specs = DB::table('doctors')
->where('doctor_id', $doctor_id)
->pluck('specification')
->transform(function ($item) { return explode(',', $item); })
->flatten();
$specs_array = DB::table('specializations')
// use whereIn to find all the rows by 'specialty_id'
->whereIn('speciality_id', $doctor_specs)
->pluck('specialty_name')
->toArray();
return view ('doctor_details', compact('doctor', 'specs_array'));
Laravel 6.x Docs - Database - Query Builder - Retrieving Results pluck
Laravel 6.x Docs - Collections - Methods - transform
Laravel 6.x Docs - Collections - Methods - flatten
Update:
Though since doctor_id is a key there will only be one, we can remove the collection methods and deal with this simpler:
$doctor_specs = explode(
',',
DB::table('doctors')->where('doctor_id', $doctor_id)
->value('specification')
);
Ideally:
Or if $doctor was retrieved with all columns from the doctors table, including specification:
$doctor_specs = explode(',', $doctor->specification);
You can simplify your code using join
$doctor_spec_result = DB::table('doctors')
->select('specializations.speciality_name')
->join('specializations','specializations.speciality_id','doctors.specification')
->where('doctors.doctor_id', $doctor_id)
->get();
return view ('doctor_details', compact('doctor', 'doctor_spec_result '));
Change in this line.
$doctor_spec_result = DB::table('specializations')->where('speciality_id', $doctor_spec)->get();
you are checking the worng attribute. As you are getting specification in 0 index.
speciality_id to specification

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>

Checking First Character of a String with Blade Template

Right now, in my controller, I'm passing some alphabetized data to my explore view.
public function browse()
{
return View::make('explore')
->with('artists', Artist::orderBy('artist', 'ASC')->get());
}
And then in the view, I'm using Blade to loop through that information.
<ul>
#foreach($artists as $artist)
<li>{{ $artist->artist }}</li>
#endforeach
</ul>
I want to run a conditional that checks the first letter of each artist so I can further group the data under the correct starting letter. How would you do that with Blade? I saw the helper "starts_with" but I'm not quite sure how to implement that into a conditional.
This logic really belongs somewhere other than the view/template layer. A View Composer could be a better location, or perhaps even a model method to return your data separated by starting letter - thus returning a hash of arrays containing artists under each letter.
Example code:
class Artist extends Eloquent
{
public static function allByFirstCharacter()
{
$artists = Artist::orderBy('artist', 'ASC')->get();
return $artists->reduce(function($sortedArtists, $artist) {
$firstChar = $artist->artist[0];
if (!isset($sortedArtists[$firstChar])) {
$sortedArtists[$firstChar] = [];
}
$sortedArtists[$firstChar][] = $artist;
return $sortedArtists;
}, []);
}
}
// Controller
$sortedArtists = Artist::allByFirstCharacter(); // Then pass it to the view
// In view
#foreach ($sortedArtists as $letter => $artists)
<!-- Some menu item or something similar here -->
#foreach ($artist as $artist)
<!-- Print out details of artist -->
#endforeach
#endforeach
Note that this example only fills in existing first characters. If you'd like to have all characters in the alphabet/numbers you'd need to prepopulate the hash and then reduce it.

model relationship and routes get model id

i have the following route:
Route::get('notes/main', function(){
$destinations = Destination::where('show', '=','1')->get();
$notes = Destination::find($destination->id)->notes()->get();
return View::make('notes.main')
->with('destinations', $destinations);
});
//the relationship models:
<?php
class Destination extends Eloquent {
public function notes()
{
return $this->has_many('Note');
}
}
<?php
class Note extends Eloquent
{
public function destination()
{
return $this->belongs_to('Destination');
}
}
//View:
#foreach( $destinations as $destination)
{{ $destination->name}}<br>
{ $notes->destination->text }} // this isn't echoed
#endforeach
what's the correct way to filter this and define $destination->id
thanks
How would i Filter the notes in an if statement inside the loop ?
#if (isset($note->title) != 'shorttext')
#else
<p> {{ $note->text }} </p>
#endif
#endforeach
You use $destination->id in your Route but it seems to be not defined yet. The question is, what do you want to achieve with your code?
With:
$destinations = Destination::where('show', '=','1')->get();
$notes = Destination::find($destination->id)->notes()->get();
you are getting only the Notes of one specific destination (so far, $destination is not defined. You could use Destination::all()->first() to get the first, or Destination::find(id), with ID being replaced with the primary key value of the destination you need).
But I guess you don't want it that way. From your Output it seems like you want to have an output with each destination and below each destination the corresponding Notes.
Controller:
//gets all the destinations
$destinations = Destination::where('show', '=','1')->get();
return View::make('notes.main')
->with('destinations', $destinations);
View:
#foreach( $destinations as $destination)
{{ $destination->name}}<br>
#foreach($destination->notes as $note)
{{ $note->text }} <br>
#endforeach
<hr>
#endforeach
Didn't test this, but this way your View would show you all your Destinations and for each Destination all the Notes.
In your route, your not sending $notes variable to the view.
How I would do it:
$destinations = Destination::where('show', '=','1')->get();
$destinations->notes = Destination::find($destination->id)->notes()->get();
Then in view:
#foreach( $destinations as $destination)
{{ $destination->name}}<br>
{{ $destination->notes->text }}
#endforeach
So first you asked a question, I gave you a correct answer.
You marked my answer as accepted, but later on you edit your initial question to add another question (for which you should create a new thread instead).
Then you create your own answer which is only answering part of your initial question and mark that as the good solution?
I could tell you why your isset and empty did not work, but why should I if you don't value my help at all?
OK
for the last part this worked out at the end
function isset and empty didn't work , strange:
#if ($note->title == 'shorttext')

Resources