I've got a problem with model's method with parameters. I've got 2 Page and ContentTranslation. I want to get ContentTranslation based on language, so I've got following method in Page model:
public function contentTranslations($language) {
return $this->hasMany('App\ContentTranslation')->where('language', $language);
}
and then I've got a method in PageController for getting the pages based on language:
public function getPagesByLanguage($language)
{
$pages = Page::orderBy('position', 'asc')->get();
foreach ($pages as $page) {
$page->contentTranslations($language);
}
$return $pages;
}
I'm returning my results in JSON format (I'm using Laravel as an api). But this approach doesn't work. It throws me error:
Call to undefined method Illuminate\Database\Query\Builder::contentTranslations()
Some time ago, I wanted to return contentTranslations for all languages, so I haven't got a parameter in contentTranslations model method and everything worked fine after calling $page->contentTranslations; in foreach loop. Why I've got the trouble with passing parameter into method?
You should use eager loading to avoid N+1 query problem:
public function getPagesByLanguage($language)
{
return Page::with(['contentTranslations' => function($q) use ($language) {
$q->where('language', $language);
}])
->orderBy('position', 'asc')
->get();
}
Also change your relation to:
public function contentTranslations() {
return $this->hasMany('App\ContentTranslation');
}
Related
I have the following error.
Too few arguments to function Illuminate\Support\Collection::get()
public function upteamLogs(Request $request)
{
$logs = DB::table('upteam_product_logs');
if ($request->from_date != '' && $request->to_date != '') {
$logs->whereBetween('created_at',
array($request->from_date, $request->to_date));
}
$logs->orderBy('id', 'desc')->paginate(30)->get();
return view("product-inventory.upteam_logs", compact('logs'));
}
the method paginate and simplePaginate of the laravel Illuminate\Database\Query\Builder class return respectively and instance classes which have implemented Illuminate\Contracts\Pagination\LengthAwarePaginator or Illuminate\Contracts\Pagination\Paginator interface and those interfaces havent define get method that's main reason of the error.
You should just return the reassign the result of the paginate call directly to the $log variable like this
$logs = $logs->orderBy('id', 'desc')->paginate(30);
This will fix your error and you can loop through logs into your product-inventory.upteam_logs view without any problem
I'm trying to add the piece of code from How to get the id of youtube videos in laravel into my Controller.
Error:
Indirect modification of overloaded property App\Gallery::$link has no
effect
GalleryController:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Gallery;
class GalleryController extends Controller
{
//
public function galleryAll()
{
$gallery = Gallery::orderBy('date', 'desc')
->get()
->map(function ($gallery) {
$gallery->link = parse_str( parse_url( $gallery->link, PHP_URL_QUERY ), $gallery->link );
return view('gallery', ['gallery' => $gallery]);
});
}
}
I'm unsure on how to save it to the $gallery-link. I'm planning on doing a #foreach in the View, and I want all the $gallery-link to be modified to only contain the youtube video code.
Update:
Controller
class GalleryController extends Controller
{
//
public function galleryAll()
{
return Gallery::orderBy('date', 'desc')
->get()
->map(function ($gallery) {
return view('gallery', ['gallery' => $gallery]);
});
}
}
Page gives me:
[{},{},{},{},{},{},{},{},{},{},{},{},{}]
Using
$gallery = Gallery::orderBy('date', 'desc')
gives me blank page.
Returning the view should be the last part of your controller method.
map() basically takes the collection, loops through it and allows you to edit each iteration of the loop (each item in the collection) which in your case will be an instance of the Gallery model. So, what you're actually doing in you code is replacing each Gallery instance with an instance of Illuminate\View\View and then returning a collection of that.
As for the "Indirect modification of overloaded property" error you're getting have a look at: Indirect Modification of Overloaded Property Laravel MongoDB
I would suggest using an Accessor for this. In your Gallery model add the following:
public function getYoutubeIdAttribute()
{
parse_str( parse_url( $this->link, PHP_URL_QUERY ), $query);
return $query['v'];
}
Then your controller would just be something like:
public function galleryAll()
{
$gallery = Gallery::orderBy('date', 'desc')->get();
return view('gallery', compact('gallery'));
}
And finally in your view you can simply access the youtube_id like:
#foreach($gallery as $g)
{{ $g->youtube_link }}
#endforeach
you can't using: $gallery->link = parse_str($str, $gallery->link)
parse_str($str, $output);//output array
because $gallery->link is string
you see:http://php.net/manual/en/function.parse-str.php
I have a Card model which has many notes. And each note has an author. I am eager loading an individual card in a show action in my CardsController like so:
$card = $card->load(['notes' => function($query){
$query->orderBy('created_at', 'desc')->limit(8);
}, 'notes.author']);
This query works. I want to now refactor this into a model scope so I can just call $card = Card::popular() in my controller. So add this method to my Card model:
public function scopePopular()
{
$results = $this->with(['notes' => function($query){
$query->orderBy('created_at', 'desc')->limit(8);
}, 'notes.author']);
return $results;
}
This messes up everything. I start getting unreadable template errors, when nothing should really break.
What am I doing wrong?
In order to use it as a static function and still be able to access the static methods within the class, use self:: instead of $this->.
public function scopePopular()
{
$results = self::with(['notes' => function($query){
$query->orderBy('created_at', 'desc')->limit(8);
}, 'notes.author']);
return $results;
}
To avoid duplicate code, I would like to create a function eagerLoading() in my eloquent model. Here is my code:
Model Product:
public function scopeActive($query)
{
return $query->where('active', 1);
}
public function eagerLoading($query)
{
return $query->with([
'owners',
'attributes',
'prices' => function ($query)
{
$query->orderBy('created_at', 'desc');
$query->distinct('type');
}
]);
}
MyController:
$products = Product::active()->eagerLoading()->paginate(100);
return $this->response->withPaginator($products, $this->productTransformer);
But when using this, I have this error : Call to undefined method Illuminate\Database\Query\Builder::eagerLoading().
How should I use my function?
Your eagerLoading() method is just another scope, like your scopeActive() method. In order to do what you want, you need to rename it to scopeEagerLoading().
Right now, Product::active() is returning an Eloquent Query Builder. You are then trying to call eagerLoading() on that, and the method doesn't exist. By prefixing the method with scope, it tells the query builder to call the method on the Model for which it is querying.
From the documentation:
"To define a scope, simply prefix an Eloquent model method with scope."
Check documentation at: https://laravel.com/docs/5.1/eloquent#query-scopes
So you need to rename your method to have "scope" at the beginning.
Change public function eagerLoading($query) to be public function scopeEagerLoading($query)
Route
Route::get('/site/{site_name_en}/{id}', array(
'as' => 'profile-site',
'uses' => 'ProfileController#site'
));
Controller
class ProfileController extends BaseController{
public function site($id, $site_name_en){
$site = Site::where('id', '=', $id)
->where('site_name_en', '=', $site_name_en);
if($site->count()){
$site = $site->first();
return View::make('profile.site')
->with('site', $site);
}
return App::abort(404);
}
}
What I'm trying to achieve is: that when I visit the following URL www.domain.com/site/abc/123456, it will shown the correct page based on the parameters. Is the where clause correct? (because I couldn't retrieve the value)
Your route
Route::get('/site/{site_name_en}/{id}',
says the 1st parameter is site name, the second the id, but your controller function has the arguments swapped. You should call it:
public function site($site_name_en, $id){
// rest of code
}
parameters are automatically passed down in the order they are defined by the route, and are not recognized by the variable name (IIRC).
As for the rest of your function I can't really tell if you're doing right or not, but I can suggest this:
$site = Site::where('id', '=', $id)
->where('site_name_en', '=', $site_name_en)
->first();
if($site){
return View::make('profile.site');
}
return App::abort(404);
Alternatively, you could use firstOrFail(), which throws a ModelNotFoundException if the record is not found that you can catch with App::error() for example (an implementation is outlined in the manual)