Laravel 5 pagination Call to a member function render() on a non-object - pagination

I am trying to paginate some categories and this error popped up from nowhere and I don't know how to fix it :
Call to a member function render() on a non-object
This is my controller:
public function getFilmeByCateg()
{
$categorii = Categorii::all();
//$Movies = Movies::all();
$categorie = Request::segment(2);
$cat = Categorii::where('denumire', '=',$categorie)->first();
$cat2 = Categorii_filme::where('categorie_id', '=' ,$cat->categorie_id)->get();
$filme = array();
foreach($cat2 as $filmulet)
{
$film = Movies::where('movie_id','=',$filmulet->film_id)->paginate(12)->first();
$filme[] = $film;
}
return view('filme')->with('Movies',$filme)->with('categorii',$categorii);
}
And this is how I render the paginator in my layout:
{!!$Movies->render() !!}
This is in my routes:
Route::get('categorie/{categorie}','WelcomeController#getFilmeByCateg');
This is in my Movies.php:
class Movies extends Model {
protected $table = "movies";
}
Can someone tell me how can I manage to make this work ?

Since $filme is an array, you can access render() method whose object you wanted is $Movies which is array.
foreach($cat2 as $filmulet)
{
$film = Movies::where('movie_id','=',$filmulet->film_id)->paginate(12)->first();
$filme[] = $film;
}
Here $filme is an array.
return view('filme')->with('Movies',$filme)->with('categorii',$categorii);
Here you passed $filme as $Movie variable.
{!!$Movies->render() !!}
And here you wanted to access render() method of $filme which is not an object.
Change your controller to this:
public function getFilmeByCateg()
{
$categorii = Categorii::all();
//$Movies = Movies::all();
$categorie = Request::segment(2);
$cat = Categorii::where('denumire', '=',$categorie)->first();
$movie_ids = Categorii_filme::where('categorie_id', '=' ,$cat->categorie_id)->get()->lists('movie_id');
$filme = Movies::whereIn('movie_id','=',$movie_ids)->paginate(12);
return view('filme')->with('Movies',$filme)->with('categorii',$categorii);
}

OK First of all, you made it the wrong way.
Using an intermediate class for representing the pivot table is completely bad.
I'll make it work for you.
Your Category class
class Category extends \Model {
protected $table = 'categories';
public function movies()
{
return $this->belongsToMany('Your\Namespace\To\Movie');
}
}
Your Movie class
class Movie extends \Model {
protected $table = 'movies';
public function categories()
{
return $this->belongsToMany('Your\Namespace\To\Category');
}
}
Your route is still :
Route::get('categorie/{category_id}','WelcomeController#getFilmeByCateg');
So in your controller method you do the following :
public function getFilmeByCateg($category_id)
{
$category = Category::findOrFail($category_id);
return view('filme')->with('Movies',$category->movies()->paginate(12)->ge())->with('categorii',Category::all());
}
Now in your view $Movies->render() will work

If you wont paginate your data how would you render it ? Documents on the official laravel website states :
There are several ways to paginate items. The simplest is by using the paginate method on the query builder or an Eloquent model.
Paging database results
$users = DB::table('users')->paginate(15);
Note: Currently, pagination operations that use a groupBy statement cannot be executed efficiently by Laravel. If you need to use a groupBy with a paginated result set, it is recommended that you query the database and create a paginator manually.
Creating A Paginator Manually
Sometimes you may wish to create a pagination instance manually,
passing it an array of items. You may do so by creating either an
Illuminate\Pagination\Paginator or
Illuminate\Pagination\LengthAwarePaginator instance, depending on your
needs.
Now in your case you should first
use Illuminate\Pagination\LengthAwarePaginator as Paginator;
and then
$paginator = new Paginator($items, $count, $limit, $page, [
'path' => $this->request->url(),
'query' => $this->request->query(),
]);
Please supply parameters accordingly in the Paginator function above.

I know it is very late but it will help someone who get in to same issue. Instead of ->get() use ->paginate(10) in query.

Related

CS1646 Keyword, identifier, or string expected after verbatim specifier: #

tables in my EntityFramework model are events, eventtypes, subevents, subeventtypes
using the MVC5 builders (right click on controllers, add, add controller) I created controllers and views for the last three tables without issue however when I create the controller and views for the events entity I produce the following errors
Keyword, identifier, or string expected after verbatim specifier: #
'EventType' is a type, which is not valid in the given context
the code that was generated in the event controller is
{
private Entities db = new Entities();
// GET: Events
public ActionResult Index()
{
var events = db.Events.Include(# => #.EventType); ERROR HERE
return View(events.ToList());
}
any help with this issue would be greatly appreciated
TIA
I experienced the same issue when using the "MVC Controller with views, using Entity Framework" template.
var #group = await _context.Groups
.Include(# => #.Company)
.FirstOrDefaultAsync(m => m.GroupId == id);
My workaround was simple to replace the # symbol with another character i.e. g
var #group = await _context.Groups
.Include(g => g.Company)
.FirstOrDefaultAsync(m => m.GroupId == id);

Laravel Eloquent relationship query not working

I am attempting to build a query where a product is updated via an API. The application is built in Angular2 wrapped in a NodeJS layer.
A product has a many-to-many relationship with files. What I want to happen is that when data is sent to the API to update a file, a Eloquent query checks whether this relationship already exists and if not it adds a relationship into the 'file_product' table. I have this functionality working fine with a category many-to-many relationship but for some reason this is not working on the files relationship. here is my code:
Product Controller update function:
public function update(Request $request, $id)
{
if($id && is_numeric($id)) {
try {
$requestProductVars = $request->get('product');
$product = Product::find($id);
$product->title = $requestProductVars['title'];
$product->description = $requestProductVars['description'];
$product->images = json_encode($requestProductVars['images']);
$product->SKU = $requestProductVars['SKU'];
$product->manufacturer_id = $requestProductVars['manufacturer_id'];
$product->active = (($requestProductVars['active'] === true) ? '1' : '0');
if($request->get('categories')) {
$categories = $request->get('categories');
foreach($categories as $categoryId) {
$category = Category::find($categoryId);
if(!$product->categories->contains($category)) {
$product->categories()->save($category);
}
}
}
if(count($requestProductVars['files'])) {
$files = $requestProductVars['files'];
foreach($files as $file) {
$fileId = $file['id'];
$fileRecord = File::find($fileId);
if(!$product->files->contains($fileRecord)) {
$product->files()->save($fileRecord);
}
}
}
$product->save();
As you can see, I check to see if there is a 'files' property on the request and if there is I loop through each file, get the id and check if the relationship exists using:
if(!$product->files->contains($fileRecord)) {
The files property contains an array of File objects.
My code seems to stop here and doesn't even seem to execute if. The category functionality works fine in this code though which is odd and I am doing exactly the same thing here.
I checked the models for Product and File and the many-to-many relationships are defined here fine:
Product.php
/**
* Returns all files associated with a product
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function files() {
return $this->belongsToMany('App\File')->withTimestamps();
}
File.php
/**
* Returns all products related to a file
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function products() {
return $this->belongsToMany('App\Product')->withTimestamps();
}
Can anyone see why my code doesn't seem to be working?
Thanks
Ok I discovered what the problem was.
Before I abstracted out the files to products functionality I had a cell in the products table called 'files'. I had forgotten to delete this cell and this was causing a conflict when I was trying to query the files relationship. Hope this helps someone in the future.

TableController and Odata Query

In a small Azure Mobile App, I have the following GET method in a tablecontroller:
public IQueryable<User> GetAllUser()
{
return Query();
}
using the following REST call, I can query users with the lastname='Tiger'
GET: ~/userinfo?$filter=lastName%20eq%20'Tiger'
Now I'd like to add an organisation fields to my user, so I've changed the get method to:
public IQueryable<UserDto> GetAllUser()
{
return Query().Select(u => new UserDto{FirstName=u.FirstName, LastName=u.LastName, Organisation="Acme"});
}
but now, when I try to query my users, using the same filter:
GET: ~/userinfo?$filter=lastName%20eq%20'Tiger'
I get an 'Bad Request' error....
How can I make this work...
Any help would be greatly appreciated....
Try:
public IQueryable<UserDto> GetAll()
{
return Query().AsEnumerable().Select(u =>
new UserDto
{
FirstName = u.FirstName,
LastName = u.LastName,
Organisation = "Acme"
}).AsQueryable();
}
Your ODATA query will be used on the DTO and not the entity.
Your Controller should still use TableController<User>.
You could also use AutoMapper and simply do:
return Query().ProjectTo<UserDTO>();
This will do LINQ to Entities.
Your post helped me solve my own issue!
From what I can tell, it doesn't work because when you're using DTO objects and MappedEntityDomainManager, this.Query() call crashes. In my case, both my Model and DTO object inherit from Azure.Mobile.Server.EntityData.
Basically... avoid this.Query() with MappedEntityDomainManager
Try this:
public IQueryable<UserDto> GetAllUser()
{
return _context.User.Select(u => new UserDto{FirstName=u.FirstName, LastName=u.LastName, Organisation="Acme"});
}
where _context is your DBContext and .User is your User DBSet

Laravel Slugs with Str::slug

Looking at Str::slug for my frontend URL generation but just wondering how you guys go about implementing it with routes etc, for example, how would you guys go about changing http://www.example.com/courses/1 to http://www.example.com/courses/this-course
OK, I did it this way:
// I have a slug field in my courses table and a slug field in my categories table, along with a category_id field in my courses table.
// Route
Route::get('courses/{categorySlug}/{slug?}', function($categorySlug, $slug) {
$course = Course::leftJoin('categories', 'categories.id', 'courses.category_id')
->where('categories.slug', $categorySlug)
->where('courses.slug', $slug)
->firstOrFail();
return View::make('courses.show')->with('course', $course);
});
Works like a charm. It gets the $categorySlug and $slug variables then uses them to filter the Eloquent model Course to get the correct course object from the database.
EDIT: You can generate a URL in your view like:
http://www.example.com/courses/it-training/mcse
By doing something like:
{{ $course->title }}
A have a method in my Category like below that retrieves the parent category slug. This could be better achieved though using some sort of presenter class which would allow you to simply use $course->url but I haven't got around to doing this yet. I will update the answer when I do.
public function parentCategorySlug($parentId)
{
if ($parentId === '0')
{
return $this->slug;
}
return $this->where('id', $parentId)->first()->slug;
}
You can use the cvierbrock's Eloquent-Sluggable package.
As for me I created a helper function and used the following method taken from here.
public static function getSlug($title, $model) {
$slug = Str::slug($title);
$slugCount = count( $model->whereRaw("url REGEXP '^{$slug}(-[0-9]*)?$'")->get() );
return ($slugCount > 0) ? "{$slug}-{$slugCount}" : $slug;
}
You can create a related model Slug, and approach the course in your methods like so:
$course = Slug::where('slug', $slug) -> firstOrFail() -> course;
I have also implemented a similar URL mapping but I preferred to have both the ID and the slug in the requested URL, like this:
http://www.example.com/courses/1/my-laravel-course
This method allows me to get the requested course object from the ID given in the URL, rather than having to store the slugs in my DB table.
Route::post('courses/(:num)/(:any)', function ($courseid, $slug) {
$course = Course::where('id', '=', $courseid)->get();
return View::make('courses.show')->with('course', $course);
}
For Laravel 8:
Given my URL:
http://www.example.com/courses/this-course
My route:
Route::get('/courses/{course:slug}' , function(Course $course){
return view('showCourse' , [
'course' => $course
])
})

Extract paging from IQueryable

I'm using a function to allow query composition from Web UI and I would to implement paging functionality which it will be available for dataBound controls such as ObjectDataSource, gridView, etc:
public class MyClass<TEntity> where TEntity : class
{
FakeEntities xxx = new FakeEntities();
public IEnumerable<TEntity> Get(Func<IQueryable<TEntity>, IQueryable<TEntity>> queryExpression)
{
var query = xxx.Set<TEntity>();
return queryExpression(query).ToList();
}
public int Count()
{
// What Can I return?
}
}
// **** USAGE ****
MyClass<User> u = new MyClass<User>();
var all = u.Get(p => p.Where(z => z.Account == "Smith").OrderBy(order => order.IdOther).Skip(1).Take(2));
The above query use Take and Skip function, so can I get real count of my entities? Obviously I must return Query Count without modifying filter expression.
I found this solution: Get count of an IQueryable<T>
However I get targetInvocationException with inner message {"This method supports the LINQ to Entities infrastructure and is not intended to be used directly from your code."}
I know my request could be freak-abnormal, because best practice should to impose to move "presentation needs" to some wrap class and that's is what I'll do. So I don't need anymore to get Count entities on my business logic class.
That's just UI concern only.
Thank you the same.

Resources