laravel 5.2 - Accessing Model in Controller Method - laravel

I have added the line use App\Post; in the header of my PostController class.
When I try $post = new App\Post; in a controller method, I get the following error message
Class 'App\Http\Controllers\App\Post' not found
What are some possibilities for why I am getting this error message?

Since you already included the Post class, you don't have to reference the path again.
$post = new Post();
This should work.

u can use facades..
$post = Post::all(); << return all row

I am assuming you used artisan to generate the Model. You may use eloquent as:
use App\Post as Post;
...
$post = Post::all();

The reason you are not able to access the model via App\Post is because the file you are attempting to do this in already has a namespace, shown in the error: App\Http\Controllers\App\Post, which implies the namespace of the file is App\Http\Controllers.
Since you are not referencing the model with an absolute namespace (\ at the beginning), PHP is looking for that class relative to the current namespace.
<?php
namespace App\Http\Controllers;
...
$post = App\Post::find(1); // App\Http\Controllers\App\Post
$post = \App\Post::find(1); // App\Post
That explains the error. However, as mentioned by others, you have already used the model in your file and can access it simply with Post.
$post = Post::find(1);

Related

Laravel, eloquent and foreach in controller

I'm new in Laravel and I'm curious about one thing. I have 3 database tables: posts, comments, replies. I want to make a simple delete from each. But obviously post has many comments and comments has many replies. Whole thing is about these replies. Seems like I can't reach them.
I have properly working relations between tables.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
use App\Comment;
use App\Reply;
use App\Traffic;
use Image;
use Illuminate\Support\Facades\Storage;
class PostsController extends Controller
{
//few others things here...
public function destroy($id) //$id is an id of post
{
// Select Post and comments of post
$post = Post::find($id);
$comments = Comment::where('post_id', $id);
//remove image (working fine)
Storage::delete('public/img/' . $post->image);
// delete all replies of post comments <<< Here is the issue. Can I even do like this?
foreach ($comments as $comment) {
$post_comment_reply = Reply::where('comment_id', $comment->id);
$post_comment_reply->delete();
}
// delete post record (working fine)
$post->delete();
//delete comments of post (working fine)
$comments->delete();
// return to user profile (working fine)
return redirect('/home')->with('success', 'Post has been deleted');
}
There is an even easier way to do so.. if you just add a database constraint to the foreign key in the replies table to the comment..
$table->unsignedInteger('comment_id');
$table->foreign('comment_id')->references('id')->on('comments')
->onDelete('cascade');
The last part: onDelete('cascade') ensures that all the replies will be deleted once a comment has been deleted :) so you don't have to manually do that in the application layer.
Let me know if it makes sense :)
Instead of deleting the replies in a loop, you can delete them all at once:
$comments = Comment::where('post_id', $id);
$comment_ids = $comments->pluck('id');
Reply::whereIn('comment_id', $comment_ids)->delete();
What's wrong in your code is that you create a db query but does not execute it:
// You forgot the ->get() following the where statement
foreach ($comments as $comment)
$post_comment_reply = Reply::where('comment_id', $comment->id)->get();
$post_comment_reply->delete();
}
However the code altogether is not quite optimal, you could make it directly on database level with onDelete('cascade'), or simply create a request to delete the replies without retrieving them and reducing the number of query to the db, like such:
foreach ($comments as $comment)
Reply::where('comment_id', $comment->id)->delete();
}
One step further reducing db queries like suggested above:
Reply::whereIn('comment_id', $comments->pluck('id'))->delete();
If you want to delete the relations via Laravel, you have to override the boot function.
Override the boot() on your Comment model like
protected static function boot()
{
static::deleting(function (Comment $model) {
$model->replies()->delete();
});
parent::boot();
}
This will delete all the replies associated to a comment when that comment is deleted via eloquent.

Call to undefined method Illuminate\Database\Query\Builder::remember()

I was trying to cache the db query with built in function remember(). But it doesn't seem to be working fine. Here is fine snippets.
$categories = Category::orderBy('rank', 'asc')
->select('id', 'name', 'rank')
->where('parentid', '=', 0)
->where('id', '<>', 4)
->remember(300)
->get();
This is the reference link, which I was following. I am getting the following error messa
Call to undefined method Illuminate\Database\Query\Builder::remember()
Category.php
<?php
namespace App;
use Eloquent;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
//
}
This functionality was removed in Laravel 5. However, you can still bring it back by following the tutorial behind this link. It's using the dwightwatson/rememberable package.
A better and future proof way of resolving this issue, is using the Cache method. This functionality is available from Laravel 4.2 onwards.

Laravel Eloquent: get model id from inside getAttribute function?

I have a model like the following:
User extends Authenticatable
{
protected $appends = array('role');
public function getRoleAttribute()
{
$role = DB::table('acl_user_has_roles')->where('user_id', $this->id)
->value('role');
return $role;
}
}
When I try to reference this foo attribute like the following:
$user = User::find(1);
unset($user->id); // This line causes the problem.
echo $user->role;
I always get "null" instead of expected "Owner".
What did I miss here?
I am running this in laravel 5.5.43.
In the following post, getKey() function was mentioned, that didn't work.
The problem is actually caused by something else, as described in the following medium post.
Just in case anyone else runs into the same issue. The problem is caused by another line in the code. I unset $user->id before echo.
The issue is described in detail in the following medium post:
Be Careful to Use Laravel Eloquent’s Accessors, Mutators And Events

How to create slugs in Laravel?

I'm trying to develop an e-com website in Laravel 5 (Since it required lot of customization, I decided not to use Magento or OpenCart).
The problem I'm facing is to creating category and product URLs from slugs.
For example, one URL can be:
http://somewebsite.com/products/lenovo-yoga-500
But I want to make URL like:
http://somewebsite.com/lenovo-yoga-500
I tried to create a route like:
Route::get('{slug}', 'BaseController#route');
and in the route() method, I tried:
function route($route){
$product = Product::where(array('slug' => $slug))->first();
if(isset($product))
.....
else
.....
but first of all, the value is not getting passed to variable '$slug' and secondly I want to redirect the request to another route after checking the condition.
You might want to go with the first URL (product/{slug}) because the way you have it setup with the slug as the first parameter, every route you make for any page will be interpreted as the slug.
Either way, fix your controller method as such
function route($slug){
$product = Product::where(array('slug' => $slug))->first();
if(isset($product))
.....
else
.....
The documentation covers everything you are asking for here, so please read through about redirecting to routes.
To achieve it like Magento does, you need to add a new product-routes.php file that will be rebuilt.
First instruct app/Providers/RouteServiceProvider.php to load your dynamic route file thus:
protected function mapWebRoutes(Router $router)
{
$router->group([
'namespace' => $this->namespace,
], function ($router) {
require app_path('Http/routes.php');
require base_path('resources/routes/product-routes.php');
});
}
Next: Rebuild product-routes.php automatically on save or when the user requests it in the backend to include all product slug routes and to load the product by slug.
Hope that helps.
in Product-model:
public function getRouteKeyName() {
return 'slug';
}
in routes:
Route::get('{product}', 'ProductController#product');
in ProductController:
public function product(Product $product) {
$product->doSomething();
}
Note that the route should be last in the routes-file so any other route has chance to match before that.
You must use this Route
Route::get('/sample/show/{sample : slug}',[SampleController::class]);
Enter the model of the controller and set the value of getRouteKeyName equal to slug such as:
public function getRouteKeyName(){return 'slug';}
Custom Keys & Scoping
When implicitly binding multiple Eloquent models in a single route definition, you may wish to scope the second Eloquent model such that it must be a child of the previous Eloquent model. For example, consider this route definition that retrieves a blog post by slug for a specific user:
use App\Models\Post;
use App\Models\User;
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) { return $post;});

Laravel model all() function is not working as intended

I have a model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Contact extends Model {
protected $table = 'contacts';
//
}
And in the controller action
$c= Contact::all();
I am getting the "Whoops, looks like something went wrong." error.
Error detail:
FatalErrorException in ContactController.php line 9:
Class 'App\Http\Controllers\Contact' not found
The table "contacts" exists in the database.
What thing I am missing? Whats wrong here?
Tell your controller where your model is if it is in route of your project then on the top of your controller add
use App\Contact;
Or you may also define it every time
$c = App\Contact::all();
also in your model no need to define a table until it is not different from the plural model name. If your model name is Contact, laravel on its own query contacts table, you should define the table name if the model name is Contact and the table name is somethingElse.
Don't use
$c= Contact::all();
Instead use
$c = \App\Contact::all()
or
$c = new \App\Contact;
$c->all();
This is all that you have to use.
UPDATE: Just after digging in the concepts of OOP, I found this:
<?php
use \App\Contact;
var_dump(Contact::all());

Resources