Laravel 5.3 Pulling comments from the fields of a DB table - laravel

Simple question here:
In laravel 5.3 how would I pull the comments from a database table? Is there a clean way of doing it using some of the out-of-the-box features that laravel provides??
Thank you in advance.

Laravel 5.2-5.3, as far as I know, comes with a built-in package called doctrine that allows you to interact with a lot more within a database and it's tables than eloquent. I believe the framework members will eventually add more to the system so you can make more dynamic use of a DB and tables etc.
For the time being this is how I implement accessing the structure (comments included) of a database table:
$settings = SomeModel::where($items_match)->get(); //Making use of Eloquent
$columns = DB::connection('database_name_here')
->getDoctrineSchemaManager()
->listTableDetails('table_name_here');
foreach ($settings as $key => $value) {
if ($comments[$key] = $columns->getColumn($key)->getComment()) {
}
}
It's fairly clean and get's the job done. The only downside I see is it's a double hit to the DB which I'm thoroughly against, I'm working on a way to combine the 2 implementations in laravel so that it's only 1 query doing both jobs.

Related

Can this block of code of mine can be improved

[This is to populate data from two tables that one has two foreign keys from the same column as reference on the other table]
https://i.stack.imgur.com/D8fiv.png
[This is my schema for the table with the foreign key]
https://i.stack.imgur.com/eYDL0.png
This is written in laravel and it is working however i have an itchy feeling that this is wrong
As someone else has commented, you should put the code in your question. More context might also be necessary as it's not clear what you are trying to return from your view(). Are you returning $citizen, $family, or both? It would also be helpful to include what version of Laravel you are using. I'll assume you are using the latest Laravel 8.
Your code should work but you are making more work for yourself if you don't utilize Laravel's relationships. If you do, all the query stuff you have in your code can be reduced to just a few short lines of code such as this:
public function view(Citizen $citizen)
{
$citizen->load('family');
return $citizen;
}
Database Migration
You can shorten your migration by using foreignId(). See docs for details
https://laravel.com/docs/8.x/migrations#foreign-key-constraints
Before:
$table->integer('client_id')->unsigned();
$table->foreign('client_id')->references('id')->on('citizens');
After:
$table->foreignId('client_id')->constrained();
Route Model Binding
I'm assuming your view() method is in your controller and is called from a route. Since the one parameter required is the client's id, you can use Route Model Binding and skip fetching the client from the database.
https://laravel.com/docs/8.x/routing#route-model-binding
public function view(Citizen $citizen)
{
// your code
}
Relationships
You seem to have relationships set up but you aren't using them to load data. You should be able to load the related objects without any manual queries.
If you have a belongsTo(One to Many) relationship on the Citizen model to the Family model, you can load it like this:
$citizen->load('family');
or just use it like this
$relationship = $citizen->family->relationship;
I don't know what the relationships between your models are but you should read up on the different relationship types in the docs.
https://laravel.com/docs/8.x/eloquent-relationships

Current model is incompatible with old migrations

I have following sitation (I will describe it as history line):
I setup project witch User model (and users table) with migration file A
After some time i add user_modules table many-to-many and I was force to initialize this array during schama update in migration file B. I do it by
User::chunk(100, function($users) {
foreach ($users as $user) {
$user->userModule()->create();
}
});
After some time i need to update User model and table by add soft-delete (column delete_at) in migration file C and field $dates=['deleted_at'] in User model.
Then I develop system and add more migrations but at some point new developer join to our team and he must build DB schema from scratch so he run php artisan:migrate but he get error in migration file B:
[Illuminate\Database\QueryException (42S22)]
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'users.deleted_at' in 'where clause' (SQL: select * from users
where users.deleted_at is null order by users.id asc limit 100
off set 0)
So the current User model is incompatible witch migration file B
How to deal with that situation?
Where I made mistake and what to do to prevent such situation in future?
This is because of Soft Deletes. When you add the trait SoftDeletes to a model, it will automatically add where users.deleted_at is null to all queries. The best way to get around this is to add withTrashed() to your query in migration B.
To do this, change your query in migration B to look like the following. This should remove the part where it's trying to access the non existent deleted_at column. This migration, after all, is not aware that you want to add soft deletes later on, so accessing all users, including those that are trashed, makes perfect sense.
User::withTrashed()->chunk(100, function($users) {
foreach ($users as $user) {
$user->userModule()->create();
}
});
You could always comment out the SoftDelete trait on the user model before running the migrations also, but that's a temporary fix since you'll need to explain it to all future developers. Also, it can be very handy to run php artisan migrate:fresh sometimes. You don't want to have to remember to comment out the trait each time, so adding withTrashed() seems like the most desirable solution to me.
As a final note, I highly suggest NOT adding seeds to your migrations. Migrations should ONLY be used for schema changes. In cases like this, I would use a console command, or a combination of console commands.
For example, you could make a console command that gets triggered by php artisan check:user-modules. Within this command, you could have the following which will create a user module only if one does not yet exist.
User::chunk(100, function($users) {
foreach ($users as $user) {
if (!$user->userModule()->exists()) {
$user->userModule()->create();
}
}
});
You should be able to run this command at any time since it won't overwrite existing user modules.
Alternative answer: In such situation when we need to generate or transform some data after db schema change - we should NOT use Models (which can independently change in future) but instead use inserts/updates:
DB::table('users')->chunkById(100, function ($users) {
foreach ($users as $user) {
DB::table('user_modules')->insert(
['user_id' => $user->id, 'module_id' => 1]
);
}
});
As it is written in laravel documentation, seeders are designed for data seeding with test data but not for data transformation - so migration files are probably good place to put transformation code (which can generate or change some production data in DB after schema update)
Laravel includes a simple method of seeding your database with test data using seed classes.
Add this to your old migration queries
use Illuminate\Database\Eloquent\SoftDeletingScope;
User::withoutGlobalScope(new SoftDeletingScope())

Algolia save only strings using Laravel 5.4

I use Laravel 5.4 and i integrate algolia with my project, but I have some problems with data type of columns.
If I run the command from the localhost, status columns (and others) appear like integer in algolia database, but if I run the same artisan command from the production environment, the status column is now string, and I can't use ->where('status', 1) in my code, because algolia can use only integers for where clauses.
Is there a problem with my database? But is the same database from my localhost, same mysql version...
I don't know what could be the reason of this, but I think I know a good work around.
Let me also say that Algolia can have string as a where clause, but it's an intentional limitation of Laravel Scout.
You can use the toSearchableArray in your model to customize the array sent to Algolia. I'd use it to cast the data.
https://laravel.com/docs/5.5/scout#configuring-searchable-data
You should have something like this:
public function toSearchableArray()
{
$data = $this->toArray();
$data['attribute'] = (int) $data['attribute'];
return $data;
}

Where to process data in Laravel

Back when I was using CodeIgniter I had functions in my models like
public function GetArticlesFormatted($inactive = FALSE)
and then in my controller I could have had
$articles->GetArticlesFormatted(true);
And so on.
How should I achieve the same with Laravel 5.4? The database of the app I'm building is already built and full and is a mess so most of the "automated" super-restrictive things that Laravel has don't work out of the box.
For example there is a Country Code that I'm retrieving and I need it as is, but in some instances I need it converted in a Country Name which I had in another table.
Right now I just have in my controller wherever I am retrieving data from the model:
$countryResult = Country::where('country_code', $item['country_code'])->first();
$countryArray = $countryResult->toArray();
$item['country'] = $countryArray['country_name'];
Can I somehow achieve that in a more elegant way?
I tried accessors but for some reason couldn't get anything to work for my purposes.
A select query can be used to limit selection to a particular column.
$countryName = Country::select('country_name')
->where('country_code', $item['country_code'])
->first();

laravel 5.2 work with belongs to with two different queries

I have write down this query
Controller
$data = User::where('name',$name)->with('country');
In User model
function country () {
return $this->belongsTo('App\Country');
}
In view
echo $data->country->name;
It is working fine but it run 2 queries :(
Select * from user where name = "xyz"
Select * from country where id = "745"
I want to stop this, I want to fetch data with one query only. Join is the solution, Is any other solution for this?
Unfortunately this is the way Eloquent works. It uses two queries because it's a simpler task to initialise your models and to avoid column naming conflicts.
If you are concerned about performance but still want some sort of querying tool, use the Query Builder shipped with Laravel.
To answer your question, joins will be your best bet.
$data=user::with('country')->where('id',745)->where('name','xyz')->get();
i hope that will help you

Resources