Method store & posts not found [LARAVEL] - php

I've been stuck for a little while on a backend issue. PHPStorm tells me that the posts and store method doesn't exist, and I don't know which way to go to solve this problem...
File PostController.php:
public function store(){
$data = request()->validate([
'caption' => ['required', 'string'],
'image' => ['required', 'image']
]);
$imagePath = request('image')->store('uploads','public');
auth()->user()->posts()->create([
'caption' => $data['caption'],
'image' => $imagePath
]);
return redirect()->route('profiles.show', ['user' => auth()->user()]);
}
File User.php:
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'username', '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',
];
public function getRouteKeyName()
{
return 'username';
}
public function profile(){
return $this->hasOne('App\Profile');
}
}
Error encountered:

I hadn't created a relationship posts in my User.php.
So I added the relationship this way:
public function posts(){
return $this->hasMany('App\Post');
}

try this :
Post::create([
'caption' => $data['caption'],
'image' => $imagePath
]);

Related

My storage fake doesn't store the image inside the test directory

I'm writing a test for my Item model, it has images to be uploaded and I expect it should be stored inside the testing directory to be cleared each time I ran the test. But it wasn't. Instead, it creates a new directory named item-images in both storage and testing/disks but it uses the actual storage/item-images directory instead of storage/disks/item-images.
Storage::fake('item-images') is already defined on top of the test case, I'm a bit confused by this, please help.
tests/Feature/ItemTest.php
public function test_user_can_store_new_item()
{
Storage::fake('item-images');
Sanctum::actingAs(User::factory()->create());
$images = [
UploadedFile::fake()->image('image1.png'),
UploadedFile::fake()->image('image2.png'),
UploadedFile::fake()->image('image3.png'),
];
$item = Item::factory()->make(['images' => $images]);
$this->postJson(route('items.store'), $item->toArray())
->dump()
->assertCreated()
->assertJsonFragment($item->toArray());
foreach ($images as $image) {
Storage::disk('item-images')->assertExists($image->hashName());
Storage::disk('item-images')->assertMissing('missing.png');
}
}
app/Models/Item.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Item extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'category_id',
'name',
'description',
'history',
];
protected $with = ['category'];
/**
* Get the category that owns the Item
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
}
app/Http/Controllers/ItemController.php
/**
* Store a newly created resource in storage.
*
* #param \App\Http\Requests\RequestItem $request
* #return \Illuminate\Http\Response
*/
public function store(RequestItem $request)
{
$data = $request->validated();
$item = Item::create(Arr::except($data, 'images'));
if ($request->has('images')) {
foreach ($request->file('images') as $image) {
$path = $image->store('item-images');
Image::create(['item_id' => $item->id, 'url' => $path]);
}
}
return response()->json($item, 201);
}
app/Http/Requests/RequestItem.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class RequestItem extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'category_id' => [
'required',
'integer',
],
'name' => [
'required',
'string',
'max:255',
Rule::unique('items', 'name'),
],
'description' => [
'required',
'string',
'max:255',
],
'history' => [
'string',
'max:2500',
],
'images' => [
'required',
'array',
'min:1',
'max:10',
],
];
}
}
I believe the confusing is you are creating a fake file, but actually properly saving it. $image->store('item-images'); doesn't specify the store you are saving it in, but the 'item-images' is the path and it will save it to the default storage. So either Storage::fake() the default storage option.
// assuming default storage is local
Storage::fake('local');
Or change your logic to specify the correct faked storage disk.
Storage::disk('item-images')->putFile('path/yourfile', $image);

Issue: Argument #1 ($user) must be of type Illuminate\Contracts\Auth\Authenticatable, null given, called in

I'm beginner in Laravel. I'm using jetstream for auth. When I trying register to database, it saves to database but gives this error. So how can I fix this problem
My HomeController is:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth;
class HomeController extends Controller
{
protected $user;
public function __construct(){
$this->middleware(function ($request, $next) {
$this->user= Auth::user();
return $next($request);
});
}
public function main(){
return view('welcome');
}
public function home(){
return view('design2.index');
}
public function logout(Request $request) {
Auth::logout();
return redirect('/');
}
public function register(){
return view('design2.registerpage');
}
public function login_page(){
return view('design2.loginpage');
}
public function profile(){
return view('profile');
}
}
My user model is:
<?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\Fortify\TwoFactorAuthenticatable;
use Laravel\Jetstream\HasProfilePhoto;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens;
use HasFactory;
use HasProfilePhoto;
use Notifiable;
use TwoFactorAuthenticatable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
'two_factor_recovery_codes',
'two_factor_secret',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = [
'profile_photo_url',
];
}
My CreateNewUser is:
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\CreatesNewUsers;
use Laravel\Jetstream\Jetstream;
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
/**
* Validate and create a newly registered user.
*
* #param array $input
* #return \App\Models\User
*/
public function create(array $input)
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => $this->passwordRules(),
])->validate();
$save = User::create([
'name' => $input['name'],
'email' => $input['email'],
'password' => Hash::make($input['password']),
]);
}
}
Error is:
Illuminate\Auth\SessionGuard::login(): Argument #1 ($user) must be of type Illuminate\Contracts\Auth\Authenticatable, null given, called in /Applications/XAMPP/xamppfiles/htdocs/muzik/vendor/laravel/fortify/src/Http/Controllers/RegisteredUserController.php on line 56
Try to return created user instead of just save it in variable $save.
public function create(array $input)
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => $this->passwordRules(),
])->validate();
return User::create([
'name' => $input['name'],
'email' => $input['email'],
'password' => Hash::make($input['password']),
]);
}

I cant login on Server - Laravel 6

I don't know why I can't login on the server, I can access on server local but hen I try login on the server that is impossible. I'm using Laravel 6.2 and Auth process by Default
I run this command
php artisan ui vue --auth
This is my login ctrl
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = RouteServiceProvider::HOME;
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}
And this is my User Model
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', '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 $appends = ['client'];
public function countriesAccess(){
$countries = Countries::whereIn('id',explode(',',$this->countriesId))->get();
return $countries;
}
public function getClientAttribute()
{
$client = Clients::where('id',$this->clientId)->first();
return $this->client = $client->name;
}
public function sendPasswordResetNotification($token)
{
$this->notify(new MyResetPassword($token));
}
public function country(){
return $this->belongsTo('App\Countries','countryId');
}
}
In config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
]
I run
PHP artisan optimize
And nothing works. Please help me.
Ahh the server ins a vHost in AWS

Auth::attempt always return false and I don't know why

public function login( Request $request ) {
$fields = [
'email' => $request->email,
'password' => $request->password,
];
$access = Auth::attempt( $fields );
echo $access;
if ( $access ) {
$user = Auth::teacher();
$token = $user->createToken('MyApp')->accessToken;
return response()->json( [
"message" => "Login realizado com sucesso!",
"data" => [
'user' => $user,
'token' => $token
]
], 200 );
} else {
return response()->json( [
"message" => "Email ou senha inválidos!",
"data" => null,
"return" => $access,
], 401 );
}
I have this function to login, I am try with a Model Teacher, but always auth::attempt gave me false, but if I am try with User Model the result is true.
My Model Teacher
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;
use App\Student;
use App\Rating;
use App\Commentary;
use App\User;
class Teacher extends Authenticatable
{
use Notifiable;
use HasApiTokens;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', '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',
];
public function students(){
return $this->belongsToMany('App\Student')->withTimestamps();
}
public function ratings(){
return $this->hasMany('App\Rating');
}
public function commentaries(){
return $this->hasMany('App\Commentary');
}
public function updateTeacher(Request $req){
$validator = Validator::make($request->all(),[
]);
if($validator->fails()){
return response()->json($validator->errors());
}
if ($req->name)
$this->name = $req->name;
if ($req->email)
$this->email = $req->email;
if ($req->password)
$this->password = $req->password;
if ($req->number)
$this->number = $req->number;
if ($req->birth)
$this->birth = $req->birth;
if ($req->CPF)
$this->CPF = $req->CPF;
if ($req->lesson_price)
$this->lesson_price = $req->lesson_price;
if ($req->rent_price)
$this->rent_price = $req->rent_price;
if ($req->description)
$this->description = $req->description;
if ($req->district)
$this->district = $req->district;
if ($req->zone)
$this->zone = $req->zone;
if ($req->instruments)
$this->instruments = $req->instruments;
if ($req->certification)
$this->certification = $req->certification;
$this->save();
}
public function listTeachers(){
$paginator = Teacher::paginate(10);
return response()->json([$paginator]);
}
public function showTeacher($id){
$teacher = Teacher::findOrFail($id);
return response()->json([$teacher]);
}
}
My Model User
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use Notifiable;
use HasApiTokens;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', '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',
];
}
So i am think that Teacher have the same functions and most operations like User, thus the function auth::attempt should works with Teacher.
add teacher model to the guard in config/auth.php and then use
Auth::guard('teacher')->attempt($credentials)
'guards' => [
'user' => [
'driver' => 'session',
'provider' => 'users',
],
'teacher' => [
'driver' => 'session',
'provider' => 'teachers',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'teachers' => [
'driver' => 'eloquent',
'model' => App\Teacher::class,
],
],
Default Laravel authentication only works with User model. It is specified in config/auth.php. If you want to use another model for authentication you can just change in auth.php.
If you want multiple models to be used for Authentication, for example, both User and Teacher , you need to look into Guards in Laravel.
Here is a link to a tutorial which explains this technique.
HOW TO USE MULTIPLE AUTHENTICATION GUARDS IN A LARAVEL APP

Laravel Confide not triggering eloquent.saving

I'm using zizaco/confide in combination with cviebrock/eloquent-sluggable.
eloquent-sluggable uses Events::listen('eloquent.saving*') for generating the slug while/before saving.
// Cviebrock\EloquentSluggable\SluggableServiceProvider:55
public function registerEvents()
{
$app = $this->app;
$app['events']->listen('eloquent.saving*', function($model) use ($app)
{
$app['sluggable']->make($model);
});
}
Since I switched to Confide for authentication the slugs are not getting generated.
My user model is simply class User extends ConfideUser. Switching to class User extends Ardent or User extends Eloquent the event eloquent.saving is getting triggered fine.
I'm not shure if this is a bug or I'm missing something.
My Model:
<?php
use Illuminate\Database\Eloquent\Model;
use Zizaco\Confide\ConfideUser;
class User extends ConfideUser
{
public $autoPurgeRedundantAttributes = true;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* Soft delete
*
* #var boolean
*/
protected $softDelete = true;
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password');
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = array(
'nickname',
'password',
'email',
'deleted_at',
'disabled',
'firstname',
'lastname',
'birthday',
// needed by ardent
'email_confirmation',
'password_confirmation'
);
public static $rules = array(
'firstname' => 'required',
'email' => 'required|email|confirmed|unique:users',
'email_confirmation' => 'required',
'nickname' => 'required|min:2|unique:users',
'birthday' => 'date:d.m.Y|before:now',
'password' => 'required|min:5|confirmed',
'password_confirmation' => 'required'
);
public $imageSizes = array(
array(64, 64),
array(250, 250)
);
public static $sluggable = array(
'build_from' => 'nickname',
'save_to' => 'slug',
);
/**
* Roles
*
* #return object
*/
public function roles()
{
return $this->belongsToMany(
'Role',
'role_user'
)
->withTimestamps();;
}
}
Seems to me like this one is a bug: https://github.com/Zizaco/confide/issues/179
As a temporary workaround you can wrap the beforeSave() method in your Model without returning anything (!):
public function beforeSave($forced = false)
{
parent::beforeSave($forced);
}

Categories