Mutating model data - laravel

I want to manipulate data in my model how would I do that? I'm trying this but it doesn't work:
class Character extends Model
{
//Get players by level
public function scopeGetPlayersByLevel($query){
$output = $query->orderBy('level', 'desc')->get();
$output->classid = 100;
return $output;
}
//Get online status
public function account(){
$account = $this->belongsTo(Account::class, 'account_name', 'username');
$account->online = $account->online == 1 ? 'Online' : 'Offline';
return $account;
}
}

Define an accessor in the Account model:
public function getOnlineAttribute($value)
{
return $value === 1 ? 'Online' : 'Offline';
}

Try this:
a) Define a relationship for account model
b) Make an accessor (I called it getAccountStrAttribute, which means you call it like this: $acc->account_str).
c) Win
class Character extends Model
{
// Relationship defined
public function account() {
return $query->belongsTo(Account::class, 'account_name', 'username');
}
//Get online status
public function getAccountStrAttribute(){
return $this->account->online ? 'Online' : 'Offline';
}
// I can't figure out what you want this function to return/do :/
//Get players by level
public function scopeGetPlayersByLevel($query){
$output = $query->orderBy('level', 'desc')->get();
$output->classid = 100;
return $output;
}
}

Related

Laravel associate relationships by model instance dynamically

In my Laravel 9 project, My User Model is belongs to 3 models (Distributor, Agency and Advertiser) like:
public function distributor()
{
return $this->belongsTo(Distributor::class);
}
public function agency()
{
return $this->belongsTo(Agency::class);
}
public function advertiser()
{
return $this->belongsTo(Advertiser::class);
}
And I use this function to associate in my DistributorRepository(and other 2 model's repositories):
public function associateUser($id, $user_id)
{
$user = $this->user->find($user_id);
$distributor = $this->find($id);
$result = $user->distributor()->associate($distributor)->save();
return $result;
}
Now, I want to modify to associate them by user's id and relation model instance (Distributor, Agency and Advertiser) in my UserRepository (or UserService) dynamically, like:
public function associate($id, $modelInstance)
{
// Something happens here
}
Is that possible and how to do? Thanks!
If I understand right, then you can do it with:
public function associate($user_id, $parentModelInstance)
{
$user = User::find($user_id); //or how ever you get user in repository
$reflect = new ReflectionClass($parentModelInstance);
$relationName = Str::lower($reflect->getShortName()); //magic for getting relation (if class name is relation name)
return $user->{$relationName}()->associate($parentModelInstance)->save();
}
And you can use it like this:
$distributor = Distributor::find(1);
$user_id = 1;
$this->associate($user_id, $distributor)

Custom Eloquent relation which sometimes returns $this Model

I have a Model Text which has a 1-to-many-relation called pretext(), returning a 1-to-many-Relationshop to Text, like so:
class Text extends Model
{
public function pretext(){
return $this->belongsTo('App\Models\Text', 'pretext_id');
}
public function derivates(){
return $this->hasMany('App\Models\Text', 'pretext_id');
}
}
If a $text does not have any pretext (which, in my scenario, means $text['pretext_id'] == 0) $text->pretext() shall return the $text itself. When I try
public function pretext(){
if ( $this->belongsTo('App\Models\Text', 'pretext_id') ) {
return $this->belongsTo('App\Models\Text', 'pretext_id');
}
else {
return $this;
}
}
I get the error
local.ERROR: LogicException: Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
when the else-part is executed. So my questions are:
How do I turn $this into an object of type Relation? or alternatively:
How can I achieve my goal on a different way?
Try dynamic props
class Text extends Model
{
protected $appends = ['content'];
public function pretext(){
return $this->belongsTo('App\Models\Text', 'pretext_id');
}
public function getContentAttribute(){
$pretext = $this->pretext()->get();
if ($pretext->count()) {
return $pretext;
}
return $this;
}
}
Then in controller or view if you have the instance
(consider optimizing it if you have N+1 issues)
$obj = Text::find(1);
dd($obj->content);
I think you can create another method that calling pretext() and check the returned value.
public function getPretext() {
$value = pretext();
return ($value)? $value : $this;
}

belongsTo() function not working

I am trying to make a relation with my Character table and Account table but when I add the belongsTo() method I don't see the data of Account added to it.
So this is my Character model:
class Character extends Model
{
//Get players by level
public function scopeGetPlayersByLevel($query){
return $query->orderBy('level', 'desc')->get();
}
//Get players by zulie
public function scopeGetPlayersByZulie($query){
return $query->orderBy('zuly', 'desc')->get();
}
//Get online status
public function account(){
return $this->belongsTo(Account::class, 'username', 'account_name');
}
}
Account model:
class Account extends Model
{
//Get online players
public function scopeGetOnlinePlayers($query){
return $query->where('online', 1);
}
//Get online staff
public function scopeGetOnlineStaff($query){
return $query->where('online', 1)->where('accesslevel', 350);
}
public function characters(){
return $this->hasMany(Character::class, 'account_name', 'username');
}
}
And I add the variable in my controller like this:
use App\Character;
class RankingController extends Controller
{
function index(){
$players = Character::find(100);
return $players;
}
}
Table structure:
accounts:
- username
characters:
- account_name //foreign key
The result of $players is only the character data. Why doesn't the account data add to it?
If I understand what you are trying to do is you are trying to get a player and all their characters.
try
function index(){
$player = Account::find(1);
return $player->characters;
}
Find the account of a character
$caracter = Character::find(1);
return $caracter->account;
Try this:
//Get online status
public function account(){
return $this->belongsTo(Account::class, 'account_name', 'username');
}

Laravel : Trouble when trying to navigate till root of records

I have a table category with a field category_id which tells what's the father category.
I want to navigate from the actual category till the root.
$category = Category::where('id', '=', $id)->first();
$tc = $category;
$cc = [];
while ($tc->category_id > 0) {
$tc = Category::where('category_id', '=', $tc->category_id)->first();
$cc[] = $tc;
}
If the line have a category_id=0 (root) then it works but if it have one, then it doesn't work
Use belongsTo relationship and something like this:
// Category model
public function parent()
{
return $this->belongsTo('Category', 'category_id');
}
public function getRootCategory()
{
if ($this->hasParent()) return $this->parent->getRootCategory();
return $this;
}
protected function hasParent()
{
return ($this->category_id > 0);
}
Then all you need is:
$category = Category::find($someId);
$root = $category->getRootCategory();
// and all the ancestors of $category are accessible this way:
$category->parent;
$category->parent->parent;
Basically you don't need to use getRootCategory to load all the ancestors, you can simply use dynamic property ($category->parent) until you reach the root. It's just a convenient way to return the root cat itself.
In you model, be sure to define the parent-child relationship, something like this:
class Category
{
public function parent()
{
return $this->belongsTo('Category', 'category_id', 'id');
}
public function children()
{
return $this->hasMany('Category', 'id', 'category_id');
}
}
Then you should be able to query for all the category children something like so:
$children = Category::with('children')->find($id);

How I can get the tuples in tables N to N in laravel?

I have the following data model
A technician can have many services and a service can have many technical
Tecnico Model
class Tecnico extends Eloquent{
protected $table = 'Tecnico';
protected $fillable = array('Auth_Token');
public function servicios(){
return $this->belongsToMany('Servicio', 'Servicio_Tecnico', 'idTecnico', 'idServicio');
}
}
Servicio Model
class Servicio extends Eloquent{
protected $table = 'Servicio';
public function detalleServicio(){
return $this->hasOne('Detalle_Servicio', 'idDetalle_Servicio');
}
public function tecnicos(){
return $this->belongsToMany('Tecnico', 'Servicio_Tecnico', 'idServicio', 'idTecnico');
}
}
I'm trying to get all the services of a particular technician according to the "auth_token"
ServicioController
class ServicioController extends BaseController{
public function obtenerServicios($auth){
if($auth != ''){
$tecnico = DB::table('Tecnico')->where('Auth_Token',$auth)->first();
if($tecnico != null){
$servicio = $tecnico->servicios;
$response = Response::json($tecnico);
return $response;
}else{
$array = array('Error' => 'NotAuthorizedError', 'Code' => '403');
$response = Response::json($array);
return $response;
}
}else{
$array = array('Error' => 'InvalidArgumentError', 'Code' => '403');
$response = Response::json($array);
return $response;
}
}
}
Route
Route::get('servicio/{auth}', array('uses' => 'ServicioController#obtenerServicios'));
Error
How I can get all that technical services?
First: it's best to use the Eloquent model to query instead of DB::table.
Eg:
$tecnico = Tecnico::with('servicio')->where('Auth_Token',$auth)->firstOrFail();
The DB query builder doesn't know the Eloquent relationships. Eloquent only knows the Query builder.
And second: don't pass access tokens in the URI. Not in a segment and not in the query string. Use headers for that.
Eg:
Route::get('servicio', 'ServicioController#obtenerServicios');
class ServicioController extends BaseController {
public function obtenerServicios() {
// strip the "Bearer " part.
$token = substr(Request::header('Authorization'), 0, 7);
// ...
}
}
Use Eloquent to get Eloquent results like Model::find() etc. (DB::table... will return stdObject, that's the error you get), and correct these relations:
// class Tecnico
public function servicios(){
// the keys are wrong:
// return $this->belongsToMany('Servicio', 'Servicio_Tecnico', 'idTecnico', 'idServicio');
// it should be like this:
return $this->belongsToMany('Servicio', 'Servicio_Tecnico', 'Tecnico_idTecnico', 'Servicio_idServicio');
}
// class Servicio
public function tecnicos(){
return $this->belongsToMany('Tecnico', 'Servicio_Tecnico', 'Servicio_idServicio', 'Tecnico_idTecnico');
}

Resources