So I just start using Laravel and Orchid yesterday...
and now I have this problem
I want to create a data page to all posts
So I create the layout: PostListLayout
class PostListLayout extends Table
{
public $target = 'posts';
/**
* #return TD[]
*/
public function columns(): array
{
return [
TD::make('title', 'Title')
->render(function (Post $post) {
return Link::make($post->title)
->route('platform.post.edit', $post);
}),
TD::make('created_at', 'Created'),
TD::make('updated_at', 'Last edit'),
];
}
}
and after that I defined the table layer, we return to the view screen
class PostListScreen extends Screen
{
/**
* Display header name.
*
* #var string
*/
public $name = 'Blog post';
/**
* Display header description.
*
* #var string
*/
public $description = 'All blog posts';
/**
* Query data.
*
* #return array
*/
public function query(): array
{
return [
'posts' => Post::paginate()
];
}
/**
* Button commands.
*
* #return Link[]
*/
public function commandBar(): array
{
return [
Link::make('Create new')
->icon('pencil')
->route('platform.post.edit')
];
}
/**
* Views.
*
* #return Layout[]
*/
public function layout(): array
{
return [
PostListLayout::class
];
}
}
but In the end I get this error page:
Call to undefined method App\Models\Post::getContent() (View: C:\Users\KHARYA\Desktop\ORCHID\orchid-project\vendor\orchid\platform\resources\views\layouts\table.blade.php)
in app\Models\Posts.php
class Posts extends Model {use AsMultiSource ...}
Related
I am trying to test the tool I have been created. When I used relationship field in one of my resource, the page detail on this resource give me Not found.
/* My Relationship field */ (Ticket Resource)
HasMany::make(__('Replies'), 'replies',Reply::class)
/* Include */
use TicketWhmcs\TicketWhmcsPackage\Nova\Reply;
/* Ticket Model */
<?php
namespace TicketWhmcs\TicketWhmcsPackage\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use TicketWhmcs\TicketWhmcsPackage\Traits\API;
use TicketWhmcs\TicketWhmcsPackage\Models\TicketReplay;
class Ticket extends Model
{
use HasFactory, API;
protected $table = 'tickets';
protected $fillable = [
'tid',
'user_id',
'dept_id',
'subject',
'message',
'priority',
'status',
'admin',
];
public function department()
{
return $this->belongsTo(Department::class, 'dept_id', 'id');
}
/**
* Get all of the replies for the Ticket
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function replies()
{
return $this->hasMany(TicketReplay::class);
}
}
/* My resource */
namespace TicketWhmcs\TicketWhmcsPackage\Nova;
My Reply Resource
<?php
namespace TicketWhmcs\TicketWhmcsPackage\Nova;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Http\Requests\NovaRequest;
class Reply extends Resource
{
/**
* The model the resource corresponds to.
*
* #var string
*/
public static $model = \TicketWhmcs\TicketWhmcsPackage\Models\TicketReplay::class;
/**
* The single value that should be used to represent the resource when being displayed.
*
* #var string
*/
public static $title = 'id';
/* Sort */
public static $sort = [
'id' => 'desc',
];
/**
* The columns that should be searched.
*
* #var array
*/
public static $search = [
'id', 'admin',
];
/**
* Get the fields displayed by the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function fields(Request $request)
{
return [
ID::make(__('ID'), 'id')->sortable(),
Text::make(__('Message'), 'message')->hideFromIndex(),
Text::make(__('Message'), 'message')->displayUsing(function ($value) {
return Str::limit($value, 50);
})->onlyOnIndex(),
Text::make(__('Author'), 'admin')->displayUsing(function ($value) {
if ($value) {
return 'Admin';
} else {
return 'You';
}
})->hideWhenCreating(),
Text::make('Last Update', 'updated_at')
->displayUsing(function ($lastActive) {
if ($lastActive === null) {
return null;
}
return $lastActive->diffForHumans();
})->hideWhenCreating(),
];
}
/**
* Get the cards available for the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function cards(Request $request)
{
return [];
}
/**
* Get the filters available for the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function filters(Request $request)
{
return [];
}
/**
* Get the lenses available for the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function lenses(Request $request)
{
return [];
}
/**
* Get the actions available for the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function actions(Request $request)
{
return [];
}
public function authorizedToUpdate(Request $request)
{
return false;
}
public function authorizedToDelete(Request $request)
{
return false;
}
public static function indexQuery(NovaRequest $request, $query)
{
if (empty($request->get('orderBy'))) {
$query->getQuery()->orders = [];
return $query->orderBy(key(static::$sort), reset(static::$sort));
}
return $query;
}
}
I register My resource in NovaServiceProvider
public function resources()
{
Nova::resources([
Reply::class
]);
}
And it's worked!
I have Laravel mix installed on my server. there is a chat part on website and I use some kind of class :
class ActivityCell extends Component {
getTimestamp() {
const {message} = this.props;
return (
<span className="font-weight-semi-bold">
{utcDateCalendarTime(message.created_at)}
</span>
);
}
And here is my AppServiceProvider.php file :
<?php
namespace App\Providers;
use Illuminate\Http\Resources\Json\Resource;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function boot()
{
setlocale(LC_ALL, Config::get('app.lc_all'));
Carbon::setLocale(Config::get('app.locale'));
}
public function register()
{
$this->registerPlugins();
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
$this->bootDatabase();
$this->bootResource();
}
/**
* Boot database schema
*
* #return void
*/
private function bootDatabase()
{
Schema::defaultStringLength(191);
}
/**
* Boot resource
*
* #return void
*/
private function bootResource()
{
Resource::withoutWrapping();
}
/**
* Register plugins
*
* #return void
*/
private function registerPlugins()
{
$pluginDirs = File::directories(base_path('app/Plugins'));
foreach ($pluginDirs as $pluginDir) {
$class = "App\\Plugins\\" . basename($pluginDir) . "\\PluginServiceProvider";
if (class_exists($class) && is_subclass_of($class, ServiceProvider::class)) {
$this->app->register($class);
}
}
}
}
I tried to put setlocale(LC_TIME, 'tr'); on top of the class file but there is no success. Then tried to use carbon in order to make the date is viewed in different languages when I change the website language.
I added the following codes in app/config.php :
'locale' => env('APP_LOCALE', 'az'),
'lc_all' => env('APP_LC_ALL', 'az_AZ.UTF-8'),
and added following to the env file :
APP_LOCALE = az
APP_LC_ALL = az_AZ.UTF-8
in both methods, I was not successful. I am pretty sure that I am doing a mistake somewhere but can not find where exactly. Maybe I am missing to add something else to add. Any help would be highly appreciated.
EDIT : Adding Chat.php :
<?php
namespace App\Models;
use App\Events\ChatParticipationChanged;
use App\Events\ChatUpdated;
use App\Http\Resources\ChatMessage as ChatMessageResource;
use App\Http\Resources\MarketplaceTrade as MarketplaceTradeResource;
use ArrayObject;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use JSsVPSDioNXpfRC;
use DateTimeInterface;
class Chat extends Model
{
protected $lastMessageAttribute;
protected $lastMarketplaceTradeAttribute;
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = [];
/**
* The event map for the model.
*
* #var array
*/
protected $dispatchesEvents = [
'updated' => ChatUpdated::class
];
/**
* Indicates if the IDs are auto-incrementing.
*
* #var bool
*/
public $incrementing = false;
/**
* Get the route key for the model.
*
* #return string
*/
protected function serializeDate(DateTimeInterface $date)
{
return $date->translatedFormat('A B M');
}
public function getRouteKeyName()
{
return 'id';
}
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function creator()
{
return $this->belongsTo(User::class, 'creator_id', 'id');
}
/**
* Participants for this chat
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function participants()
{
return $this->hasMany(ChatParticipant::class, 'chat_id', 'id');
}
/**
* Messages for this chat
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function messages()
{
return $this->hasMany(ChatMessage::class, 'chat_id', 'id');
}
/**
* Update user's participation record
*
* #param User $user
*/
public function updateParticipation($user)
{
$this->participants()->where('user_id', $user->id)
->update(['last_read_at' => now()]);
broadcast(new ChatParticipationChanged($this, $user));
}
/**
* All marketplace trades hosted by this chat
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function marketplaceTrades()
{
return $this->hasMany(MarketplaceTrade::class, 'chat_id', 'id')
->has('buyer')->has('seller');
}
/**
* #return Model|\Illuminate\Database\Eloquent\Relations\HasMany|mixed|object|null
*/
public function getLatestMarketplaceTrade()
{
if (!isset($this->lastMarketplaceTradeAttribute)) {
$trade = $this->marketplaceTrades()->latest()->first();
$this->lastMarketplaceTradeAttribute = new MarketplaceTradeResource($trade);
}
return $this->lastMarketplaceTradeAttribute;
}
/**
* Last chat message
*
* #return ChatMessageResource|ArrayObject|mixed
*/
public function getLatestMessage()
{
if (!isset($this->lastMessageAttribute)) {
$message = $this->messages()->latest()->first();
if ($message) {
$this->lastMessageAttribute = new ChatMessageResource($message);
} else {
$this->lastMessageAttribute = new ArrayObject();
}
}
return $this->lastMessageAttribute;
}
/**
* #param User $user
* #return array
*/
public function getParticipation($user)
{
$participant = $this->participants()
->where('user_id', $user->id)->without('user')
->first();
$unreadMessagesCount = ($participant && $participant->last_read_at) ?
$this->messages()->where('user_id', '!=', $user->id)
->where('created_at', '>', $participant->last_read_at)
->count() :
$this->messages()->where('user_id', '!=', $user->id)
->count();
return [
'user_id' => $user->id,
'unread_messages_count' => $unreadMessagesCount
];
}
/**
* If user should be allowed in this chat
*
* #param User $user
* #return bool
*/
public function shouldAllowUser($user)
{
$isParticipant = $this->participants()
->where('user_id', $user->id)->exists();
return (
$isParticipant ||
$user->can('moderate_chats')
);
}
/**
* #return string
*/
public function attachmentsDir()
{
return "chats/{$this->id}/message-attachments";
}
}
The problem is on your namespace :
// Using PHP callable syntax
use Carbon\Carbon;
Or,
// Using string syntax
\Carbon\Carbon::setLocale('ru');
You also need to use translatedFormat() method on your blade for use the translate format, like :
{{ Carbon\Carbon::now()->translatedFormat('A B M') }} // утра 428 фев
You can use serializeDate() method on your model, to change timestamp column as a translated dataTime format :
use DateTimeInterface;
protected function serializeDate(DateTimeInterface $date)
{
return $date->translatedFormat('A B M');
}
i am using http://laravel-admin.org/ this extension admin panel
my controller
class Related_productController extends Controller
{
use ModelForm;
/**
* Index interface.
*
* #return Content
*/
public function index()
{
return Admin::content(function (Content $content) {
$content->header('header');
$content->description('description');
$content->body($this->grid());
});
}
/**
* Edit interface.
*
* #param $id
* #return Content
*/
public function edit($id)
{
return Admin::content(function (Content $content) use ($id) {
$content->header('header');
$content->description('description');
$content->body($this->form()->edit($id));
});
}
/**
* Create interface.
*
* #return Content
*/
public function create()
{
return Admin::content(function (Content $content) {
$content->header('header');
$content->description('description');
$content->body($this->form());
});
}
/**
* Make a grid builder.
*
* #return Grid
*/
protected function grid()
{
return Admin::grid(Related_product::class, function (Grid $grid) {
$grid->id('ID')->sortable();
$grid->column('related_id');
});
}
/**
* Make a form builder.
*
* #return Form
*/
protected function form()
{
return Admin::form(Related_product::class, function (Form $form) {
$form->display('id', 'ID');
$form->select('product_id')->options(product::all()->pluck('id', 'id'));
$form->multipleSelect('related_id')->options(product::all()->pluck('productname', 'productname'));
});
}
}
And my model
class Related_product extends Model
{
protected $table = 'related_product';
public $timestamps = false;
public function setRelated_productAttribute($related_id)
{
if (is_array($related_id))
{
$this->attributes['related_id'] = implode(',', $related_id);
}
}
when i am selecting multiselect and submitting the data it showing error like
QueryException In Connection.php line 664 :
Array to string conversion (SQL: insert into related_product (product_id, related_id) values (48, ))
I'm looking for a solution to optimize my Code using Laravel Eloquent.
My issue is that I want to add Attributes conditionally, and this Attributes is basically the a transformed many-to-many relationship.
At the moment I have this in my controller (simplified):
<?php
namespace App\Http\Controller;
/**
* Class Category
*/
class Category extends Controller
{
/**
* #return Collection
*/
public function index()
{
return Category::withCount('countries')->get();
}
/**
* #param int $id
*
* #return Category
*/
public function show($id)
{
$result = Category::where('id', $id)
->with('countries')
->firstOrFail();
$result->countries_list = '';
return $result;
}
}
My Category model looks like this (simplified):
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
/**
* Class Category
*/
class Category extends Model
{
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = [
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'countries',
];
/**
* #return string
*/
public function getCountriesCountAttribute()
{
return trans_choice('labels.countries', $this->original['countries_count']);
}
/**
* #return
*/
public function getCountriesListAttribute()
{
return $this->countries->pluck('alpha_2');
}
/**
* Get the related Countries.
*/
public function countries()
{
return $this->belongsToMany(
Country::class,
'category_country',
'category_id',
'country_id'
);
}
}
The Country Model is just a list of Countries with id, name, the Alpha2 Code, etc. I can't use the protected $appends to add countries_list because than the the list would be always included.
I also can't change my Countries model because this is used in several other occurrences.
What I'm looking for is a way to optimize the code in the controller to this:
<?php
namespace App\Http\Controller;
/**
* #return Collection
*/
public function index()
{
return Category::withCount('countries')->get();
}
/**
* #param int $id
*
* #return Category
*/
public function show($id)
{
return Category::where('id', $id)
->withAttribute('countries_list') // An array of all country aplha 2 codes
->firstOrFail();
}
You can access the countries_list attribute after querying (don't include it in your query).
public function show($id)
{
$category = Category::findOrFail($id);
$list = $category->countries_list; // this calls getCountriesListAttribute()
}
In a nutshell, I want to create a function that my query scopes can use across multiple models:
public function scopeNormaliseCurrency($query,$targetCurrency) {
return $query->normaliseCurrencyFields(
['cost_per_day','cost_per_week'],
$targetCurrency
);
}
I have got my logic working within this scope function no problem, but I want to make this code available to all my models, as there are multiple currency fields in different tables and I don't want to be replicating the code in each query scope - only specify the columns that need attention.
So, where would I make my function normaliseCurrencyFields? I have extended the Model class as well as used the newCollection keyword to extend Collection but both result in Call to undefined method Illuminate\Database\Query\Builder::normaliseCurrencyFields() errors.
I have looked into Global Scoping but this seems to be localised to a Model.
Am I along the right lines? Should I be targeting Eloquent specifically?
Create an abstract base model that extends eloquent then extend it with the classes you want to have access to it. I do this for searching functions, uuid creation, and class code functions. So that all of my saved models are required to have to certain attributes and access to my searching functions. For instance I created a static search function getobjectbyid(). So that when extended I can call it like so:
$user = User::getobjectbyid('habwiifnbrklsnbbd1938');
Thus way I know I am getting a user object back.
My base model:
<?php
/**
* Created by PhpStorm.
* User: amac
* Date: 6/5/17
* Time: 12:45 AM
*/
namespace App;
use Illuminate\Database\Eloquent\Model as Eloquent;
abstract class Model extends Eloquent
{
protected $guarded = [
'class_code',
'id'
];
public $primaryKey = 'id';
public $incrementing = false;
public function __construct($attributes = array()) {
parent::__construct($attributes); // Eloquent
$this->class_code = \App\Enums\EnumClassCode::getValueByKey(get_class($this));
$this->id = $this->class_code . uniqid();
return $this;
}
public static function getObjectById($id){
$class = get_called_class();
$results = $class::find($id);
return $results;
}
public static function getAllObjects(){
$class = get_called_class();
return $class::all();
}
my user model:
<?php
namespace App;
use Mockery\Exception;
use Illuminate\Support\Facades\Hash;
use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use App\Model as Model;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
use Authenticatable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'contact', 'username', 'email_address'
];
/**
* The column name of the "remember me" token.
*
* #var string
*/
protected $rememberTokenName = 'remember_token';
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'remember_token', 'active'
];
/**
* the attributes that should be guarded from Mass Assignment
*
* #var array
*/
protected $guarded = [
'created_at', 'updated_at', 'password_hash'
];
/**
* Define table to be used with this model. It defaults and assumes table names will have an s added to the end.
*for instance App\User table by default would be users
*/
protected $table = "user";
/**
* We have a non incrementing primary key
*
* #var bool
*/
public $incrementing = false;
/**
* relationships
*/
public function contact(){
// return $this->hasOne(Contact::class, 'id', 'contact_id');
return $this->hasOne(Contact::class);
}
public function customers(){
// return $this->hasOne(Contact::class, 'id', 'contact_id');
return $this->hasMany(Customer::class);
}
/**
* User constructor.
* #param array $attributes
*/
public function __construct($attributes = array()) {
parent::__construct($attributes); // Eloquent
// Your construct code.
$this->active = 1;
return $this;
}
/**
* #param $password string
* set user password_hash
* #return $this
*/
public function setPassword($password){
// TODO Password Validation
try{
$this->isActive();
$this->password_hash = Hash::make($password);
$this->save();
} catch(\Exception $e) {
dump($e->getMessage());
}
return $this;
}
/**
* Returns whether or not this use is active.
*
* #return bool
*/
public function isActive(){
if($this->active) {
return true;
} else {
Throw new Exception('This user is not active. Therefore you cannot change the password', 409);
}
}
public function getEmailUsername(){
$contact = Contact::getObjectById($this->contact_id);
$email = Email::getObjectById($contact->email_id);
return $email->username_prefix;
}
/**
* #return string
*
* getFullName
* returns concatenated first and last name of user.
*/
public function getFullName(){
return $this->first_name . ' ' . $this->last_name;
}
/**
* Get the name of the unique identifier for the user.
*
* #return string
*/
public function getAuthIdentifierName(){
return $this->getKeyName();
}
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier(){
return $this->{$this->getAuthIdentifierName()};
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword(){
return $this->password_hash;
}
/**
* Get the token value for the "remember me" session.
*
* #return string
*/
public function getRememberToken(){
if (! empty($this->getRememberTokenName())) {
return $this->{$this->getRememberTokenName()};
}
}
/**
* Set the token value for the "remember me" session.
*
* #param string $value
* #return void
*/
public function setRememberToken($value){
if (! empty($this->getRememberTokenName())) {
$this->{$this->getRememberTokenName()} = $value;
}
}
/**
* Get the column name for the "remember me" token.
*
* #return string
*/
public function getRememberTokenName(){
return $this->rememberTokenName;
}
/**
* Get the e-mail address where password reset links are sent.
*
* #return string
*/
public function getEmailForPasswordReset(){
}
/**
* Send the password reset notification.
*
* #param string $token
* #return void
*/
public function sendPasswordResetNotification($token){
}
public function validateAddress(){
}
}
a TestController:
public function test(){
$user = User::getObjectById('USR594079ca59746');
$customers = array();
foreach ($user->customers as $customer){
$contact = Contact::getObjectById($customer->contact_id);
$name = PersonName::getObjectById($contact->personname_id);
$c = new \stdClass();
$c->id = $customer->id;
$c->name = $name->preferred_name;
$customers[] = $c;
}
$response = response()->json($customers);
return $response;
}
Take note on how getObjectById is extended and available to my other classes that extend my base model. Also I do not have to specify in my user model an 'id' or 'class_code' and when my user model is constructed it calls the parent constructor which is the constructor on my base model that handles 'id' and 'class_code'.