I have a package media library by spatie. I need to get table name of the model.
I know that I can do this:
public function getPath(Media $media) {
$name = (new $media->model())->getTable()
}
But this creates a new query. I don't need to create an extra query on database. In table media, I have a column a model_type, where records can be like this: App\ModelName. Maybe I can get names of the model without a query?
There is an answer in laravel framework github:
https://github.com/laravel/framework/issues/1436 .
So it seems you will need to extend Media model.
Example from github
class BaseModel extends Eloquent {
public static function getTableName()
{
return with(new static)->getTable();
}
}
class User extends BaseModel {
}
User::getTableName();
I don't think "new model()" created a query on the database, it just spawns a new object instance of the model class. I don't know the library by heart, but given that it's a Spatie library, it probably functions very similar like Eloquent does, which has the same behaviour.
Related
I'm currently trying to use Laravel Relationships to access my achievements Model using User model, I use this relationship code:
public function achievements()
{
return $this->hasMany('App\Models\User\Achievement');
}
I can easily make some eloquent queries, however I can't access any method that I created there, I can't access this method:
class Achievement extends Model
{
public function achievementsAvailableToClaim(): int
{
// Not an eloquent query
}
}
Using the following code:
Auth::user()->achievements()->achievementsAvailableToClaim();
I believe that I am using this Laravel function in the wrong way, because of that I tried something else without using relationship:
public function achievements()
{
return new \App\Models\User\Achievement;
}
But that would have a performance problem, because would I be creating a new class instance every time I use the achievements function inside user model?
What would be the right way of what I'm trying to do?
it's not working because your eloquent relationship is a hasMany so it return a collection. you can not call the related model function from a collection.
you can var dump it on tinker to understand more what i mean.
You can use laravel scopes.Like local scopes allow you to define common sets of constraints that you may easily re-use throughout your application.
In your case you use this like, Define scope in model:
public function scopeAchievementsAvailableToClaim()
{
return $query->where('achivement_avilable', true);
}
And you can use this like :
Auth::user()->achievements()->achievementsAvailableToClaim();
I'm sure this is a totally simple question but for the life of me I'm stuck here- we're using Eloquent outside of Laravel due to PHP restrictions. I have a support ticket tracking app that I'm trying to update.
The data structure of this app is such that each ticket is assigned a UUID on submission and a table with that UUID as its name is generated and all changes to the ticket are tracked as new entries in that table.
Following some tutorials on Eloquent I got our models and controllers set up and working but for each one I see that I'm defining the table name in the model itself. IE our ticket model is
namespace Models;
use \Illuminate\Database\Eloquent\Model;
class Ticket extends Model {
protected $table = 'tickets';
protected $fillable = [table columns here];
}
and anything called in the tickets controller correctly and successfully reads and writes data to our tickets table.
So... my question is: how would I go about reading/writing/creating/deleting those previously mentioned UUID tables?
I've tried the built in table selector (ie- DB::table(uuid here) and DB::setTable(uuid here) but to no avail. I get Fatal error: Call to undefined method Models\Database::setTable()
What I'm after is a model/controller that I can reuse for ANY dynamically-named table.
You could create a generic model and dynamically set the table name, like this:
namespace Models;
use \Illuminate\Database\Eloquent\Model;
class FormerUUIDTicket extends Model {
protected $table = 'some_table';
protected $fillable = [table columns here];
}
class SomeController
{
public function someAction()
{
$uuid = $_POST['uuid_field']; //some uuid, the table name
$model = new FormerUUIDTicket;
$model->setTable($uuid);
return $model->get(); //do anything using eloquent with proper table
}
}
Make sure that you always set the table name before use, or it will fail. Don't use static function either, for the same reason.
I want to execute my custom code after or before every $model->save() in Yii2.
I want to perform this globally like using components, etc.
I want to create a user activity log to store how many times a user insert or update any rows in database table, so for this I want to run some code when ever data inserted or update in tables.
Any help or suggestion will appreciated.
As #patryk mentioned ActiveRecord has beforeSave and afterSave methods.
I use something like the following to store a created date for new records (and updated date when existing records are updated). The code in the example is, of course, trivial but it allows you to use any arbitrary code you need, see the layout and how to split code for 'new' records and existing.
This overridden method can be added to any model class which extends ActiveRecord to allow the parent beforeSave to be called correctly also.
/**
* #inheritdoc
*/
public function beforeSave($insert)
{
if ($insert) {
// This is a new instance of modelClass, run your 'insert' code here.
$this->created_date = time();
}
// Anything else will be run any time a model is saved.
$this->updated_date = time();
return parent::beforeSave($insert);
}
edited to add:
if the code to be run is the same for each model you could create a trait and use the trait in each model to allow you to change the behaviour in one place. Or create a custom ActiveRecord class to override the beforeSave method for each subclass.
Create new class(MyActiveRecord) which extends \yii\db\ActiveRecord
Use extends MyActiveRecord to all your project models
Ex:
class MyActiveRecord extends \yii\db\ActiveRecord
{
public function afterSave($insert, $changedAttributes){
//This will called after every model saved
return parent::beforeSave($insert,$changedAttributes);
}
}
In your project other models
class Customer extends app\models\MyActiveRecord
{
}
Yii2 ActiveRecord class has beforeSave and afterSave methods. https://github.com/yiisoft/yii2/blob/master/framework/db/BaseActiveRecord.php#L926
But maybe it would be better to do such operation on database triggers?
In my Laravel 5.1 App I have a lot of aux Models with the same structure. I was thinking in the posibility of make one model and controller for using all of them, but I cannot figure how to do.
I explain, all the database aux tables have the fields ID and name, and are made for CRUD operations and for filling the forms all over the App.
Is possible to specify the table on the methods implemented by Laravel? I mean, stablish the table on construct, on get(), etc. This would made the work a much more simple if I could do AuxTable::create("sex") or even in requests like $request->auxtable("studies")->get().
Am I explaining?
you can do it with single model like below in Model class there is a method called setTable($table) which can set the table name you want to use so consider below
use Illuminate\Database\Eloquent\Model;
class AuxTable implements Model {
//other class properties
}
in your controller use the model like below
class SampleController extends BaseController {
public function index() {
$model = new AuxTable;
$model->setTable('sex');
$model->get();
}
}
this should do the trick
In my Laravel application I have an Faq model. An Faq model can contain many Product models, so the Faq class contains the following function:
class Faq extends Eloquent{
public function products(){
return $this->belongsToMany('Product');
}
}
In a controller, I would like to be able to retrieve the class name that defines the relationship. For example, if I have an Faq object, like this:
$faq = new Faq();
How can I determine the class name of the relationship, which in this case would be Product. Currently I am able to do it like this:
$className = get_class($faq->products()->get()->first());
However, I'm wondering if there is a way to accomplish this same thing without having to actually run a query.
Yes, there is a way to get related model without query:
$className = get_class($faq->products()->getRelated());
It will work for all relations.
This will return full name with namespace. In case you want just base name use:
// laravel helper:
$baseClass = class_basename($className);
// generic solution
$reflection = new ReflectionClass($className);
$reflection->getShortName();