laravel - how to give alias name to eloquent model - laravel

<?php
namespace App\Http\Models;
use Illuminate\Database\Eloquent\Model;
use Sofa\Eloquence\Eloquence;
use Sofa\Eloquence\Mappable;
class User extends Model
{
use Eloquence, Mappable;
public $id;
public $name
}
$data= User::select('distinct User.name')->join('Member as m','User.id','m.userId')->whereRaw('User.name is not null')->get();
I want to avoid Using table name all time instead i want to use alias name.

You can use the Model::from method for this
<?php
class User extends Model
{
use Eloquence, Mappable;
public $id;
public $name
}
$data= User::from('User as u')
->select('distinct u.name')
->join('Member as m','u.id','m.userId')
->whereRaw('u.name is not null')
->get();
NOTE: I see a lot upvotes, but this approach isn't good practice. It's better to find a different approach. My advice stay on the common walked paths.

You can add
protected $table = 'users as u';
-- users is exact your table name in db
And use it like this
User::where('u.id', 1229)->select('u.email')->get();

This works for me:
$query = Model::from('table as alias')->get();
And u can check it with:
dd($query->toSql());

Related

Laravel relation one to many get results joined

I'm kinda lost one this one, I really can't find the problem, I have been watching a lot of questions all over the web but still can't seem to put this working properly.
I have two tables, the tabelaAngaricao table and the tabelaFotos table with a relationship of one-to-many, meaning that a tabelaAngariacao can have many tabelaFotos, and tabelaFotos as a angariacaoid(foreign key) so my tabelaAngariacao model is:
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\TabelaFotos;
class TabelaAngariacao extends Model
{
protected $table = 'tabelaAngariacao';
public function TabelaFotos()
{
return $this->hasMany(TabelaFotos::class, 'angariacaoid');
}
}
and my tabelaFotos model is:
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\TabelaAngariacao;
class TabelaFotos extends Model
{
protected $table = 'tabelaFotos';
public function TabelaAngariacao()
{
return $this->belongsTo('App\TabelaAngariacao');
}
}
What I want is to get all results joined by the angariacaoid, so in my controller I have:
public function index()
{
$results = DB::table('tabelaAngariacao')
->leftJoin('tabelaFotos', 'tabelaAngariacao.id', '=', 'tabelaFotos.angariacaoid')
->select('tabelaAngariacao.*')
->get();
}
Could someone help me on finding the problem? What is that I'm doing wrong?
You don't need to add select. Try following
$results = DB::table('tabelaAngariacao')
->leftJoin('tabelaFotos', 'tabelaAngariacao.id', '=', 'tabelaFotos.angariacaoid')
->get();
The above script will give you columns from both tables.
And probably you don't need to use DB::table, you can use Eloquent Queries instead, since you've defined your relationsips
You can try it by doing this.
$results = TabelaFotos::with('TabelaAngariacao')->get();
Here is how it works
$results = ModelName::with('relationship_in_model_name')->get();
Hope it works

Best way to check if user 'owns' another user

I have implemented a system in Laravel where a user can be a manager of multiple 'stores'. A store can have multiple users belonging to that store. Here's my stripped down table structure -
users
id (int)
name (string)
email (string)
user_stores
user_id (int)
store_id (int)
manager (boolean/tinyint)
stores
id (int)
name (string)
My issue is checking who a user with a manager pivot flag can manage. I have a solution but I'm not sure it's optimal. I want the query to be as lean as possible. Here is my current solution -
protected $manageable_users;
public function getManageableUserIds () {
if(!is_array($this->manageable_users)) {
// get our store id's that we manage
$manages = DB::table('user_stores')
->where('user_id', $this->id)
->where('manager', true)
->select('store_id');
// make a join so we can get our data
$this->manageable_users = DB::table('user_stores AS d2')
->joinSub($manages, 'stores', function ($join) {
$join->on('d2.store_id', '=', 'stores.dealership_id');
})->distinct()->pluck('d2.user_id')->toArray();
}
return $this->manageable_users;
}
So what I'm doing here is grabbing an array of all user ID's that the manager can possibly manage. I then store this as a protected variable so that on the same request I can perform this check multiple times within the same request without making multiple queries.
I then have a separate method called canManage which checks if the current user object can actually manage the passed user -
public function canManage(User $user) {
// check if our user is manageable
return in_array($user->id, $this->getManageableUserIds(), true);
}
Now I know Laravel is super smart and for some reason I feel like this isn't the best solution.. plus I don't want it to be too intensive on the database as ultimately there will be a lot of users and stores on this system.
If nothing else, maybe this could be a solution for someone else!
Thanks.
So basically you wanted to build a pivot relation. Here is how you could do it relative to your case:
app/User.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
public $table = 'user';
protected $primaryKey 'id';
protected $foreignKey = 'user_id';
public function stores() {
return $this->belongsToMany('App\Store', 'user_stores', 'user_id', 'store_id')->withPivot('manager');
}
}
?>
app/Store.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Store;
class Store extends Model {
public $table = 'store';
protected $primaryKey 'id';
protected $foreignKey = 'store_id';
public function users() {
return $this->belongsToMany('App\User', 'user_stores', 'store_id', 'user_id')->withPivot('manager');
}
}
?>
Now, let us say you know in advance user with id 4 is a manager, and you want to get all the users this manager can manage.
I will asume we are in a controller because most of the time this is the place where all your business logic is located, so you are browsing route /user/4/store/1, and we will display a list of all the users this user(manager) manages.
I also add the store (1) in the route to make it clear we want all users from this store, because your model does not forbid a manager to manage multiples stores. Right after the version assuming a manager only manages one store.
app/Http/Controllers/UserStoreController.php
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class UserStoreController extends Controller {
public function show(User $user, Store $store) {
// Grab all the users that are in the store and that are not manager
$managed_users = User::whereHas('stores', function($query) use($store) {
$query->where('manager', false)->where('store_id', $store->id);
})->get();
return view('user.store.index')
->withStore($store)
->withUser($user)
->withManagedUsers($managed_users);
}
}
(Note, accessing a route with an id let us use the power of Model injection, that is why I do not put public function show($user_id, $store_id), because Laravel will automatically use User::find($user_id) and Store::find($store_id) for us).
Version assuming a manager can manage only one store:
app/Http/Controllers/UserController.php
<?php
namespace App\Http\Controllers;
use App\User;
use App\Store;
use App\Http\Controllers\Controller;
class UserController extends Controller {
public function show(User $user) {
// We find the related store
$store = $user->stores->first();
// Same thing, we grab all users that are managed
$managed_users = User::whereHas('stores', function($query) use($store) {
$query->where('manager', false)->where('store_id', $store->id);
})->get();
return view('user.index')
->withUser($user)
->withManagedUsers($managed_users);
}
}
Hope it helps.
Here's a raw SQL solution:
SELECT
a.userid FROM user_stores a
INNER JOIN
user_stores b ON a.store_id = b.store_id
WHERE
a.manager=0 AND b.manager=1;
To convert this to eloquent, might try DB::select and/or DB::raw
Database table views are also worth considering. Then you'd just query your view to get your custom tailored results instead of the table directly. This kind of solution promotes clean code, allows you to continue using the ORM, doesn't require you to resort to running raw SQL in your application and gives you all the speed benefits of having this done as raw SQL. The main down side is having to write such a view and make sure it's maintained. Pretty much the same drawbacks as using triggers.
Another idea is just pull the whole database in one shot through the ORM, then use laravel collections to filter the data. In this case I'd probably reach for reduce. Could also pipeline it with filter or anything else on the list. Sure this is extra looping, but in comparison to the ORM, is it really that bad of a performance trade off?
Finally, it's also worth considering the solution of "whatever works and is most readable" and then simply cache it using, for example, redis.

How can i get result from model in laravel 5

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);
}

Laravel eloquent get all from one table and one from another

I'm fetching with $articles = Article::all(); for an index-page (using foreach with $articles as $article) all of my articles in a table. Now I want to join this results with another table called 'devices' and only want add one column named 'name' to my result in $articles.
The 'id' of the devices if equal to the 'device_id' in my articles-table.
I can make a big select with
$articles = DB::table('articles')
->join('devices', 'articles.device_id', '=', 'devices.id')
->select('devices.name','articles.id','articles.text', ...)
->get();
but I don't want to do this. Is there any better option to handle this?
Thank you in advance,
quantatheist
You can use relationship in Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model as Eloquent;
class Article extends Eloquent{
public function device(){
$this->belongsTo('App\Models\Device');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model as Eloquent;
class Device extends Eloquent{
public function articles(){
$this->hasMany('App\Models\Article');
}
}
And after when you get $articles = Article::all();
You can loop through articles
foreach($articles as $article){
echo $article->device->name
}
Also you can eager or lazy load relationship $articles = Article::with('device')->all();
And more you can take all artciles for particular device
Device::find(1)->articles()->get()

How to return database table name in Laravel

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();

Resources