Eloquent: relationships between blog tables - laravel

someone would have a practical example of using relationships in Eloquent as follows: I have a blog with several categories, in these categories I will have several Posts, as I do to display a category with several Post in Views. Any practical examples for me to study my logic? I've seen several here, but none fit into what I want above.
Model Post:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
public function tags()
{
return $this->belongsToMany('App\Tag');
}
public function comments()
{
return $this->hasMany('App\Comment');
}
}
Controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Post;
use Mail;
use Session;
use App\Category;
class PagesController extends Controller {
public function getIndex() {
$posts = category::find(1)->posts()->orderBy('created_at', 'desc');
return view('v1.index')->withPosts($posts);
// $posts = Post::orderBy('created_at', 'desc')->limit(3)->get();
// $categorias = Category::find(1);
// return view('v1.index')->withPosts($posts)->withCategorias($categorias);
}
public function getContact() {
return view('v1.contato');
}
public function postContact(Request $request) {
$this->validate($request, [
'email' => 'required|email',
'subject' => 'min:3',
'message' => 'min:10']);
$data = array(
'email' => $request->email,
'subject' => $request->subject,
'bodyMessage' => $request->message
);
Mail::send('emails.contact', $data, function($message) use ($data){
$message->from($data['email']);
$message->to('hello#devmarketer.io');
$message->subject($data['subject']);
});
Session::flash('success', 'Your Email was Sent!');
return redirect('/');
}
}
Model Category:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = 'categories';
public function posts()
{
return $this->hasMany('App\Post');
}
}
View index
<div class="col-sm-6">
<div id="home-slider">
#foreach($posts as $post)
<div class="post feature-post">
<div class="entry-header">
<div class="entry-thumbnail">
<img class="img-responsive" src="{{ asset('imgs/'.$post->image) }}" width="572" height="350" alt="" />
<div class="catagory world">{{ $post->category->name }}</div>
</div>
<div class="post-content">
<h2 class="entry-title">
{{ $post->title }}
</h2>
</div>
</div><!--/post-->
#endforeach
</div>
</div>

First get the category you want to display
$category = Category::find(1);
Then Get all the post related to that category by skipping the first 3
$posts = Post::where('category_id', $category->id)
->skip(3)
->take(6)
->get();
Pass them to your view
return view('v1.index', compact('posts'));
In your view, wherever you want, loop them with blade exactly the way you are doing already.
#foreach($posts as $post)
#endforeach

Related

Method Illuminate\Database\Eloquent\Collection::paginate does not exist using relations tales

I created a page using the pagination feature, when I opened the blog page everything went well, but when I opened the blog page based on the username from the user table there was an error Method Illuminate\Database\Eloquent\Collection::paginate does not exist. BTW it uses the same view.
blog.blade.php
#extends('layouts.main')
#section('container')
<main class="mt-20 mb-5 w-[800px] mx-auto">
#foreach ($blogs as $blog)
<article class="mb-5">
{{-- judul --}}
<h2 class="text-blue-600 text-2xl mb-2 font-semibold">{{ $blog->title }}</h2>
{{-- penulis category --}}
<p>Author : {{ $blog->user->name }} | Category : {{ $blog->category->name }}</p>
<p class="mt-2 pb-2 border-b border-grey-500">{{ Str::limit($blog->body, 100) }}</p>
</article>
#endforeach
{{ $blogs->links() }}
</main>
#endsection
BlogController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Blog;
class BlogController extends Controller
{
public function index() {
return view('blog', [
'title' => 'All Blog',
'blogs' => Blog::latest()->paginate(5)
]);
}
public function show(Blog $blog) {
return view('show_blog.index', [
'title' => $blog->title,
'blog' => $blog
]);
}
}
UserController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
class UserController extends Controller
{
public function blogFromUser(User $user) {
return view('blog', [
'title' => $user->name,
'blogs' => $user->blog->paginate(5)
]);
}
}
Blog.php *relate to user (belongsTo)
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Blog extends Model
{
use HasFactory;
public function category() {
return $this->belongsTo(Category::class);
}
public function user() {
return $this->belongsTo(User::class);
}
}
)*
User.php *related to Blog (hasMany)
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
public function Blog() {
return $this->hasMany(Blog::class);
}
}
)*
When you do :
$user->blog
it will execute the query and retrieve the results, so $user->blog will be a collection.
If you want to paginate it, you need to call paginate on the query/relation, not the result, so you need to do something like :
$user->blog()->paginate(5)
then to access other pages, you will have to append ?page=xy to the page url
be aware that if you have multiple paginations within the same page you will need to change the name of the parameter to avoid conflict like so :
$user->blog()->paginate(5, '*', 'blog')

Call to undefined method App\Models\Catogry::firstItem()

I'm trying to create a CMS project but I got this error when I create the URL & Controller for the edit button (Call to undefined method App\Models\Catogry::firstItem()).
here is the web.php page
<?php
use App\Http\Controllers\CategoryController;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
// $users = User::all();
$users = DB::table('users')->get();
return view('dashboard', compact('users'));
})->name('dashboard');
//category controller
Route::get('/category/all', [CategoryController::class, 'index'])->name('index.category');
Route::post('/category/add', [CategoryController::class, 'store'])->name('store.category');
Route::get('/category/edit/{id}', [CategoryController::class, 'edit']);
here Is the CategoryController >>
<?php
namespace App\Http\Controllers;
use App\Models\Catogry;
use Carbon\Carbon;
use Illuminate\Auth\Events\Validated;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class CategoryController extends Controller
{
public function index()
{
$categories = Catogry::latest()->paginate(5);
return response()->view('Admin.category.index', compact('categories'));
}
public function store(Request $request)
{
$validated = $request->validate([
'category_name' => 'required|unique:catogries|max:25|min:4',
]);
//insert with three ways *****
// Catogry::insert([
// 'category_name' => $request->category_name,
// // 'user_id' => Auth::user()->id,
// 'created_at' => Carbon::now()
// ]);
$categories = new Catogry;
$categories->category_name = $request->category_name;
$categories->user_id = Auth::user()->id;
$categories->save();
// $date = array();
// $data['category_name'] = $request->category_name;
// $data['user_id'] = Auth::user()->id;
// DB::table('catogries')->insert($data);
return redirect()->back()->with('success', 'Category Inserted Successfully');
}
public function Edit($id)
{
// return 'edit page';
$categories = Catogry::findOrFail($id);
return response()->view('Admin.category.edit', compact('categories'));
}
}
here is the edit.blade.php page >>
<form action=" " method="POST">
#csrf
<div class="card-body">
<div class="form-group">
<label for="category_name">Edit Your Category Name</label>
<input type="text" class="form-control" id="category_name" name="category_name" placeholder="Enter category name"
value="{{ $categories->category_name }}">
</div>
<div class="card-footer">
<button type="submit" class="btn btn-info">Update Category</button><br>
#error('category_name')
<span class="text-danger">{{ $message }}</span>
#enderror
</div>
<!-- /.card-footer -->
</form>

Laravel problems with redirect

So I am working on a laravel project and I want that if a user types in their order code, the order will show up with the details. For some reason, the order code doesn't get through the if statement, because I get the output 'Order not found.' all the time, even if I type in an order code that is present in my orders table.
TrackController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Order;
class TrackController extends Controller
{
public function index()
{
return view ('track.index');
}
public function show($id)
{
$order = Order::where('code', $id)->first();
return view('track.show',[
'order' => $order
]);
}
public function redirect(Request $request)
{
$orderCode = $request->input('order-track-id');
$order = Order::where('code', $orderCode)->first();
if(!$order){
return redirect('/track')->with('error', 'Order not found.');
}else{
return redirect('/track/' . $order->code);
}
}
}
web.php
Route::get('/track', 'TrackController#index');
Route::post('/track/redirect', 'TrackController#redirect');
Route::get('/track/{id}', 'TrackController#show');
track.index
#extends('layouts/app')
#section('content')
<div class="container">
<div class="row justify-content center">
{!! Form::open(['action' => 'TrackController#redirect', 'method' => 'post']) !!}
{!! csrf_field() !!}
<input type="number" name="input-order-track-id" id="order-track-id">
{{ Form::button('Track', ['type' => 'submit', 'class' => 'btn btn-primary'] ) }}
{!! Form::close() !!}
</div>
</div>
#endsection
What am I doing wrong and why isn't my function putting me through to the show function in the TrackController?
In your redirect controller function.
public function redirect(Request $request)
{
$orderCode = $request->input('input-order-track-id');
$orders = Order::where('code', $orderCode)->get();
if($orders->isEmpty()){
return redirect('/track')->with('error', 'Order not found.');
}else{
$order = Order::where('code', $orderCode)->first();
return redirect('/track/' . $order->code);
}
}

ReflectionException Class App\User does not exist

hello i have this error : ReflectionException Class App\User does not exist Previous exceptions syntax error, unexpected '{', expecting ')' (0)
but dont understand where is syntax error ,
User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username', 'nom', 'prenom', 'adresse', 'ville', 'codepostale', 'datedenaissance','email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
protected static function boot()
{
parent::boot();
static::created(function ($user {
$user->profile()->create([
'title' => 'Profil de' . $user->username
]);
});
}
public function getRouteKeyName()
{
return 'username';
}
public function profile()
{
return $this->hasOne('App\Profile');
}
public function posts()
{
return $this->hasMany('App\Post')->orderBy('created_at', 'DESC');
}
}
ProfileController.php
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use Intervention\Image\Facades\Image;
class ProfileController extends Controller
{
public function show(User $user)
{
return view('profile.show', compact('user'));
}
public function edit(User $user)
{
$this->authorize('update', $user->profile);
return view('profile.edit', compact('user'));
}
public function update(User $user)
{
$this->authorize('update', $user->profile);
$data = request()->validate([
'title' => 'required',
'description' => 'required',
'image' => 'sometimes|image|max:3000'
]);
if (request('image')) {
$imagePath = request('image')->store('avatars', 'public');
$image = Image::make(public_path("/storage/{$imagePath}"))->fit(800, 800);
$image->save();
auth()->user()->profile->update(array_merge($data,
['image' => $imagePath]
));
} else {
auth()->user()->profile->update($data);
}
auth()->user()->profile->update($data);
return redirect()->route('profile.show', ['user' => $user]);
}
}
show.blade.php
<#extends('layouts.app')
#section('content')
<div class="container">
<div class="row">
<div class="col-4">
<img src="{{ $user->profile->getImage() }}" class="rounded-circle">
</div>
<div class="col-8">
<div class="d-flex align-items-baseline">
<div class="h4 mr-3 pt-2">{{ $user->username }}</div>
<button class="btn btn-primary">S'abonner</button>
</div>
<div class="d-flex">
<div class="mr-3">{{ $user->posts->count() }} article(s) en vente
</div>
#can('update', $user->profile)
Modifier Profile
#endcan
<div class="mt-3">
<div class="font-weight-bold">
{{ $user->profile->title }}
</div>
<div class="font-weight-bold">
{{ $user->profile->description }}
</div>
</div>
</div>
</div>
<div class="row mt-5">
#foreach ($user->posts as $post)
<div class="col-4">
<img src="{{ asset('storage') . '/' . $post->image }}" class="w-100">
</div>
#endforeach
</div>
</div>
#endsection
Profile.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
protected $fillable = ['title'];
public function user()
{
return $this->belongsTo('App\User');
}
public function getImage()
{
$imagePath = $this->image ?? 'avatars/default.png';
return "/storage/" . $imagePath;
}
}
i try to create profile with upload image, someone can help me with this error?
Your IDE should give you an error in your overridden boot method, so change this:
static::created(function ($user {
$user->profile()->create([
'title' => 'Profil de' . $user->username
]);
});
to this:
static::created(function ($user) {
$user->profile()->create([
'title' => 'Profil de' . $user->username
]);
});
Note the missing ) in your $user param.

How to get Title, Description and Price stored in a pivot table between users and services in Laravel

I want to get the title, description, and price which are stored in a pivot table between users and services called userservices. I want to be able to display this information I'll get from the userservices table, inside the user profile view page.
I have 4 tables for that which include,
A User table with id, name, surname, email, phone, area_id.
A Service table with id, name, description, and category_id.
A category table with id, name, description
and I have pivot table btw users and services called service_user which stores the service_id, user_id, title, description and price
I wish to know how can I get the title, description and price for a service that belongs to a particular user, provided the information exists in the userservice table in the database using Laravel.
In my user Controller, I did something like this
public function jobberDetails($id) {
$profiledetail = User::with('area.town.region.country')
->with('userservice')
->find($id);
DB::update("UPDATE users SET visit = visit + 1 WHERE id = '$id'");
// dd($jobdetail);
return view('Users.profileDetail', compact('profiledetail'));
}
in my web file
// Route qui permet d'afficher,le profil d'un Jobbeur
Route::get('/jobber/profiledetails/{id}', 'UserController#jobberDetails')->where(array('id' => '[0-9]+'))->name('profileDetails');
In my model I did something like this
public function area(): BelongsTo
{
return $this->belongsTo(Area::class);
}
public function getTownAttribute(): Town
{
return $this->area->town;
}
public function getRegionAttribute(): Region
{
return $this->area->town->region;
}
public function getCountryAttribute(): Country
{
return $this->area->town->region->country;
}
public function userservice(): BelongsTo
{
return $this->belongsTo(UserServices::class);
}
and in my profile detail blade I did this
<div class="row">
<div class="col-lg-8">
<div class="job-single-head3">
<div class="job-single-info3">
<h3>{{ $profiledetail->name }} {{ $profiledetail->surname }}</h3>
<span><i class="la la-map-marker"></i>{{ $profiledetail->town->name}}, {{ $profiledetail->region->name}}</span>
<span class="job-is ft" id="more" onclick="$('.details').slideToggle(function(){$('#more').html($('.details').is(':visible')?'Cacher le numero':'Voir le numero');});">Voir le numero</span>
</div>
</div><!-- Job Head -->
</div>
</div>
</div>
<div class="job-wide-devider">
<div class="row">
<div class="col-lg-8 column">
<div class="extra-job-info details" style="display:none">
<p style="text-align: center; padding: 10px; font-size: 45px;"><i class="la la-phone"></i> {{ $profiledetail->phone }}</p>
</div>
<div class="job-details">
<h3>Description</h3>
<p> {{ $profiledetail->userservices->description }}.</p>
<h3>Conditions et tarifs</h3>
<ul>
<li>{{ $profiledetail->userservices->price }}</li>
</ul>
<h3>Title</h3>
<ul>
<li>{{ $profiledetail->userservices->title }}</li>
</ul>
</div>
Here's how you can do it using pivot as suggested by #DigitalDrifter
Start by adding services relationship method to the User model
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class User extends Authenticatable
{
use Notifiable;
//...
public function services(): BelongsToMany
{
return $this->belongsToMany(Service::class)->withPivot('title', 'description', 'price');
}
}
Add reverse relationship to the User from within Services model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Service extends Model
{
protected $fillable = ['category_id', 'name', 'description'];
public function country(): BelongsTo
{
return $this->belongsTo(Category::class);
}
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class);
}
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
}
Now you can use it like so
$profileDetail = User::with(['area.town.region.country', 'services'])->find($id);
foreach($profileDetail->services as $service) {
{{ $service->pivot->title }}
{{ $service->pivot->description }}
{{ $service->pivot->price }}
{{ $service->category->name }}
}
Here's the test (containing all previous code example as well)
<?php
namespace Tests\Unit;
use App\Area;
use App\Town;
use App\User;
use App\Region;
use App\Service;
use App\Country;
use App\Category;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
class UserTest extends TestCase
{
use RefreshDatabase;
/**
* #test
*/
public function pulls_area_town_region_and_country()
{
$country = Country::create([
'name' => 'United Kingdom',
'description' => 'United Kingdom'
]);
$region = Region::create([
'country_id' => $country->id,
'name' => 'Somerset',
'description' => 'Somerset'
]);
$town = Town::create([
'region_id' => $region->id,
'name' => 'Bristol',
'description' => 'Bristol'
]);
$area = Area::create([
'town_id' => $town->id,
'name' => 'South',
'description' => 'South'
]);
$category = Category::create([
'name' => 'Animals',
'description' => 'Animals'
]);
$service = Service::create([
'category_id' => $category->id,
'name' => 'Service',
'description' => 'Service'
]);
$user = factory(User::class)->create([
'area_id' => $area->id
]);
$user->services()->attach($service->id, [
'title' => 'Attached service',
'description' => 'Attached service description',
'price' => 12575
]);
$user = User::with('area.town.region.country')->first();
$recentJobbers = User::with(['area.town.region.country', 'services.category'])
->limit(5)
->whereType('jobber')
->orderBy('updated_at', 'desc')
->get();
$this->assertEquals('United Kingdom', $user->area->town->region->country->name);
$this->assertEquals('Somerset', $user->area->town->region->name);
$this->assertEquals('Bristol', $user->area->town->name);
$this->assertEquals('South', $user->area->name);
$this->assertEquals('United Kingdom', $user->country->name);
$this->assertEquals('Somerset', $user->region->name);
$this->assertEquals('Bristol', $user->town->name);
$this->assertEquals('South', $user->area->name);
$this->assertEquals('Attached service', $user->services->get(0)->pivot->title);
$this->assertEquals('Attached service description', $user->services->get(0)->pivot->description);
$this->assertEquals(12575, $user->services->get(0)->pivot->price);
$this->assertEquals('Animals', $user->services->get(0)->category->name);
}
}

Resources