If my class is Category, Am I supposed to name my SQL table "categorys" and not "categories"? - laravel

Any simpler way to not depend on Laravel's sql table naming convention?

In your Model you can override the table it's going to use. Just add a protected property:
class Category extends Model {
protected $table = 'categories123123'; //For example =D
}

categories, it works it out using Doctrine's Inflector class!

Related

Laravel retrieve records from database using mysql view instead of the table itself

I know this is a simple question and I tried hard to search a solution for this. Maybe someone knows or experienced this already that might help me.
I am only a beginner in using Laravel please bear with me.
So I have this AgencyModel, the name of my table in the database is agency.
And I have a MySQL view which is named view_agency, this contains the inner join of the agency table and other tables that has connection with it.
Model (This is the working code)
protected $table = 'agency';
The records displays when I use the agency as the table name
But MySQL view table view_agency does not display/retrive the records from the database.
Model (This code is not working)
protected $table = 'view_agency';
I have a suspicion that the laravel eloquent might have to do with this, because $table is only being accepted and not mysql view.
use Illuminate\Database\Eloquent\Model;
Thanks...
In SQL, a view is a virtual table based on the result-set of an SQL statement.
And you can get datas from view just like table's datas:
select * from view_agency
So you can use Laravel query builder or Eloquent builder to query records like table,
Laravel will convert the query builder or Eloquent to sql, so it will works:
DB::table('view_agency')->get();
I used do this before, I created a views/ directory inside the models/, and create the all views' files inside.
I think you can create that view model like this:
namespace App\Models\Views;
use Illuminate\Database\Eloquent\Model;
class ViewAgency extends Model {
}
However, I am following the laravel's way. I use the lowercase underscore plural form. So when I use ViewAgency, Laravel will find the table or view's name which is view_agencies:
ViewAgency::first();
It works fine.
And If you want to change the name, and I think there is no error with protected $table = 'view_agency;', You can try this way:
class ViewAgency extends Model {
public function __construct()
{
$this->setTable('view_agency');
}
}
This will work, too

Laravel Query builder and table names

I noticed that I write the database table names quite a lot, and in different files, when I use the Query Builder. If I were to change the database table names, I would have to search and change quite many rows in my project.
Is this an issue your Laravel guys noticed and come up with an solution to?
I like the Eloquent approach which uses class models, instead of database names; but for some queries I think the Query Builder is a better solution (though I am no expert in this matter).
If you already have a queryBuilder object you can obtain the table name like
$tableName = $query->getModel()->getTable();
Use this in your query :
(new YourModel())->getTable()
Example :
DB:raw('SELECT * FROM '.(new User())->getTable().' WHERE id=3');
How about using OOP concept. Laravel is a framework, so no one stops you from using basic PHP OOP concept. This is what I do:
Consider my query is like :
$result=DB::table('myTable')->select()->get();
What I do is make a class that holds all the tablenames :
class TableName
{
private $tableName= "myTable";
public function getTableName()
{
return $this->tableName;
}
public function setTableName($table_name)
{
$this->tableName = $table_name;
}
}
Now all i have to do is call a method using an object in the file I want to use the table like :
$name = new TableName() ;
$result=DB::table($name->getTableName())->select()->get();
Use wherever you want. I don't think its the best solution however it works for me. Hope it helps
Maybe you can extend the model class.
CModel extend Model {
protected static $tableName;
public static getTableName(){
if(static::$tableName)
return static::$tableName;
/* if you create a "reference break" you don't have to *
/* create "protected static $tableName" row in your all model */
$table = (new static())->getTable();
return static::$tableName = &$table;
}
}
YourModel extends CModel {...}
than you can use
YourModel::getTableName()
I'm not have better idea.

Laravel assumes the database table is the plural form of the model name

By default, Laravel is assuming that the database table is the plural form of the model name. But what if my table name is "news" and i still want to use this feature? should i change it to "newses" or should i use "new" for the model name?
You may specify a custom table by defining a table property on your model as below
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'my_flights';
}
Ref:https://laravel.com/docs/5.1/eloquent
If you have a model ending with the letter 's', it will keep the table name the same. In your case, your model will name your table news by default.
If you want to use another name though, you can use:
protected $table = 'tablename';
inside of your model.
EDIT: I tested this in my application. I made a model named News. Then I made a new instance of News and retrieved the table name:
$news = new News();
dd($news->getTable());
It returns: news
Inside your eloquent model you have to define table name. For example if my model is named user and table in database is named user_of_application then i do it this way
class user extends Model
{
protected $table = 'user_of_application';
}
Laravel uses a "standard set" rule that defines:
A Model is a single instance of a record
A Collection is one or more records
Therefore it assumes that a table is a collection of records.
The nomenclature has a problem when it clashes with various features / gotchas of human languages. For example, what if I have a Model called Sheep? That does mean my Database Table should be called "Sheeps"?
It's up to the developer to avoid "Gollum/Smeagol" syntax. Indeed, you wouldn't want a table called "Newses" as much I'd like to end up with a table called "Sheeps".
Ultimately, I construct Migrations with:
sudo php artisan make:migration create_sheep_table --create=sheep
As for Models, you'll notice in the documentation that they have a different table name for "Flights" called "my_flights"
https://laravel.com/docs/master/eloquent#defining-models
Again, it's up to the developer / DB manager to make decisions on naming conventions that make sense in an application context.

Disable eager relations

In my project I have many Eloquent models that have eager relations configured in class like this:
protected $with = [ 'countries', 'roles' ];
But sometimes I need just old plain model without any relations. Can I somehow do:
Model::noRelations()->all()
Really don't wanna use query builder nor create another class just for few occasions.
If you have to set the $with property on your model rather than leaving it empty, you can manually override the relationships that need to be eager loaded like this:
Model::setEagerLoads([])->get();
Link to API for setEagerLoads
In addition to Thomas Kim answer.
If you anyway extend Eloquent\Model class and often need to strip off relations from model, this solution might suit you well.
Create scope in your default model class:
public function scopeNoEagerLoads($query){
return $query->setEagerLoads([]);
}
For any ORM, that extends that class you will be able to:
User::noEagerLoads()->all()
Just like the issues say
Model::without(['countries', 'roles' ])->all();

Laravel - Extending Model

I've created a BaseModel class, which extends from Model. It seemed like everything was working fine, but now I've run into a problem when saving. I'm overriding the save() method in this BaseModel. I'd just like to add some attributes to the model before saving. So I do that, then call return parent::save($options);. The method signature is still the same: public function save(array $options = []).
It appears to be grabbing the name of the BaseModel class for the table name when performing the insert (it's using base_models as the table name), rather than the actual model that is being saved. Has anyone run into this before? What is the proper way of extending from the model class?
I originally created some traits to handle some extra functionality, but thought it would be a better idea to just create a base model and have my models extend from that instead.
In your model (the child one that extends the base model) add the table name explictly for example:
class SomeChildModel extends BaseModel {
// Manually set the table name
protected $table = 'table_name';
}
I realized that I previously had a static method that was creating an instance of itself using new self() and would set a few attributes, back when I was using the methods from a trait. It was fine before, but now since I moved the methods into the base model, that method was actually being called on the base model itself rather than the class that had the trait.
I was basically using the static method to instantiate the class, as I've read it's one way to avoid cluttering the constructor. But I just opted to do it in the constructor this time around since it made sense, so that was my solution.
Laravel will use snake case of the class name by default (the class where save method is called), if no $table instance variable is set. In your case it will use snake case of the BaseModel as a table name. You have two solutions:
Solution 1:
In classes which extends BaseModel add the $table instance variable as follow:
class User extends BaseModel {
protected $table = 'table_name'; // Your table name in the database;
}
Solution 2:
You can use Laravel Eloquent's Events, which allows you to hook into various points in the model's lifecycle.
You can hook into the save method as follow and make your changes. You can use these methods in your BaseClass, in traits, etc. For example in your BaseModel:
class BaseModel extends Model
{
/**
* Listen for save event
*/
protected static function boot()
{
parent::boot();
static::saving(function($model)
{
if ( ! $model->isValid()) {
return false;
}
});
}
}
The above will always call isValid before a model is saved into the storage. In this case it will return false and will not save the object.
For more info see the official docs here. Let me know if it isn't clear.

Resources