I am trying to build some chat system using Laravel and i have these 2 models: User and Thread
The User model has Messagable Trait where you can get all the threads with
$user->threads();
I am trying to eager load additional data to the threads array using the following:
$threads = Auth::user()->threads()->with(['participants.user'])->get();
What i am struggling is the Threads model has function to get the latest message from it:
$thread->getLatestMessage();
My question is how can i append this latest message to the upper query i am doing. I was trying something like this but its not ok... I guess im doing something stupid here...
$threads = Auth::user()->threads()->with([
'participants.user',
'latestMessage' => function ($query) {
return $query->getLatestMessageAttribute();
}])->get();
or
$threads = Auth::user()->threads()->with(['participants.user','getLatestMessageAttribute'])->get();
I hope i clarified this ok because i am using a 3rd party package for this system which has these Traits and Thread classes i am using.
SOLUTION
Looks like i had to add append('accessor_name') at the end when getting the collection.
$collection = Auth::user()->relationship()->get()->append('accessor_name');
You can override class .Create new model and extend package model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Thread extends \Lexx\ChatMessenger\Models\Thread
{
use HasFactory;
protected $appends=['latest_message'];
}
Publish config:
php artisan vendor:publish --provider="Lexx\ChatMessenger\ChatMessengerServiceProvider" --tag="config"
in config/chatmessenger.php
'thread_model' => \App\Models\Thread::class,
Updated
If anyone still not getting get attribute data then dont forget to clear cache
php artisan cache:clear
php artisan optimize
php artisan config:clear
php artisan clear
Related
I started using Laravel few days before.
I'm actually struggling with a problem, I created a homepage and I want to replace some text of the page with content from my database.
So how do I create a model/controller, and after that I will make an admin panel, so I can edit them.
The only tutorials/docs I see are for making a form/post to create users
Example
In basic php it's easy you just do a pdo connection and then a fetch and you use your date as you want. How do you do it in laravel ?
To fetch data from the DB in Laravel can be done in 1 of two ways, 1. using a Model (the best way) or using a Query Builder, which is much more familiar to those migrating from pure PHP.
Using a Model
Create a model using php artisan make:Model (change Model with a name of your choosing) then open the model once created (found in app/Http/Models) and add the following under use HasFactory;:
protected $table = 'your_table_name';
protected $primaryKey = 'id'; // This is the column you usually set to PRIMARY
public $timestamps = true;
protected $fillable = [
'table_column',
'table_column',
];
To use the Model, import it into your Controller file like so use App\Models\Model; and then use it as so:
$flights = Flight::where('destination', 'Paris')->get();
Learn more about Models in Laravel here.
Using a Query Builder, not best practice
Import the DB facade in the controller like so use DB; then call upon it like so:
$db = DB::table('users')->where('name', 'John')->first();
Learn more about the Query Builder here.
I hope this helps, if not let me know how I can assist further.
I would like to know how I can get some fields in my db Mysql5.7 without using the faker technique in my controller, my db is not yet populated, if my db was not populated and I did not use this technique?
class ClientsController extends Controller{
public function index(){
$clients = Client::all()
return view(clients.index);
}
}
Faker is for generating random fake data to get started with your logic implementation. There are so many ways you can generate data for your model. One is through bulk insert. You can add multiple arrays at a time in your seeder.
Client::insert([
[// data],
[// data],
[// data],
[// data],
[// data]
]);
Populating fields with random data in controller is not a good option. I would recommend to use seeder without faker library with above code and when you migrate just add --seed parameter and it will work for you. You can use tinker too for this purpose. just paste the above code(with data arrays) in tinker and it will work for you.
try this
public function index(){
$clients = Client::all()
return view('clients.index',['clients' => $clients]);
}
Here is my question. I want to update the scout index saved in storage in my controller. Any ideas how to do it?
I am using tntsearch package. I know I can do artisan command in command prompt with $ php artisan scout:import App\\Models\\Paper
But I'm working on a website that everyone can submit their journals in it and I need a powerful search engine on my website. So in this situation, I need to update the index every time a journal submitted. So that everyone can be able to search the journals.
I manage to do a part of this task by making a provider TNTSearchScoutServiceProvider.
here is TNTSearchScoutServiceProvider:
class TNTSearchScoutServiceProvider extends \TeamTNT\Scout\TNTSearchScoutServiceProvider
{
public function boot()
{
$this->app[EngineManager::class]->extend('tntsearch', function ($app) {
$tnt = new TNTSearch();
$driver = config('database.default');
$config = config('scout.tntsearch') + config("database.connections.{$driver}");
$tnt->loadConfig($config);
$tnt->setDatabaseHandle(app('db')->connection()->getPdo());
$this->setFuzziness($tnt);
$this->setAsYouType($tnt);
return new TNTSearchEngine($tnt);
});
// To allow us run commands if we're not running in the console
$this->commands([
ImportCommand::class,
]);
}
}
After adding this provider to config/app.php. In the controller I am using the provider like this:
Artisan::call('tntsearch:import', ['model' => 'App\Models\Paper']);
But this throwes this error:
unlink(C:\wamp64\www\mywbsite\storage/papers.index): Resource temporarily unavailable
Here is what I accomplish so far:
although it throws the error,but I can only get the last updated row in search results and the oldest rows doesn't show up in the search results.
So what are your suggestions? Is it a better way to do this? Or I should check out the site every day and run the artisan commands so that the table can be indexed?
I finally managed to solve this problem:
to update the index in storage you just make a new obj from TNTindexer class; First, you create that index and after that, you select the columns you want to update with query() method. then run() the indexer.Before that make sure to load the configuration. here is the method that I write in the controller:
protected function add_to_search(){
$indexer = new TNTIndexer;
$driver = config('database.default');
$config = config('scout.tntsearch') + config("database.connections.{$driver}");
$indexer->loadConfig($config);
$indexer->createIndex('paper.index');
$indexer->query('SELECT id,title,description,abstract,keywords FROM papers;');
$indexer->run();
}
this way the index always updated through a controller.
I want to add column in my existing table in CakePHP 3.
My ContactsTable.php file code:
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
use Migrations\AbstractMigration;
class ContactsTable extends Table
{
public function initialize(array $config)
{
$this->addBehavior('Timestamp');
$table = $this->table('contacts');
$table->addColumn('price', 'decimal')->update();
}
}
I have tried as described in CakePHP 3 documentation but I got this error:
Call to a member function addColumn() on a non-object
How do I add columns on-the-fly via the controller?
Code:
<?php
namespace App\Controller;
use Cake\Core\Configure;
use Cake\Network\Exception\NotFoundException;
use Cake\View\Exception\MissingTemplateException;
use Cake\ORM\TableRegistry;
use Cake\Database\Schema\Table;
use Cake\Datasource\ConnectionManager;
use \Migrations\AbstractMigration as AbstractMigration;
use \Phinx\Db\Adapter\MysqlAdapter as MysqlAdapter;
class PagesController extends AppController
{
public function display()
{
$connectionArray = ConnectionManager::get('default')->config();
$connectionArray['pass'] = $connectionArray['password'];
$connectionArray['user'] = $connectionArray['username'];
$connectionArray['name'] = $connectionArray['database'];
$migrationObject = new AbstractMigration(mt_rand());
$migrationObject->setAdapter(new MysqlAdapter($connectionArray));
$tree = $migrationObject->table('tests');
$tree->addColumn('something', 'text')
->update();
}
}
After few hours of Hacking, finally found a way to do it on-the-fly.
Tested in default cakephp 3 (latest - as of today - 2nd June '16)
If you are using a different database adapter, change it to that adapater from MysqlAdapter.
Note to the users:
This is an ugly hack and should be used ONLY if you do not work in
an organization where each migration commit requires peer reference.
mt_rand() must NEVER be used as a version number hack.
There is no canonical way of doing it via the controllers. Update in a datasource MUST always be done modified via migrations - using a proper structure.
Refer to Running Migrations in a non-shell environment and try to create a migrations logs under /config/migrations, that would be more rule-specific-on-the-fly and you will also have logs for peers to review.
Migration plugin also support Running Migrations in a non-shell environment.
Since the release of version 1.2 of the migrations plugin, you can run migrations from a non-shell environment, directly from an app, by using the new Migrations class. This can be handy in case you are developing a plugin installer for a CMS for instance. The Migrations class allows you to run the following commands from the migrations shell: migrate, rollback, markMigrated, status and seed.
Each of these commands has a method defined in the Migrations class.
You can prepare some custom handler which will accept column data from user side and run migration. In this case it could be some form with name and type inputs. Migration will be applied to DB after form with data will be submitted.
Here is how to use it:
use Migrations\Migrations;
$migrations = new Migrations();
// Will return an array of all migrations and their status
$status = $migrations->status();
// Will return true if success. If an error occurred, an exception will be thrown
$migrate = $migrations->migrate();
// Will return true if success. If an error occurred, an exception will be thrown
$rollback = $migrations->rollback();
// Will return true if success. If an error occurred, an exception will be thrown
$markMigrated = $migrations->markMigrated(20150804222900);
// Will return true if success. If an error occurred, an exception will be thrown
$seeded = $migrations->seed();
If you want add new column to product table e.g 'price' and price is a 'decimal' you should go to your project and write this in console:
bin/cake bake migration AddPriceToProducts price:decimal
You can see a new file e.g. Config/Migrations/20160501190410_AddPriceToProducts.php
<?php
use Migrations\AbstractMigration;
class AddPriceToProducts extends AbstractMigration
{
/**
* Change Method.
*
* More information on this method is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-change-method
* #return void
*/
public function change()
{
$table = $this->table('products');
$table->addColumn('price', 'decimal', [
'default' => null,
...
'null' => true,
]);
$table->update();
}
}
and later just launch migrations to add this column to data base, write this in console:
bin/cake migrations migrate
i'm working on a web app using eloquent and laravel 5. The problem is that i'm trying to delete a row of a table called "Ponderacion" but when i send the ajax delete request, the server stops (it stops the execution of the routed function but the server keeps running) at the line where the delete is, without throwing any errors.
Here is the Model of Ponderacion:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Ponderacion extends Model{
protected $table = 'Ponderacion';
protected $fillable = array('ponderacionidearea', 'ConfiguracionDeExamenifconf', 'peso');
public $timestamps = false;
}
Here is the function in the Controller:
public function deleteConfig(Request $request){
error_log('deleting');
$s_area = Area::where('nombre', '=', $request->input('s_area'))->first();
error_log(count($s_area->Configuracion->first()->Ponderacion));
//DB::statement('delete from Ponderacion where idponderacion = 22');
foreach ($s_area->Configuracion->first()->Ponderacion as $ponderacion){
error_log($ponderacion->peso);
try{
$ponderacion->delete();
}catch(Exception $e){
error_log('failure');
}
}
//$s_area->Configuracion->first()->Ponderacion->delete();
error_log('succesfully deleted');
$s_area->Configuracion->first()->delete();
}
I can succesfully print the property "peso" of ponderacion but i'm unable to delete it. Ponderacion has Foreign Keys to other table but no other table has a reference to Ponderacion. I'm able to delete a row of Ponderacion with DB::statement but that is not secure.Succesfully deleted never shows on console.
Thanks in advance.
For AJAX testing, I always prefer to directly test via a GET request first where possible and then layer on the AJAX POST once I know the underlying code works.
In this case, the server is likely throwing a Fatal Error, which will then return a 500 error for an AJAX request and no further information. There is a good SO question that deals with catching Fatal Errors.
I would check your includes for your class. In Laravel 5, the default namespace is not the global namespace for Controllers. You'll need to add a \ before Exception or add use Exception to the top of your class file.
Two tips as well:
Use SoftDeletes on your model. It's better to track and audit your database records if you never really remove a row. DB storage space is really cheap and Laravel will automatically skip the deleted rows when querying.
Use an IDE for development. A lot of these errors can be caught before run-time by a good compiler.