I have a package model named Company\Contact\Models\Contact
I have a local model named App\Models\MenuItem
Menu item is a polymorphic table with:
id
menuable_id
menuable_type
When I use it on local models like \App\Models\Page it works fine. When I call the menuable relationship in my MenuItem model, this one:
public function menuable()
{
return $this->morphTo();
}
$menuitem->menuable it gives me an instance of the page model, great, perfect. But when I do this on any package model it is null.
I tried binding my model:
$this->app->bind('Company\Contact\Models\Contact', function () {
return new Contact;
});
But that didn't work.
I then tried mapping it in the AppServiceProvider boot:
use Company\Contact\Models\Contact; // This does dump an instance of the contact model.
Relation::morphMap([
'Company\Contact\Models\Contact' => Contact::class,
]);
Anybody know how to do this?
Please let me know if I can provide any more information.
You could extend the packages model from within your own applications codebase. Create a new Contact class within your App/Models directory:.
<?php
namespace App\Models;
use Company\Contact\Models\Contact as CompanyContact;
class Contact extends CompanyContact
{
// your polymorphic relationship methods
}
Now you can use the App\ModelContact model in your application instead of the packages model.
Good day, i'm trying to get the result from my model that called with Mainmodel through my controller, my controller is MainController.
Here is my controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use app\Mainmodel;
class MainController extends Controller
{
function index(){
echo "Kok, direct akses sih?";
}
function get_menu(){
$menu = app\Mainmodel::request_menu();
dd($menu);
}
}
Here is my model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Mainmodel extends Model
{
function request_menu(){
$menu = DB::table('menu')
->orderBy('[order]', 'desc')
->get();
return $menu;
}
}
my routes
Route::get('menu','MainController#get_menu');
with my script above i get this
FatalErrorException in MainController.php line 17: Class
'App\Http\Controllers\app\Mainmodel' not found
how can i fix this ? thanks in advance.
Note: I'm bit confuse with laravel. I'm using codeigniter before. And i have a simple question. In laravel for request to database should i use model ? or can i just use my controller for my request to database.
sorry for my bad english.
I would imagine it's because your using app rather than App for the namespace.
Try changing:
app\Mainmodel
To:
App\Mainmodel
Alternatively, you can add a use statement to the top of the class and then just reference the class i.e.:
use App\Mainmodel;
Then you can just do something like:
Mainmodel::request_menu();
The way you're currently using you models is not the way Eloquent should be used. As I mentioned in my comment you should create a model for each table in your database (or at least for the majority of use cases).
To do this run:
php artisan make:model Menu
Then in the newly created Menu model add:
protected $table = 'menu';
This is because Laravel's default naming convention is singular for the class name and plural for the table name. Since your table name is menu and not menus you just need to tell Laravel to use a different table name.
Then your controller would look something like:
<?php
namespace App\Http\Controllers;
use App\Menu;
class MainController extends Controller
{
public function index()
{
echo "Kok, direct akses sih?";
}
public function get_menu()
{
$menu = Menu::orderBy('order', 'desc')->get();
dd($menu);
}
}
Hope this helps!
You can solve it by different solution. The solution is you don't have to call request_menu(); you can get it in your controller.
MainController
use use Illuminate\Support\Facades\DB;
public function get_menu(){
$menu = DB::table('menu')
->orderBy('Your_Field_Name', 'DESC')
->get();
dd($menu);
}
I can't seem to figure out what's wrong with this code. I'm running laravel 5.4.
The error:
https://www.dropbox.com/s/64ioxdf4mv6ps1w/Screenshot%202017-02-28%2020.11.33.png?dl=0
The Controller function:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Thread;
class ThreadController extends Controller
{
public function show($id) {
return Thread::where('id', '=', $id)->messages();
}
}
The Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Thread extends Model
{
public function messages()
{
return $this->hasMany(Message::class)->get();
}
}
I suggest adding your error code instead of linking to image (right now AWS is down, thus I'm unable to view the image).
Regardless, the messages method is defining a relationship and as such, is an instance of the query builder. Rather than chaining the get method there, I suggest a slightly different approach:
In your controller
public function show($id)
{
// Use first() instead of get() since you're returning a
// specific model by its primary key (I assume)
return Thread::where('id', $id)->with('messages')->first();
}
And in your model
public function messages()
{
// This returns a query builder instance, which is what you want.
// It defines the relationship between Thread and Message
return $this->hasMany(Message::class);
}
This will eager load your messages along with your Thread model.
Hope it helps!
Regarding Joel's question in the comments...
User::find(1)->messages->create($request->only('body'));
Is not calling the 'messages function' you mentioned and not returning the relationship. Instead, it is calling the messages property, which is something different.
I have created a laravel api for my application.I have used Pingpong module package for different modules.I am having hard time establishing many-to-many relation.I have 3 tables:roles,groups,group_roles.And my models are:
Group.php
namespace Modules\User\Entities;
use Illuminate\Database\Eloquent\Model;
class Group extends Model {
protected $fillable = [];
protected $table='groups';
public static function roles(){
return $this->belongsToMany('Modules\User\Entities\Role','group_roles','group_id','role_id');
}
}
Role.php
namespace Modules\User\Entities;
use Illuminate\Database\Eloquent\Model;
class Role extends Model {
protected $fillable = [];
protected $table='roles';
public function groups(){
return $this->belongsToMany('Modules\User\Entities\Group','group_roles','group_id','role_id');
}
}
And my controller
namespace Modules\User\Http\Controllers;
use Pingpong\Modules\Routing\Controller;
use Modules\User\Entities\Group;
use Modules\User\Entities\Role;
use Illuminate\Http\Request;
use App\Login;
use Input;
use Validator;
use Hash;
use Response;
class UserController extends Controller {
public function getGroupById(Request $request){
$groups=Group::with('roles')->get();
return Response::json ([
'status'=>'ok',
'group'=>$groups
],200);
}
}
The problem is I am not able to establish the relation between the models and the getGroupById returns 500 internal error response.$group=Group::all(); $group=Group::find($request['id']); returns fine but it is not returning related roles.
Similar structure and codes work fine on app without the use pingpong.
Your relationships are currently like this:
// not sure why this is static?
public static function roles(){
return $this->belongsToMany('Modules\User\Entities\Role', 'group_roles', 'group_id', 'role_id');
}
public function groups(){
return $this->belongsToMany('Modules\User\Entities\Group', 'group_roles', 'group_id', 'role_id');
}
Please note from the docs, regarding the belongsToMany method:
The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to...
So with this in mind I think your relationships may be incorrect due to using the wrong arguments on your belongsToMany method calls. I think it should be like this:
public function roles(){
return $this->belongsToMany('Modules\User\Entities\Role', 'group_roles', 'group_id', 'role_id');
}
public function groups(){
return $this->belongsToMany('Modules\User\Entities\Group', 'group_roles', 'role_id', 'group_id');
}
Also if you have intermediate table columns you'd need to declare those on the belongsToMany call.
Hope that helps!
Edit
Firstly, you said getGroupById returns 500 internal error response. Have you tried checking what the actual error is!? 500 internal error doesn't provide much info, I'm sure you'd get to the bottom of things a lot faster if you found out the exact issue through laravel's usual error response page.
I assume you're doing this through an ajax request so you could use the network tab if you're using chrome then click on the 500 request to see the error laravel returns or you can use something like postman and hit the url through that.
If I wanted to quickly check the functionality of the models relationship methods, I'd do the following:
After setting up some data for a group and relationship, could you try running this in tinker or a route for testing/debugging.
$g = Group::first(); // get the first group, or you could use find($id) if you had a specific group in mind
// if you're in tinker
$g->roles; // show the roles
// if you're running on a route
dd($g->roles); // show the roles
While haakym's answer is very detailed, but you can also try changing your mapping table name to convention based 'group_role' instead of 'group_roles'. With this method you will have to supply only one argument to belongsToMany call.
Note that in general it should not matter if the other arguments are correct, but its just another step to debug!
Is there a way that I can get the current database table in use by the model that I'm in? I see that there is a table() function in Laravel/Database/Eloquent/model.php but I've been unsuccessful calling it calling it from the model that I'm in.
There is a public getTable() method defined in Eloquent\Model so you should be able to use $model->getTable().
Taylor has an answer to your question:
Within the model class you can do something like this:
return with(new static)->getTable();
If you want all your models to have the ability to return table name statically, then so something like this:
class BaseModel extends Eloquent {
public static function getTableName()
{
return with(new static)->getTable();
}
}
class User extends BaseModel {
}
User::getTableName();
Edit April 2019: This answer is now out of date. See the new correct answer by Flyn San
Yes - Eloquent has a $table variable. There are two ways you can access this:
class yourModel extends Eloquent {
public static $table = "differentTable";
function someFunction()
{
return yourModel::$table;
}
}
or
class yourModel extends Eloquent {
public function someFunction()
{
return $this->table();
}
}
then in your code
Route::get('/', function () {
$model = new yourModel();
dd($model->someFunction());
});
In my case, i'm using laravel 5.4
return (new static)->getTable();
Since table is a protected property in the Model class (Laravel >= 5) you will need an instance of your Model.
Here is a case example:
DB::table( (new YourModelClassname)->getTable() )
->update(['field' => false]);
You can get name of a model's table by following code:
If we have a Model as ModelName:
ModelName::query()->getQuery()->from
This method also works fine in case of custom table name that are defined by protected $table = 'custom_table_name' in the Model.
It will return the table name from the model. perfectly worked on laravel 8
app(Modelname::class)->getTable()
you have to replace Modelname with your model class
Based on Lucky Soni answer, there is another easy trick if you want to directly call it from Vontroller or View.
Tested in Laravel 6, and I keep using it, if you are "One Line Programmer" who hates extra line instance declaration. No need for extra lines in Model file too.
$string_table_name = with(new \App\Model\TableModelName)->getTable();
or better you may also be able to just call this
$string_table_name = (new \App\Model\TableModelName)->getTable();
It will return plain string of the tabel name even if you rename $table variable inside model class.
EDIT :
Minus Rep ?? Maybe you should try this first in your controller instead making new function in model class just to get table name and no need to declare the object when calling.
with() itself is Laravel helper function that returns an object of the class. and inside class that extends Model, already has function getTable(). So, you don't have to put another new redundant function inside model class.
It seems the latest version, you can just call (new Class) without with() function.
The difference between this answer and Lucky's answer, mine doesn't make any new function inside Model class to get the table name, even you can just call the function inside the Controller and View without declaring the object of model class. It's for beautify the code.
While Lucky's answer create new function that inside Model class, and you need to call the function from the object.
Simple way to get table name from Laravel Model by this:
$tableName = app(\App\User::class)->getTable();
Don't forget to replace:
\App\User
With Model path.
Here's an other approach so that you can get a model's table name statically.
Define a Trait: app/Traits/CanGetTableNameStatically.php
<?php namespace App\Traits;
trait CanGetTableNameStatically
{
public static function tableName()
{
return (new static)->getTable();
}
}
Extend your required Model or BaseModel with the use statement.
app/Models/BaseModel.php
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Traits\CanGetTableNameStatically;
class BaseModel extends Model
{
use CanGetTableNameStatically;
// ...
}
On your models, if you set the custom table name on Laravel's reserved attribute: protected $table then it will still work & return correct table name.
app/Models/Customer.php
<?php namespace App\Models\Master;
use App\Models\BaseModel;
class Customer extends BaseModel
{
protected $table = 'my_customers';
// ...
}
Usage: just call YourModel::tableName() anywhere.
In Views:
{{ \App\Models\Customer::tableName() }}
When doing Joins:
DB::table( Product::tableName() . ' AS p' )
->leftJoin( ProductCategory::tableName() . ' AS pc', 'pc.id', '=', 'p.category_id')
// ... etc
Note:
I use this approach where needed but full disclosure, I found another answer here that have the exact same approach, so I copy pasted here for reference of course with citation thanks to #topher
Based on tailor Otwell's answer you could use something like this:
with(new Model)->getTable();
Note: tested on versions 5.x, 6.x, 7.x, 8.x and it works well.
another solution is to use the resolve helper like so:
resolve('\\App\\Models\\User')->getTable()
None of the answers so far will get you the table name with the prefix, if you are using a table name prefix. At this time it seems like we need to concatenate the prefix with the table name ourselves if we want the real name of database table.
Here's how to get the table name including the table prefix:
echo \App\MyModel::query()->getQuery()->getGrammar()->getTablePrefix() . app(\App\MyModel::class)->getTable();
in laravel 7.x (i'm used)
you can get table name with (new Target())->getTable();
$query->where('parent_id', function ($query) use ($request) {
$query->select('id')->from((new Target())->getTable())->where('unit_id', $request->unit_id);
});
hope it's helps
To people who want to get table name from a Builder object instead of other object, here you are:
$conn = DB::connection("my_private_mysql_conn");
$my_builder_object = $conn->table("my_table_name");
//This will print out the table name
print $my_builder_object->from;
It will work 100%. You will get table name.
$object = new OrderStockProduct();
// Use below line only when you have dynamic connection in laravel project
// $object->setConnection('mysql');
$object = $object->getTable();
dd($object);
I just wanted to add the following for people coming from search engines:
In case you do not even want to instantiate the Model at all (faster?) :
$model = 'App\User';
$modelTable = str_replace('\\', '', Str::snake(Str::plural(class_basename($model))));
dd($modelTable); // will return "users"
That might look ugly but that's exactly how the getTable() method resolves it under the hood, so...
You will need to use Illuminate\Support\Str; on top of your file.
Addendum: implying you follow the framework's standards (i.e: Post model has posts table, User model has users table, etc)
In Laravel 4 use static method
$table_name = Model::getTable();
or "self" inside Eloquent Model
$table_name = self::getTable();