Yii2 REST create with fields() - api

Let's say that I had the following API set up:
Controller:
<?php
namespace app\modules\v1\controllers;
use yii;
class ResourceController extends \yii\rest\ActiveController
{
public $modelClass = 'app\modules\v1\models\Resource';
}
Model:
use yii;
class Resource extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'ResourceTable';
}
public function fields()
{
return [
'id' => 'ResourceID',
'title' => 'ResourceTitle',
];
}
}
where my table only has the two columns, ResourceID and Title.
When I try a GET request on the API, it works fine and returns the list of resources (or single resource in the case of resource/{id}) with the aliased field names. But when I try to POST to create a resource, I want to use the aliased field names (e.g. title instead of ResourceTitle). The problem is that the default CreateAction supplied by Yii does $model->load(), which looks for the field names in the table. If I use the aliased names then it returns an error. If I use the table field names, it works fine.
So my question is, is there a way to expose resource attributes to the end user where the field names (using the fields() function) are the same for reading and creating? If possible, I'd like to avoid writing my own CreateAction.

It's necessary to add rules for new virtual properties, if you want to $model-load() save parameters to them
class OrganizationBranch extends BaseOrganization{
public function rules()
{
return array_replace_recursive(parent::rules(),
[
[['organizationId', 'cityId'], 'safe'],
]);
}
public function fields() {
return ['id',
'cityId' => 'city_id',
'organizationId' => 'organization_id',
'address',
'phoneNumbers' => 'phone_numbers',
'schedule',
'latitude',
'longitude',
];
}
public function extraFields() {
return ['branchType', 'city'];
}
public function getOrganizationId() {
return $this->organization_id;
}
public function setOrganizationId($val) {
$this->organization_id = $val;
}
public function getCityId() {
return $this->city_id;
}
public function setCityId($val) {
$this->city_id = $val;
}
}

You can create getters/setters for alias.
public function getTitle(){ return $this->ResourceTitle; }
public function setTitle($val){ $this->ResourceTitle = $val ; }

Related

notification system in Laravel 8

I am working on a laravel app where i have a user(organizer) who post an event ,and other users can comment on this event .
I am trying to make notifications system in laravel 8 between the organizer and the users when commenting on these event !
but i get this error (Call to a member function notify() on null).
This is my class :
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class NewCommentPosted extends Notification
{
use Queueable;
protected $user;
protected $event;
public function __construct($user, $event)
{
$this->user = $user;
$this->event = $event;
}
public function via($notifiable)
{
return ['database'];
}
public function toArray($notifiable)
{
return [
'user' => $this->user->name,
'eventTitle' => $this->event->title,
'eventId' => $this->event->id
];
}
This is storefunction() in my controller :
namespace App\Http\Controllers;
use App\Models\Event;
use App\Models\Comment;
use App\Notifications\NewCommentPosted;
use Illuminate\Http\Request;
class CommentController extends Controller
{
public function store(Event $event)
{
request()->validate([
'content' => 'required|min:5'
]);
$comment = new Comment();
$comment->content = request('content');
$comment->user_id = auth()->user()->id;
$event->comments()->save($comment);
$event->user->notify(new NewCommentPosted(auth()->user(), $event));
return redirect()->route('events.show', [$event->id, $event->title]);
}
Any help please !!?

Property [client] does not exist on this collection instance

I can't get the value of the foreign key that is inside the booking table.
Booking Table
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class booking extends Model
{
protected $primaryKey = 'bookingID';
protected $fillable = ['clientID', 'checkInDate', 'checkOutDate', 'roomsCount', 'roomTypeID', 'adultsCount', 'childrenCount', 'amenityID', 'paymentID'];
public function client()
{
return $this->hasOne(Client::class,'clientID');
}
}
Client Table
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class client extends Model
{
protected $primaryKey = 'clientID';
protected $fillable = ['fullNmae', 'firstName', 'lastName', 'phoneNumber', 'emailAddress'];
public function booking()
{
return $this->hasMany(Booking::class);
}
}
I tried adding the protected $primaryKey = 'bookingID'; and protected $primaryKey = 'clientID'; as suggested in my previous question but now I still can't get just the FirstName from the client table.
$bookingDetail = booking::with('client')->get();
return $bookingDetail->client->firstName;
You are trying to get a property from a collection in these lines:
$bookingDetail = booking::with('client')->get();
return $bookingDetail->client->firstName;
but this property client is defined for object, not a collection. so to solve it you must take one object from the collection like the following:
$bookingDetail = booking::with('client')->first();
return $bookingDetail->client->firstName;
i thing you need to try this one:
in your booking model:
// 'App\Client' these is example you need to put your client model path
public function client()
{
return $this->belongsTo('App\Client','clientID');
}
in your client model:
public function booking()
{
return $this->hasMany('App\Booking' , 'clientID');
}

Yii2 working with private property - non db column

I am working with Yii2 and till date using public property for non db columns like following :
public $category_id;
public function rules() {
return [
[['category_id'], 'safe'],
];
}
//// inside $dataProvider
$this->load($params);
it works perfectly. but now I want to make category_id as private so how to manage it inside rules and how to load and also set inside form element on load ?
You may use accessor and mutator for access to your private attribute, for example:
private category_id;
public function setCategory (value)
{
$this->category_id = value;
}
public function getCategory()
{
return $this->category_id;
}
These methods allow to use private attribute just as public attribute with different name in other parts of application. For example, you may use it in rules
public function rules()
{
return [['category', 'safe']];
}
Or in another code:
$model->category = 777

Two middleware for only one Function in laravel

I can use only one middleware at a time..inside a constructor..I want to use if else condition inside constructor or two middleware.
I can use only one middleware inside constructor & if else condition also not working
I want only one function work or use according to middleware.I have two seprate table for authentication
Following middleware pointing to diffrent table
$this->middleware('auth:admin') - admins
$this->middleware('auth')- user
Example are follows
If else
class HRJob extends Controller
{
public function __construct()
{
if(Auth::guard('admin'))
{
$this->middleware('auth:admin');
}
else
{
$this->middleware('auth');
}
}
public function userdetails()
{
dd(Auth::user());
}
}
Two middleware
class HRJob extends Controller
{
public function __construct()
{
$this->middleware('auth:admin');
$this->middleware('auth');
}
public function userdetails()
{
dd(Auth::user());
}
}
You can try like this in the controller
class UserController extends Controller
{
/**
* Instantiate a new UserController instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log', ['only' => [
'fooAction',
'barAction',
]]);
$this->middleware('subscribed', ['except' => [
'fooAction',
'barAction',
]]);
}
}
Also you can use Middleware groups
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
],
'api' => [
'throttle:60,1',
'auth:api',
],
];
More: https://laravel.com/docs/master/middleware

Creating Dynamic attributes,properties in model class - YII Framework

I am trying to create dynamic attributes, properties and rules in model class from one table values as columns.
Consider i have one table named "XXX" which has column "Name" now i want to create model class with rules,properties and attributes using the Name values stored in DB.
I am new to YII Framework Can anybody give idea to this ?
This is something i mocked up quickly, I hope it points ou in the right direction
$sql="SELECT 'Name' FROM XXX";
$names =$connection->createCommand($sql)->query()->readAll();
$myDynamicObject = new DynamicModel($names);
class DynamicModel extends CModel
{
protected $_members = array();
public function __construct($nameFields)
{
foreach ($nameFields as $member) {
$this->_members[$member] = null;
}
parent::__construct();
}
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
$allMembers = implode(', ', array_keys($this->_members));
return array(
array($allMembers, 'required'),
);
}
public function __get($attribute)
{
if (in_array($attribute, array_keys($this->_members))) {
return $this->_members[$attribute];
} else {
return parent::__get($attribute);
}
}
public function __set($attribute, $value)
{
if (in_array($attribute, array_keys($this->_members))) {
return $this->_members[$attribute] = $value;
} else {
return parent::__set($attribute, $value);
}
}
public function getAttributes()
{
return $this->_members;
}
public function setAttributes($attributes)
{
$this->_members = $attributes;
}
}