Laravel session table add additional column - session

I want to add an extra column user_id on session table.
The reason is, some time there are spammer to sign up fake account, once I know that the user is spammer, I want to log the user out by deleting the session record.
Is it possible to achieve this?

This is the session migration schema:
Schema::create('sessions', function($table)
{
$table->string('id')->unique();
$table->text('payload');
$table->integer('last_activity');
$table->integer('user_id')->unsigned(); //// ADD IT!
});
You can add whatever column you like on it, Laravel won't mind.
Or you can create a new migration and make it add a column on that table.
$table->integer('user_id')->unsigned();
You can create a Model for it:
class SessionModel extends Eloquent {
}
And do whatever you need with it:
$session = SessionModel::find(Session::getId());
$session->user_id = 1;
$session->save();
But if you're thinking about adding more info to the payload, which is where Laravel keeps the session data, although I think it's possible, you'll have to dig a bit more in Laravel's code to do that.

Short version of migration
if( Schema::hasTable('sessions') ) {
$table->integer('user_id')->unsigned();
}
Need to check if exist session table. Or create it before:
php artisan session:table
php artisan migrate
https://laravel.com/docs/5.7/session#introduction

This is the session migration schema:
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->unique();
$table->integer('user_id')->nullable();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->text('device')->nullable();
$table->text('payload');
$table->integer('last_activity');
});
To add the information to the payload after adding COLUMN to the TABLE, just change the DatabaseSessionHandler class.
path: vendor/laravel/framework/src/illuminate/Session
Ex:
1º Creates the function
protected function device()
{
$agent = new \Jenssegers\Agent\Agent;
if ($agent->isDesktop()){
$device = 'desktop';
}
return $device;
}
2º add in function addRequestInformation (& $ payload)
protected function addRequestInformation(&$payload)
{
if ($this->container->bound('request')) {
$payload = array_merge($payload, [
'ip_address' => $this->ipAddress(),
'user_agent' => $this->userAgent(),
'device' => $this->device(),
]);
}
return $this;
}
Ready, device added to the table when the user login.

Related

laravel access related model using mutator during $user->posts()->create([...])

I have User and Post models.
Would like to access the User when the mutator for the post's title is being called at the time of the post creation. Similar to a question from a few years ago.
But I am unable to access the User inside the Posts title mutator.
Tried $this->user->id (preferred). Also tried: $this->user_id, $this->user()->get()->id.
>>> User::first()->posts()->create(['title'=>'test '.now()])
PHP Warning: Attempt to read property "id" on null <<<=== when trying $this->user->id
=> App\Models\Post {#4155
title: "test 2021-05-08 11:41:55", <<<=== title is shown before user_id
user_id: 1, <<<=== but in migration user_id is defined *before* title
updated_at: "2021-05-08 11:41:55",
created_at: "2021-05-08 11:41:55",
id: 1,
user: null, <<<=== note "user" attribute is added as result of the $this->user->id
}
Would think the user is definitely known at that time, as we're using that user to add a post to.
If I make the user_id fillable, then this one works as expected (for that one: the array order matters):
Post::create(['user_id'=>User::first()->id, 'title'=>'test '.now()])
But, that's less... eloquent.
My config + test details:
// Post.model
protected $fillable = [
// 'user_id', // also tried with making user_id fillable
'title',
];
public function setTitleAttribute($value) {
// dump($this->user_id); // null
// dump($this->user); // null (& adds empty user property to this)
// dump($this->user->id); // PHP Warning: Attempt to read property "id" on null (& adds property)
// dump($this->user()->get()); // empty collection Illuminate\Database\Eloquent\Collection
// dump($this->user()->toSql()); // select * from "users" where "users"."id" is null
$this->attributes['title'] = $value;
}
public function user() {
return $this->belongsTo(User::class);
}
// User.model
public function posts() {
return $this->hasMany(Post::class);
}
// posts migration
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained();
$table->string('title');
$table->timestamps();
});
Using mysql as DB.
This seems to be the safest + cleanest: use boot event closure 'creating', which is triggered after the mutators and right before data is saved to the database.
public static function boot() {
parent::boot();
static::creating(function (Post $post) {
// now we have both $post->user and $post->title
dump($post->user->name);
dump($post->title);
});
}
can you provide more detail?
try this
auth()->user()->id
if user is logged in
if u want select user from db
User::where("filed name","value")->first()->id

Wrong migration called

I have 2 migrations, the first one has the following name 2019_11_06_171637_create_settings_table.php and structure:
class CreateSettingsTable extends Migration
{
public function up()
{
Schema::create('settings', function (Blueprint $table) {
//code
});
}
//function down
}
the second one has the following name 2020_07_08_246856_create_settings_table.php and structure:
class CreateAnotherSettingsTable extends Migration
{
public function up()
{
Schema::create('another_settings', function (Blueprint $table) {
//code
});
}
//function down
}
When I run php artisan migrate all migrations going well until Migrating: 2020_07_08_246856_create_settings_table - it's trying to run the previos migration(2019_11_06_171637_create_settings_table.php) and fire an exception Table 'settings' already exists.
Does this mean that the name of the migration file must be unique after the date and numbers?
I've read somewhere that Laravel uses the filenames of migrations to call the correct class for the migration. I've tried to look up some documentation or reference on this, but I can't find it anymore. You currently have the same filename twice (if you ignore the timestamp part) which results in Laravel calling the same class twice.
If you rename the second file (the one with the CreateAnotherSettingsTable class) to 2020_07_08_246856_create_another_settings_table.php, your problem will be fixed.
I found this very interesting so I looked within the source code.
\Illuminate\Database\Console\Migrations\TableGuesser will use the migration name to determine whether if the table already exists.
// Next, we will attempt to guess the table name if this the migration has
// "create" in the name. This will allow us to provide a convenient way
// of creating migrations that create new tables for the application.
if (! $table) {
[$table, $create] = TableGuesser::guess($name);
}
This is executed upon artisan:make and migrate:install commands.
So ultimately, as your migration file name is create_settings_table.php, the "settings" word is what will be used for checking.
The code that laravel uses for this determination is:
const CREATE_PATTERNS = [
'/^create_(\w+)_table$/',
'/^create_(\w+)$/',
];
const CHANGE_PATTERNS = [
'/_(to|from|in)_(\w+)_table$/',
'/_(to|from|in)_(\w+)$/',
];
/**
* Attempt to guess the table name and "creation" status of the given migration.
*
* #param string $migration
* #return array
*/
public static function guess($migration)
{
foreach (self::CREATE_PATTERNS as $pattern) {
if (preg_match($pattern, $migration, $matches)) {
return [$matches[1], $create = true];
}
}
foreach (self::CHANGE_PATTERNS as $pattern) {
if (preg_match($pattern, $migration, $matches)) {
return [$matches[2], $create = false];
}
}
}
So your solution is to rename one of those migration files.
CreateAnotherSettingsTable will be the best, standard following, name

laravel relationship one to many

before anything ,Highly appreciated in advance for help . i have two model
user:
public function posts(){
return $this->hasMany('App\Post');}
post:
public function user(){
return $this->belongsTo('App\user');}
my post have column "user_id" so every post have owner "user_id".
here is my question: i want to delete user but nothing happen to related post. right now i can do this ,but my problem is post_id column have id belongs to deleted user. i want to change that to "null" or "0".
You can do this with model events. Something like this on your User model.
public static function boot() {
parent::boot();
static::deleting(function($user) {
$user->posts()->update(['user_id' => null]);
});
}
Also make sure the user_id field is nullable on the migration.
Just make sure that your post_id field is set to nullable in your migration AND in your database.
You can do this with SQL power - add a migration to your table "posts"
...
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('set null');
It will create a foreign key which sets null to related field on deleting user row
You can change the function boot() from User model:
protected static function boot() {
parent::boot();
static::deleting(function($user) {
$user->posts()->delete();
});
}

Laravel eloquent attach auto generate random ID

I have an eloquent many to many relationship and I want to use attach() to easily create role_permissions data but the problem is I'm using an UUID for my ID and it throws an error Field 'id' doesn't have a default value. Any way of hijacking the attach() method? so I can set my UUID?
My migration
Schema::create('role_permissions', function (Blueprint $table) {
$table->increments('count')->unique();
$table->string('id')->unique();
$table->string('role_id');
$table->string('permission_id');
$table->timestamps();
});
My model
class Role extends Model
{
//
public $incrementing = false;
public function users()
{
return $this->belongsToMany('App\User', 'user_roles', 'role_id', 'user_id');
}
public function permissions()
{
return $this->belongsToMany('App\Permission', 'role_permissions', 'role_id', 'permission_id');
}
}
My attach code
$role->permissions()->attach($permission_ids);
I know the problem here is that my id is not an incrementing number it's an unique string. My question is how do I "Inject" that unique string to the attach() method? Thank you guys.
The error
Field 'id' doesn't have a default value
refers to the fact that your database does not know how to fill the id field when it's not specified.
Either you edit the schema adding a nullable:
Schema::create('role_permissions', function (Blueprint $table) {
$table->increments('count')->unique();
$table->string('id')->unique()->nullable(); // Bad idea
$table->string('role_id');
$table->string('permission_id');
$table->timestamps();
});
or injecting it via attach:
$role->permissions()->attach($permission_ids, ["id" => null]);
More info on Laravel official doc
Update
For the future developers who encounter this problem you can also set anything inside the attach array, for example:
$role->permissions()->attach($permission_ids, ["id" => Uuid::generate()]);
Update 2
There's also a more clean way to handle this to be honest. I will try to explain it.
You can handle the Pivot events inside the event service provider by simply hooking into the bootmethod:
Here's a snippet
/App/Providers/EventServiceProvider.php
public function boot()
{
Pivot::creating(function($pivot) {
if ($pivot->getTable() == 'role_permissions') {
$pivot->id = Uuid::generate();
}
});
}
Be aware I do not know if this is actually possible on your laravel version. Mine (5.4.*) works as intended
Okay managed to fixed it, what I did with the help of #Claudio Ludovico Panneta's tip.
foreach($permission_ids as $permission_id)
{
$role->permissions()->attach($permission_id, ["id" => Uuid::generate()]);
}

How to fix error Base table or view not found: 1146 Table laravel relationship table?

I am a new of laravel I try to create relationship many to many between table,My problem when I am insert data in to database I got errors
QueryException in Connection.php line 713: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'learn.category_posts' doesn't exist (SQL: insert into category_posts (category_id, posts_id) values (4, ))
can anyone help me pls . and here below is my migrate and code:
2016_08_04_131009_create_table_posts.php
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->text('title');
$table->text('body');
$table->timestamps();
});
}
2016_08_04_131053_create_table_categories.php
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
2016_08_04_131413_create_table_category_posts.php
public function up()
{
Schema::create('category_post', function (Blueprint $table) {
$table->increments('id');
$table->integer('category_id')->unsigned();
$table->integer('post_id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories')->onUpdate('cascade')->onDelete('cascade');
$table->foreign('post_id')->references('id')->on('posts')->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
}
and my model Posts.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Posts extends Model
{
protected $table = 'posts';
public function categories()
{
return $this->belongsToMany('App\Category');
}
}
Category.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = 'categories';
public function posts()
{
return $this->belongsToMany('App\Posts');
}
}
My PostsController.php
public function create()
{
$categories = Category::all();
return view('create',compact('categories'));
}
public function store(Request $request)
{
$post = new Posts;
$post->title = $request->title;
$post->body = $request->body;
$post->categories()->attach($request->categories_id);
return redirect()->route('posts.index');
}
My View create.blade.php
{!!Form::open(array('route' => 'store', 'method' => 'POST'))!!}
{{Form::text('title')}}<br>
{{Form::textarea('body')}}<br>
<select name="categories_id" multiple>
#foreach ($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
#endforeach
</select>
<br>
{{Form::submit('submit')}}
{!!Form::close()!!}
It seems Laravel is trying to use category_posts table (because of many-to-many relationship). But you don't have this table, because you've created category_post table. Change name of the table to category_posts.
Laravel tries to guess the name of the table, you have to specify it directly so that it does not give you that error..
Try this:
class NameModel extends Model {
public $table = 'name_exact_of_the_table';
I hope that helps!
Schema::table is to modify an existing table, use Schema::create to create new.
The main problem for causing your table unable to migrate, is that you have running query on your "AppServiceProvider.php" try to check your serviceprovider and disable code for the meantime, and run php artisan migrate
You can add this in Post Model,
public function categories()
{
return $this->belongsToMany('App\Category','category_post','post_id','category_id');
}
category_post indicate the table you want to use.
post_id indicate the column where you want to store the posts id.
category_id indicate the column where you want to store the categories id.
For solving your Base Table or view not found error you can do As #Alexey Mezenin said that change table name category_post to category_posts,
but if you don't want to change the name like in my case i am using inventory table so i don't want to suffix it by s so i will provide table name in model as protected $table = 'Table_name_as_you_want' and then there is no need to change table name:
Change your Model of the module in which you are getting error for example:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Inventory extends Model
{
protected $table = 'inventory';
protected $fillable = [
'supply', 'order',
];
}
you have to provide table name in model then it will not give error.
The simplest thing to do is, change the default table name assigned for the model. Simply put following code,
protected $table = 'category_posts'; instead of protected $table = 'posts'; then it'll do the trick.
However, if you refer Laravel documentation you'll find the answer. Here what it says,
By convention, the "snake case", plural name of the class(model) will be used as the table name unless another name is explicitly specified
Better to you use artisan command to make model and the migration file at the same time, use the following command,
php artisan make:model Test --migration
This will create a model class and a migration class in your Laravel project. Let's say it created following files,
Test.php
2018_06_22_142912_create_tests_table.php
If you look at the code in those two files you'll see,
2018_06_22_142912_create_tests_table.php files' up function,
public function up()
{
Schema::create('tests', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
Here it automatically generated code with the table name of 'tests' which is the plural name of that class which is in Test.php file.
You should change/add in your PostController: (and change PostsController to PostController)
public function create()
{
$categories = Category::all();
return view('create',compact('categories'));
}
public function store(Request $request)
{
$post = new Posts;
$post->title = $request->get('title'); // CHANGE THIS
$post->body = $request->get('body'); // CHANGE THIS
$post->save(); // ADD THIS
$post->categories()->attach($request->get('categories_id')); // CHANGE THIS
return redirect()->route('posts.index'); // PS ON THIS ONE
}
PS: using route() means you have named your route as such
Route::get('example', 'ExampleController#getExample')->name('getExample');
UPDATE
The comments above are also right, change your 'Posts' Model to 'Post'
try checking in the app if you are using the tables before it's created
such as appServiceProvider.php
you might be calling the table without being created it, if you are, comment it then run php artisan migrate.
This problem occur due to wrong spell or undefined database name. Make sure your database name, table name and all column name is same as from phpmyadmin
If you're facing this error but your issue is different and you're tired of searching for a long time then this might help you.
If you have changed your database and updated .env file and still facing same issue then you should check C:\xampp\htdocs{your-project-name}\bootstrap\cache\config.php file and replace or remove the old database name and other changed items.
Just run the command:
php artisan migrate:refresh --seed
If you are getting the error "SQLSTATE[42S02]: Base table or view not found" and you have no problem in your code, check if you have wrote the first letter of the table in capital letter.
Inspections >> inspections
capital case and small case letters matters on AWS environments.

Resources