I am trying to make an "unread" function for my messenger. When I refresh try to refresh the database it shows
There is no column with name 'read' on table 'messages'.
This error and my "unread" feature is not working. I am using SQlite.
Here's my Unread migration:-
public function up()
{
Schema::table('messages', function (Blueprint $table) {
$table->boolean('read')->after('to')->default(false);
});
}
public function down()
{
Schema::table('messages', function (Blueprint $table) {
$table->dropColumn('read');
});
}
Here my Messages migration:-
public function up()
{
Schema::create('messages', function (Blueprint $table) {
$table->id();
$table->integer('from')->unsigned();
$table->integer('to')->unsigned();
$table->text('text');
$table->timestamps();
});
}
Here's my controller:-
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use App\Friend;
use App\Message;
use App\Events\NewMessage;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class ContactsController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('home');
}
public function get(){
$sem = Auth::user()->id;
$contacts = DB::table('friends')
->where('my_id', $sem)
->get();
// get a collection of items where sender_id is the user who sent us a message
// and messages_count is the number of unread messages we have from him
$unreadIds = Message::select(\DB::raw('`from` as sender_id, count(`from`) as messages_count'))
->where('to', auth()->id())
->where('read', false)
->groupBy('from')
->get();
// add an unread key to each contact with the count of unread messages
$contacts = $contacts->map(function($contact) use ($unreadIds) {
$contactUnread = $unreadIds->where('sender_id', $contact->friends_id)->first();
$contact->unread = $contactUnread ? $contactUnread->messages_count : 0;
return $contact;
});
return response()->json($contacts);
}
public function getMessagesFor($id)
{
$messages = Message::where('from', $id)->orWhere('to', $id)->get();
$messages = Message::where(function($q) use ($id) {
$q->where('from', auth()->id());
$q->where('to', $id);
})->orWhere(function($q) use ($id){
$q->where('from', $id);
$q->where('to', auth()->id());
})
->get();
return response()->json($messages);
}
public function send(Request $request)
{
$message = Message::create([
'from' => auth()->id(),
'to' => $request->contact_id,
'text' => $request->text
]);
broadcast(new NewMessage($message));
return response()->json($message);
}
}
This is where contacts Ids are coming from:-
public function up()
{
Schema::create('friends', function (Blueprint $table) {
$table->id();
$table->string('created_by');
$table->string('my_id');
$table->string('friends_id');
$table->string('name');
$table->timestamps();
});
}
I can't seem to figure out the problem and have been stuck with this since weeks, your help would really be appreciated.
There are a few things that may be causing you issues with your migration.
You have a couple of reserved words in SQL (thought maybe not in
SQLite) that could be causing an issue. I would remove them in favor
of something that is not potentially causing a conflict.
You might assign foreign keys to the database so it will play nice
with your models. Then you don't have to go through the whole
DB::raw('from... stuff, it is automatically assigned by the model
if you set up the relationships correctly.
I think the issue you are having though, is that you may be using the
migration a bit differently that expected. Why not put the boolean
field on the original migration? If this migration isn't run, or is
run in the wrong order, or if it is run in down() mode, that read
field will not be in the database table.
I suggest to test, start with the following migration. Make note of the different (non-conflicting) field names and the auto-increment field:
Schema::create('messages', function (Blueprint $table) {
$table->increments('id');
$table->integer('from_id')->unsigned();
$table->integer('to_id')->unsigned();
$table->boolean('has_read')->default(false);
$table->text('text');
$table->timestamps();
});
Run a fresh migration on the database with this. Rework your controller code to work with the new field names and test. If this fixes the error:
There is no column with name 'read' on table 'messages'.
Then I would recommend adding in the foreign keys to those ids like this for example:
$table->foreign('from_id')->references('id')->on('users');
But this is a whole different issue and requires re-working of your controller db draws. For now, see if the above migration will solve the original error.
Related
Before I get into what my issue is, here is my setup. (FYI I am stuck using Laravel 7.4 at the moment so SOS):
Applications Table
public function up()
{
Schema::create('applications', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
Reports Table
public function up()
{
Schema::create('reports', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
ApplicationReports Table (I know the naming convention is off, but this is how I have to do it for code base)
public function up()
{
Schema::create('applicationReports', function (Blueprint $table) {
$table->unsignedInteger('application_id')->nullable(false);
$table->unsignedInteger('report_id')->nullable(false);
});
}
Here is an example of the ApplicationReports table
application_id
report_id
200
2
Then I have a many to many relationship setup between the Applications and Reports tables like so:
Applications Model
public function reports() {
return $this->belongsToMany(Report::class, 'applicationReports');
}
Reports Model
public function applications() {
return $this->belongsToMany(Application::class, 'applicationReports');
}
In the ReportsController I have a method that will pull all the reports that are in the reports table and then return them, that method looks a little bit like the code below (pseudo coded some of it). But what I am trying to do is only add reports that are associated with applications to the list. When I try the code below doing $report->applications->has($report->id) its returning false and I can't for the life of me figure it out.
public function getReports() {
//Pseudo codeish right here, sorry.
$reports = gets all reports->with(['applications'])->orderBy('name')->get();
$reportsList = [];
foreach ($reports as $report) {
if ($report->applications->has($report->id)) {
$reportsList[] = $report;
}
}
return $reportList;
}
If I dd $report->applications the relationship is there and I can see it under #relations -> #attributes, any help would be appreciated!
The has function is very straight forward.
You can query your reports that only contains applications by doing:
$reports = Report::with('applications')->has('applications')->get();
return $reports;
in other way you can also use whereHas this will accepts Query Builder that you can pass through.
For example:
$reports = Report::with('applications')
->whereHas('applications', function(Builder $query) {
$query->orderBy('created_at');
})->get();
return $reports;
I have a laravel model based on the following table:
public function up()
{
Schema::create('things', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('label');
$table->foreignId('user_id')->nullable()->constrained('users');
});
There is also a pivot table that makes this a many-to-many self-referential model.
public function up()
{
Schema::create('thing_thing', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('message')->nullable();
$table->unsignedBigInteger('parent_id')->nullable();
$table->unsignedBigInteger('child_id')->nullable();
$table->unique(['parent_id', 'child_id']);
$table->foreign('parent_id')->references('id')->on('things')->onDelete('cascade');
$table->foreign('child_id')->references('id')->on('things')->onDelete('cascade');
});
}
When I create a Nova resource linked to this model, I would like to restrict the attaching of a thing to itself. So a thing with id = 1, for example, would not show up in the selector for attachments for the thing with id = 1. Here's my Nova resource:
public function fields(Request $request)
{
return [
ID::make(__('ID'), 'id')->sortable(),
Text::make('label'),
ID::make('user_id')->hideWhenUpdating()->hideWhenCreating(),
BelongsToMany::make('Trees', 'trees'),
BelongsToMany::make('Things', 'childOf'),
BelongsToMany::make('Things', 'parentOf')
];
}
You can solve this through the App\Nova\Ressource's relatableQuery method. Simply override the method in your nova resource:
class Thing extends Resource {
// ...
public static function relatableQuery(NovaRequest $request, $query)
{
// Make sure you only apply the filter to the things-things relatable query
if( $request->route('resource') === 'things' ) {
$currentId = $request->route('resourceId');
$query->where('id', '!=', $currentId);
}
return $query
}
}
You can find the docs here
In addition, you might want to make the column-combination of parent_id and child_id unique in your migration to further ensure uniqueness.
I'm trying to give ability on user to see his orders. I have created relationships but when i (dd) the result of the function, the related model attributes are empty.
I don't know what is wrong.
Here is my buyer function
//Buyer Orders
public function myOrders()
{
$user = User::find(auth()->user()->id);
$user = $user->products();
dd($user);// related model attributes shows empty
return view('myOrders')->with(compact('user'));
}
and here is my user
public function products()
{
return $this->hasMany(Products_model::class);
}
public function orders()
{
return $this->hasMany(Order::class);
}
public function allOrdersBuyerSeller()
{
return $this->hasMany(OrderProduct::class);
}
products_model
public function orders()
{
return $this->belongsToMany('App\Order', 'order_product');
}
public function user()
{
return $this->belongsTo('App\User');
}
User Migration
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Product Migration
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('pro_name');
$table->integer('pro_price');
$table->text('pro_info');
$table->integer('stock');
$table->integer('category_id');
$table->string('image')->nullable();
$table->timestamps();
$table->bigInteger('seller_id')->unsigned()->index();
$table->foreign('seller_id')->references('id')->on('users')->onDelete('cascade');
});
}
I would like to see the attributes of the table like price, name, info, img and etc.
Barring the comments about your code, the reason you're not seeing the result of your products query is that you're not passing a closure to the query.
$user = $user->products();
Currently, $user is a QueryBuilder instance. Until you use a closure, like first(), get(), paginate(), etc, you won't be able to see the rows. Modify your code to the following:
$products = $user->products;
// OR
$products = $user->products()->get();
If you omit the (), it will load the relationship using products()->get(), unless already loaded.
Edit: You likely need to include foreign keys to your relationships as the Model name won't match:
User.php
public function products(){
return $this->hasMany(Product_model::class, "seller_id", "id");
}
Probably best to review the contents of the documentation for Relationships; https://laravel.com/docs/5.8/eloquent-relationships. There's a lot of incorrect practices going on with your naming, querying, etc.
The following code in tinker returns a null value while it should return the project to which the first task is linked.
App\Task::first()->projects;
Already tried renaming the method names, column names in migrations, tried exiting tinker and logging back in
Project Migration
public function up()
{
Schema::create('projects', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('title');
$table->string('description');
$table->timestamps();
});
}
Task Migration
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedInteger('project_id');
$table->string('description');
$table->boolean('completed')->default(false);
$table->timestamps();
});
}
Project.php
use App\Task;
class Project extends Model
{
protected $fillable = ['title','description'];
public function tasks(){
return $this->hasMany(Task::class);
}
}
Task.php
use App\Project;
class Task extends Model
{
protected $fillable = [
'completed'
];
public function projects(){
return $this->belongsTo(Project::class);
}
}
If anyone could just review this piece of code and let me know where I have made any conventional\idiotic mistakes (since Im new to route model binding) it would be of great help!
A task belongs to a project, so rename projects to project as it is singular. If you keep projects then provide the column name as second parameter:
public function projects(){
return $this->belongsTo(Project::class, 'project_id');
}
// I suggest this
public function project(){
return $this->belongsTo(Project::class);
}
Your column types are different, for the id of the project you use Big Integer and for the reference you use Integer, so this:
$table->unsignedInteger('project_id');
should be this:
$table->unsignedBigInteger('project_id');
// also good to make the relationship on the Database level:
$table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');
in Laravel using Schema Builder
how i can create a column and in the same time update his value whit the other value of the same table?
Its possible?
Thanks
Pseudo code
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddSkuToWaranties extends Migration {
public function up()
{
Schema::table('my_table_name', function(Blueprint $table) {
$table->text('my_table_column');
///////////////////////
$table->my_table_column = $table->my_other_table_column;
///////////////////////
});
}
public function down()
{
Schema::table('my_table_name', function(Blueprint $table) {
$table->dropColumn('my_table_column');
});
}
}
Yes that is possible. You can do it like this:
DB::table('my_table_name')
->update(array('my_table_column' => DB:raw('my_other_table_column')));
With this, you are using Laravel's Query Builder. It actually builds this query for you:
update my_table_name set my_table_column = my_other_table_column
Another solution is to just execute this raw query:
DB::update('update my_table_name set my_table_column = my_other_table_column');
As #lukasgeiter mentioned in a comment, you must place this code outside the closure, so this becomes the new up() method:
public function up()
{
Schema::table('my_table_name', function(Blueprint $table) {
$table->text('my_table_column');
});
DB::table('my_table_name')
->update(array('my_table_column' => DB:raw('my_other_table_column')));
}