Member Since 3 Months Ago
3,760 experience to go until the next level!
In case you were wondering, you earn Laracasts experience when you:
Earned once you have completed your first Laracasts lesson.
Earned once you have earned your first 1000 experience points.
Earned when you have been with Laracasts for 1 year.
Earned when you have been with Laracasts for 2 years.
Earned when you have been with Laracasts for 3 years.
Earned when you have been with Laracasts for 4 years.
Earned when you have been with Laracasts for 5 years.
Earned when at least one Laracasts series has been fully completed.
Earned after your first post on the Laracasts forum.
Earned once 100 Laracasts lessons have been completed.
Earned once you receive your first "Best Reply" award on the Laracasts forum.
Earned if you are a paying Laracasts subscriber.
Earned if you have a lifetime subscription to Laracasts.
Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.
Earned once you have achieved 500 forum replies.
Earned once your experience points passes 100,000.
Earned once your experience points hits 10,000.
Earned once 1000 Laracasts lessons have been completed.
Earned once your "Best Reply" award count is 100 or more.
Earned once your experience points passes 1 million.
Earned once your experience points ranks in the top 50 of all Laracasts users.
Earned once your experience points ranks in the top 10 of all Laracasts users.
Awarded Best Reply on Laravel API Resources Response Doesn't Contain Links And Meta For Paginated Collections
I found the solution in stackoverflow. for transforming resource data you have to do the following:
public function toArray($request)
{
return $this->collection->map(function ($person) {
return [
'id' => $person->id,
'first_name' => $person->first_name,
'last_name' => $person->last_name,
'email' => $person->email,
'phone' => $person->phone,
'city' => $person->city,
'href' => [
'link' => route('person.show', $person->id),
],
];
});
}
it's clearly changed since last time I used API resources. because in the past you don't have to map over the collection because it's already single resource.
and when returning the collection you don't wrap it inside response helper. you just return it as it is.
Route::get('users', function (Request $request) {
$users = User::paginate(3);
$users = new \App\Http\Resources\User($users);
return $users;
});
Replied to Laravel API Resources Response Doesn't Contain Links And Meta For Paginated Collections
I found the solution in stackoverflow. for transforming resource data you have to do the following:
public function toArray($request)
{
return $this->collection->map(function ($person) {
return [
'id' => $person->id,
'first_name' => $person->first_name,
'last_name' => $person->last_name,
'email' => $person->email,
'phone' => $person->phone,
'city' => $person->city,
'href' => [
'link' => route('person.show', $person->id),
],
];
});
}
it's clearly changed since last time I used API resources. because in the past you don't have to map over the collection because it's already single resource.
and when returning the collection you don't wrap it inside response helper. you just return it as it is.
Route::get('users', function (Request $request) {
$users = User::paginate(3);
$users = new \App\Http\Resources\User($users);
return $users;
});
Replied to Laravel API Resources Response Doesn't Contain Links And Meta For Paginated Collections
but what is the issue?? the class generated by artisan command
Replied to Laravel API Resources Response Doesn't Contain Links And Meta For Paginated Collections
yes you right. the meta and links disappear when I wrap the results in this resource
Replied to Laravel API Resources Response Doesn't Contain Links And Meta For Paginated Collections
I did that. still only collection data
Started a new Conversation Laravel API Resources Response Doesn't Contain Links And Meta For Paginated Collections
I created a larave api resource like this:
php artisan make:resource UserTasksResource --collection
in my controller:
$tasks = $request->user->tasks()->with(['info.details'])->paginate(5);
$tasks = new UserTasksResource($tasks );
return response([
'tasks' => $tasks
], 200);
now I the response is like:
{
"tasks": [
{...},
{...}, ...
]
}
first of all: where are the "links" and "meta" mentioned in the docs. second of all when I edited the resource controller like so:
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'infoTitle' => $this->info->title
];
}
when I do this I get this error:
Undefined property: Illuminate\Pagination\LengthAwarePaginator::$id
I worked with API resources before and I didn't encounter such issues in the past, what I missing here?
Started a new Conversation Livewire Weird Behavior
Seniors, I have a livewire component that acting weird when I click submit button. validation errors show up but it removes a whole and it's content and replacing it with another one from the form. note: I use select2 in one of my form-rows but I put wire:ignore on it.
Replied to Using Traits With Livewire
@snapey to not forget to write custom logic in every component. so whenever I make new component I'm forced to write this function. sorry about best answer click
Replied to Help Refactoring Monstrous Code
sorry @martinbean I thought I could set more than one best answer. I kinda used a little bit of both of your answers guys.
Replied to Help Refactoring Monstrous Code
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class UserRegisterationOperation extends Controller
{
public function store(Request $request)
{
DB::transaction();
try {
$user = $this->createUserFromRequest($request);
$task = $user->tasks()->create([
'name' => $request->name,
'desc' => $request->task_desc
]);
$files = $this->getFilesData($request);
$user->uploads()->insert($files);
DB::commit();
return response([
'user' => $user,
'task' => $task,
'files' => $files
], 201);
} catch (\Exception $exception) {
DB::rollBack();
Log::error($exception->getMessage());
return response([
'error' => $exception->getMessage()
], 500);
}
}
protected function createUserFromRequest(Request $request): User
{
$user = User::firstOrCreate(['email' => $request->email], [
'name' => $request->name,
'password' => bcrypt($request->password)
]);
if (!$user) {
throw new \Exception('couldn\'t create or fetch user');
}
return $user;
}
/**
* @param Request $request
*/
protected function getFilesData(Request $request)
{
$files = collect($request->allFiles())->map(function ($file, $key) {
return [
'name' => $key,
'path' => $file->store('photos')
];
})->values()->toArray();
if (!$files) {
throw new \Exception('files not uploaded');
}
return $files;
}
}
Replied to Security Concern About Livewire Render Method
what you mean full-page component? you mean your route in web.php refer to the component directly?
Started a new Conversation Using Traits With Livewire
I'm building livewire components that shares 50% of public properties and almost 90% of submit function logic.
each component using this trait has its own rules according to its html-form fields. and also each component perform some custom logic after validating the data. other that that they are all the same.
<?php
namespace App\Traits;
trait ParentServiceComponent
{
public $desc = '';
public function rules()
{
return [
'desc' => 'required|max:2000'
];
}
public abstract function componentCustomLogic(array $data);
public function submit()
{
$data = $this->validate();
$performCusomLogic = $this->componentCustomLogic($data);
// save to db and show success message
}
}
here an example of two components that uses this trait.
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Traits\ParentServiceComponent;
class RequestService extends Component
{
public $type = '';
use ParentServiceComponent { rules as traitRules; }
public function rules()
{
return array_merge($this->traitRules, [
'type' => 'required|max:200'
]);
}
public function componentCustomLogic(array $data)
{
// do the logic of this component here
}
public function render()
{
return view('livewire.request-service');
}
}
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Traits\ParentServiceComponent;
class ReplyService extends Component
{
public $body = '';
use ParentServiceComponent { rules as traitRules; }
public function rules()
{
return array_merge($this->traitRules, [
'body' => 'required|max:200'
]);
}
public function componentCustomLogic(array $data)
{
// do the logic of this component here
}
public function render()
{
return view('livewire.reply-service');
}
}
so my question is: am I doing it right?
Replied to Help Refactoring Monstrous Code
I get it. but at the end if I use form request the form-request controller will end up almost as same as this.
what I really did is I split the controller into many protected methods as @martinbean described. and then created service controller for each related-steps and then moved logic there.
Replied to Help Refactoring Monstrous Code
this series was very useful. I found this https://laracasts.com/series/whip-monstrous-code-into-shape/episodes/2 and was more suitable to my situation. thanx.
Replied to Help Refactoring Monstrous Code
isn't form request for validation/authorization only? I'm talking about dividing multi-step/task control action into separate class for each step/task.
Started a new Conversation Help Refactoring Monstrous Code
Seniors:
I have a controller method that has some complexity and it's doing several tasks at once:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class RegisterationController extends Controller
{
public function store(Request $request)
{
// 1. check request for user unique identifier. then firstOrCreate this user then pass output to next step
// 2. take the user and create new (requests) relationship record and pass that to the next step
// 3. take the relationship record and create 2 (details records) relationships for that and pass the original record to next step
// 4. run database procedure and take result to update the relationship record
// 4. if all of above went well, upload some attachment and add record to attachment table
}
}
the current code is working fine. I wrote everything on the store method with help of private functions but I don't like it and I think it's not maintainable and not really OOP.
I'm thinking about using Laravel *** Pipeline *** class and create didecated class for each step but I'm not sure if it's the right thing.
Also I can use Repository pattern but also I don't think it's very useful here.
any tips???
Started a new Conversation Livewire Component Class As Typical Laravel Controller
can I consider Livewire component class like a typical Laravel controller and do what I want inside it. I know technically I can but I'm asking generally here. Like for example can I dispatch a job? can I write more complex login inside it.
Replied to Livewire: Submit Uploaded File To Another Server
your answer is working if I add this before pass it to to file facade
$tempFile->path();
Replied to Livewire: Submit Uploaded File To Another Server
I did this instead. what you think?
$name = File::get(storage_path("app/livewire-tmp/".$this->attach->getFilename()));
Replied to File Upload Refactoring
I didn't understand why you don't like looping, but I guess your solution is solid if we exclude looping.
I will make a dedicated function for each potential uploaded file and check inside if it's exists then upload. is that what you mean?
Replied to File Upload Refactoring
what if I did:
protected $attachs = ['upload', 'attachment', 'another'];
if($request->hasFile($attachs)) {
foreach($attachs as $attach) {
if($request->hasFile($attach)) {
//upload file
}
}
}
Replied to File Upload Refactoring
this route receives requests from multiple forms. some send "attachment" some send "upload" some send them both some send more than these two. I want the uploading to be dynamic.
Started a new Conversation File Upload Refactoring
Hey seniors:
How to refactor the following code, I mean the if-statement part
if ($photo = $request->file('attachment')) {
$photo->storeAs('photos', 'avatar' . time() . '.' . $photo->extension());
}
if ($photo2 = $request->file('upload')) {
$photo2->storeAs('photos', 'uploads' . time() . '.' . $photo2->extension());
}
Started a new Conversation Livewire: Submit Uploaded File To Another Server
Hello,
I have a livewire component that uses WithFileUploads trait. I want when the user submit the upload I resend this uploaded file to API endpoint.
<div class="container mt-5">
<div class="row justify-content-center mt-5">
<div class="col-8 mt-4">
<form wire:submit.prevent="upload">
<div class="form-group">
<label for="uploaded-file">Choose</label>
<input type="file" wire:model="attach" class="form-control">
</div>
<br />
<br />
<div class="form-group">
<button class="btn btn-primary btn-sm btn-block">Upload</button>
</div>
</form>
</div>
</div>
</div>
<?php
namespace App\Http\Livewire;
use Illuminate\Support\Facades\Http;
use Livewire\Component;
use Livewire\WithFileUploads;
class RequestService extends Component
{
use WithFileUploads;
public $attach;
private $serviceUrl = "http://multistep-form-livewire.test/api/";
public function upload()
{
$this->validate([
'attach' => 'max:2000'
]);
// here i put static tmp name but how to get it dynamically
$name = File::get(storage_path('app/livewire-tmp/XHsQgMvQEcGz17BOOad1TrTjGhLhJ0-metaU2NyZWVuc2hvdCAyMDIwLTEyLTAyIDE4Mjg1OS5qcGc=-.jpg'));
$url = $this->serviceUrl . "upload-external-file";
$response = Http::attach('attachment', $name, "testname")
->post($url, [
'name' => 'Sara',
'role' => 'Privacy Consultant',
]);
dd($response->status());
}
public function render()
{
return view('livewire.request-service');
}
}
what I want is to get the actual file from livewire temporary directory and send it to the API endpoint.
Replied to Send A Post Request From Laravel Site To Another Laravel Site
yes. but now I want to implement some protection to my site. knowing I don't have users. I just want to check if the coming request is really sent by my second site and not from somewhere else. do you suggest something?
Replied to Send A Post Request From Laravel Site To Another Laravel Site
Ok, I will go with the API option. but as you mentioned I must implement token mechanism to protect my site. do you suggest anything? or it's as simple as just sending static long-length string and check it on the other side
Started a new Conversation Send A Post Request From Laravel Site To Another Laravel Site
I want to send a POST request from one site to another knowing they both Laravel. but the csrf_token middleware won't let me.
How to turn it of for specific route and it is safe to do that?
Replied to Livewire Listen For Every Coming Response From The Component Class
I'm aware of wire:ignore. I noticed that even when I use it and I submit the form when I don't change dropdown the (name is required) error shows but I lose select2 functionality. but if I select anything then return back to empty option and click submit the error of required shows but the component does not re-render.
<div x-data="{ }" x-init="() => {
$('.select2').select2();
$('#dropdown-tecks').change(e => {
const val = e.target.value;
console.log(val);
$wire.set('name', val);
Livewire.hook('message.processed', (m, component) => {
$('.select2').select2();
})
})
}" class="row mt-5">
<form wire:submit.prevent="send">
@error('name') <span class="error">{{ $message }}</span> @enderror
<div wire:ignore class="col-12">
<p><strong>{{ $name }}</strong></p>
<br />
<select wire:model="name" id="dropdown-tecks" class="form-control select2">
<option value="">-----select-----</option>
@foreach($names as $name)
<option value="{{ $name }}">{{ $name }}</option>
@endforeach
<option value="we">We</option>
</select>
@error('name') <span class="error">{{ $message }}</span> @enderror
</div>
<div class="mt-4 col-12">
<button type="submit" class="btn btn-success">
Submit
</button>
</div>
</form>
</div>
======================================
<?php
namespace App\Http\Livewire;
use Illuminate\Validation\Rule;
use Livewire\Component;
class Dropdown extends Component
{
public $name = "";
public $names;
protected $rules = [];
protected function rules()
{
return [
'name' => [
'required',
'max:2',
Rule::in($this->tachs)
],
];
}
protected $tachs = [
'Laravel', 'Livewire', 'Inertia', 'Jetstream', 'Fortify', 'Sanctum', 'we'
];
public function mount()
{
$this->fill([
'names' => $this->tachs
]);
}
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function send()
{
$this->validate();
dd($this->name);
}
public function render()
{
return view('livewire.dropdown');
}
}
Started a new Conversation Livewire Listen For Every Coming Response From The Component Class
Hello friend
I'm building a component and I'm using Select2 in my dropdown. here is my view:
<div x-data="{ }" x-init="() => {
$('.select2').select2();
$('.select2').change(e => {
$wire.set('name', e.target.value);
Livewire.hook('message.processed', (m, component) => {
$('.select2').select2();
})
})
}" class="row mt-5">
<form wire:submit.prevent="send">
<div class="col-12">
<p><strong>{{ $name }}</strong></p>
<br />
<select wire:model="name" class="form-control select2">
<option value="">-----select-----</option>
@foreach($names as $name)
<option value="{{ $name }}">{{ $name }}</option>
@endforeach
</select>
@error('name') <span class="error">{{ $message }}</span> @enderror
</div>
<div class="mt-4 col-12">
<button type="submit" class="btn btn-success">
Submit
</button>
</div>
</form>
</div>
in my alpine code I use "message.processed" hook to reapply Select2 functionality otherwise the component re-render will mess it up. now there is a case if submit the form first thing when page loads and component class responses with validation error in this case this hook never happens and I lose Select2 functionality. what can I do in my javascript side to listen to every response from component class to reapply my select2 coz I didn't find in docs.
Awarded Best Reply on Livewire Emitting Event From Child To Parent In Nested Components
found the issue
I was setting the key inside show component call
<livewire:contact.show :contacts="$contacts" :key="$contact->id" />
and not in the foreach loop
@foreach($contacts as $contact)
<livewire:contact.single-contact :contact="$contact" />
@endforeach
so I put it in the right place and everything working like a charm now:
<livewire:contact.single-contact :contact="$contact" :key="$contact->id" />
Replied to Livewire Emitting Event From Child To Parent In Nested Components
found the issue
I was setting the key inside show component call
<livewire:contact.show :contacts="$contacts" :key="$contact->id" />
and not in the foreach loop
@foreach($contacts as $contact)
<livewire:contact.single-contact :contact="$contact" />
@endforeach
so I put it in the right place and everything working like a charm now:
<livewire:contact.single-contact :contact="$contact" :key="$contact->id" />
Replied to Single Method Instead Of Multiple Boot Methods For Each Model
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CustomModel extends Model
{
protected static function boot()
{
static::creating(function($model){
$model->fill([
'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id
]);
});
static::updating(function($model){
$model->fill([
'updated_by' => auth()->user()->id
]);
});
}
}
Then in any given model that you want to use this functionality, just do this:
use App\Models\CustomModel;
class Contact extends CustomModel
{
}
Started a new Conversation Livewire Emitting Event From Child To Parent In Nested Components
I have a parent component called Show
<?php
namespace App\Http\Livewire\Contact;
use Illuminate\Database\Eloquent\Collection;
use Livewire\Component;
class Show extends Component
{
public $contacts;
public $count = 0;
protected $listeners = [
'contactEdited' => 'contactEdited'
];
public function contactEdited($contactId)
{
session()->flash('message', 'Contact #'.$contactId.' successfully updated.');
$this->count++;
}
public function mount(Collection $contacts)
{
$this->contacts = $contacts;
}
public function render()
{
return view('livewire.contact.show');
}
}
and this is it's view
<div>
<div class="mb-5">
@if (session()->has('message'))
<div class="alert alert-success">
{{ session('message') }}
</div>
@endif
</div>
<div class="mb-5">
@if($count)
<span class="font-bolder">
{{ $count }}
</span>
@endif
</div>
<table class="table table-stripped">
<tr>
<th>Name</th>
<th>Email</th>
<th>Create date</th>
<th>Actions</th>
</tr>
@foreach($contacts as $contact)
<livewire:contact.single-contact :contact="$contact" />
@endforeach
</table>
</div>
now this is single-contact component
<?php
namespace App\Http\Livewire\Contact;
use App\Models\Contact;
use Illuminate\Validation\Rule;
use Livewire\Component;
class SingleContact extends Component
{
public $contact;
public $name;
public $email;
public $editMode = false;
public function mount(Contact $contact)
{
$this->contact = $contact;
$this->name = $contact->name;
$this->email = $contact->email;
}
public function update()
{
$this->validate([
'name' => [
'required',
'max:20'
],
'email' => [
'required',
Rule::unique('contacts')->ignore($this->contact->id)
]
]);
$this->contact->update([
'name' => $this->name,
'email' => $this->email
]);
$this->contact->fresh();
$this->editMode = false;
$this->emit('contactEdited', $this->contact->id);
}
public function render()
{
return view('livewire.contact.single-contact');
}
}
and here's the view for single-component
@if($editMode === false)
<tr>
<td>{{ $contact->name }}</td>
<td>{{ $contact->email }}</td>
<td>{{ $contact->created_at->format('Y-M') }}</td>
<td>
<button class="btn btn-sm btn-success" wire:click="$set('editMode', true)" type="button">Edit</button>
<button class="btn btn-sm btn-danger" type="button">Delete</button>
</td>
</tr>
@else
<tr :key="{{ $contact->id }}">
<td>
<input type="text" class="form-control" wire:model="name">
@error('name')<span class="text-danger font-bolder">{{ $message }}</span>@enderror
</td>
<td>
<input type="text" class="form-control" wire:model="email">
@error('email')<span class="text-danger font-bolder">{{ $message }}</span>@enderror
</td>
<td>{{ $contact->created_at->format('Y-M') }}</td>
<td>
<button id="nah-{{ $contact->id }}" class="btn btn-sm btn-danger" type="button" wire:click="$set('editMode', false)">
nah
</button>
<button id="update-{{ $contact->id }}" class="btn btn-sm btn-success" type="button" wire:click="update">update</button>
</td>
</tr>
@endif
the problem is when emitting contactEdited event from any child component the flash message shows only at the first time and the counter variable stops at 1. even if I fired the event from the console using:
livewire.emit('contactEdited', 4);
livewire.emit('contactEdited', 3);
it happens only at the first time.
Replied to HasOne Relationship With Condition
No, have you tried it?
public function substitutionEmployee()
{
//$this->start_date at this point is equal to null.
$this->hasOne(Vacation::class, 'emp_id', 'emp_id')
->where('start_date', $this->start_date);
}
Replied to HasOne Relationship With Condition
what if the (start_date , end_date ) are field in Task model. will not work if I do:
$this->hasOne(Model::lcass)->where('start_date', $this->start_date);
Started a new Conversation HasOne Relationship With Condition
Hello, I have a relationship between two models:
Task: id, start_date, end_date, emp_id
Vacation: id, start_date, end_date, emp_id, substitution_emp
//in Task model i want:
public function substitutionEmployee()
{
$this->hasOne(Vacation::class, 'emp_id', 'emp_id');
}
//but alson where start_date=start_date and end_date=end_date to get exact substitution_emp
Started a new Conversation Does Laravel Default Session Name So Imortant?
Hello,
when a user login Laravel sets a cookie name as the following:
env('APP_NAME') . "_session";
But I have seen some people make it complicated and generate like big string for session name.
Does this really matter?
Replied to Authenticate Different Frontend With Sanctum
first off, thank you so much for your reply.
Ok let's say I used default authentication for my web app and then use sanctum to authenticate my mobile app.
now what about the endpoints that both web and mobile shares. they will be using the same endpoints. how I manage that. since I want them both to consume API routes and not having endpoints for each in (web/API).
Started a new Conversation Authenticate Different Frontend With Sanctum
Hello everybody,
I want to build a Laravel website that shares almost everything with a React-Native mobile application like authentication. and I want to use Laravel sanctum for this process but then in the docs I found three type of auth that sanctum provides:
I know if I build a Vue client for web I can use (API Token Authentication) to authenticate both with the same approch. but I want a Laravel app for web so what is the best choice for me.
Replied to Livewire Weird Behavior When Toggling Public Property From Blade
It worked!
but what is the best solution of these two:
1- like this by passing just the object prop and call the method from the instance.
public $object;
public function mount($object)
{
$this->object = $object;
}
2- or pass it as you mentioned in render method
public function render()
{
return view('livewire.file-browser', [
'ancestors' => $this->object->ancestors()
]);
}
OR it doesn't matter?
Replied to Livewire Weird Behavior When Toggling Public Property From Blade
it's a function in Obj model
public function ancestors()
{
$ancestor = $this;
$ancestors = collect();
while ($ancestor->parent) {
$ancestor = $ancestor->parent;
$ancestors->push($ancestor);
}
$ancestors->push($this);
return $ancestors->sortBy('id');
}
hrer's parent relation function
public function parent()
{
return $this->belongsTo(self::class, 'parent_id', 'id');
}
Started a new Conversation Livewire Weird Behavior When Toggling Public Property From Blade
Hello there everybody, this is my first livewire application and I'm facing this weird issue with it.
basically, I have a component that I pass two args for it
public function index(Request $request)
{
$rootObj = optional(Obj::root()->forCurrentTeam()->first())->uuid;
$object = Obj::forCurrentTeam()
->where('uuid', $request->get('uuid', $rootObj))
->with(['children.objectable'])
->firstOrFail();
return view('files.index', [
'object' => $object,
'ancestors' => $object->ancestors()
]);
}
and here's my "files.index" blade file:
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<livewire:file-browser :object="$object" :ancestors="$ancestors" />
</div>
</div>
here's my file-browser component class:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class FileBrowser extends Component
{
public $object;
public $ancestors;
public $creatingNewFolder = false;
public function createFolder()
{
dd('add');
}
public function render()
{
return view('livewire.file-browser');
}
}
file-browser component blade file
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-6">
<div>
<div class="flex flex-wrap items-center justify-between mb-4">
<div class="flex-grow mr-0 mt-4 md:mt-2 w-full md:w=auto order-3 md-order-1">
<input type="search" placeholder="Search files and folders" class="w-full px-3 h-12 border-2 rounded-lg outline-none">
</div>
<div class="order-2">
<div>
<button wire:click="$set('creatingNewFolder', true)" class="bg-gray-200 px-6 h-12 rounded-lg mr-2">
New folder
</button>
<button class="bg-blue-600 text-white px-6 h-12 rounded-lg mr-2 font-bold">
Upload files
</button>
</div>
</div>
</div>
<div class="border-2 border-gray-200 rounded-lg">
<div class="py-2 px-3">
<div class="flex items-center">
@foreach($ancestors as $ancestor)
<a href="{{ route('files', ['uuid' => $ancestor->uuid]) }}" class="font-bold text-gray-400">
{{ $ancestor->objectable->name }}
</a>
@if(!$loop->last)
<svg class="mx-1 w-5 h-5 text-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
</svg>
@endif
@endforeach
</div>
</div>
<div class="overflow-auto">
<table class="w-full">
<thead class="bg-gray-100">
<tr>
<th class="text-left py-2 px-3">Name</th>
<th class="text-left py-2 px-3 w-2/12">Size</th>
<th class="text-left py-2 px-3 w-3/12">Created</th>
<th class="p-2 w-2/12"></th>
</tr>
</thead>
<tbody>
@if($creatingNewFolder)
<tr class="border-b-2 border-gray-100 hover:bg-gray-100">
<td class="py-2 px-1">
<form wire:submit.prevent="createFolder" class="w-full flex items-center ">
<input type="search" placeholder="Enter folder name" class="w-full px-3 h-10 border-2 rounded-lg outline-none mr-2">
<button type="submit" class="bg-blue-600 text-white px-3 h-9 rounded-lg mr-2 font-bold">
Make
</button>
<button type="button" wire:click="$toggle('creatingNewFolder')" class="bg-gray-200 px-3 h-9 rounded-lg mr-2">
Forget
</button>
</form>
</td>
<td></td>
<td></td>
<td></td>
</tr>
@endif
@forelse($object->children as $child)
<tr class="@if(!$loop->last) border-b-2 border-gray-100 @endif hover:bg-gray-100">
<td class="flex items-center py-2 px-3">
@if($child->isFile())
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-blue-700" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg>
<a href="#" class="p-2 font-bold text-blue-700 flex-grow">
{{ $child->objectable->name }}
</a>
@endif
@if($child->isFolder())
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-blue-700" viewBox="0 0 20 20" fill="none" stroke="currentColor">
<path d="M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" />
</svg>
<a href="{{ route('files', ['uuid' => $child->uuid]) }}" class="p-2 font-bold text-blue-700 flex-grow">
{{ $child->objectable->name }}
</a>
@endif
</td>
<td class="py-2 px-3">
@if($child->isFile())
{{ $child->objectable->size }}
@else
—
@endif
</td>
<td class="py-2 px-3">
{{ $child->created_at }}
</td>
<td class="py-2 px-3">
<div class="flex items-center justify-end">
<ul class="flex items-center">
<li class="mr-2">
<button class="text-gray-400 font-bold">Rename</button>
</li>
<li class="mr-2">
<button class="text-red-400 font-bold">Delete</button>
</li>
</ul>
</div>
</td>
</tr>
@empty
<tr class="border-b-2 border-gray-100 hover:bg-gray-100">
<td colspan="4" class="py-2 px-3">
this folder is empty
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
then in file-browser component blade file, when I try to click "New Folder" button to toggle $creatingNewFolder property I get this error in the foreach of ancestors foreach loop:
Trying to get property 'uuid' of non-object (View: C:\laragon\www\larawire\resources\views\livewire\file-browser.blade.php)
what am I missing here?
Started a new Conversation Laravel Group By Clause
I have a very hard situation and I been trying to find a solution either with query builder or eloquent but had no luck for days.
I have a database table/eloquent model "Attendance" with the following fields:
id, employee_id, timesheet_id, attendance_time 'datetime'
this table represents fingerprint log for every employee in particular branch.
timesheet_id: represents employee work shift during the day and I have two of those:
now I want to make a monthly report that grab all data in this table in particular period of time let say from 01-09-2020 to 30-09-2020 which is very easy for employees whom in work shift one, but for those who work in shift two it's kinda hard because when grouping records by date - they logout record which more likely would be in the next day - will not be grouped with that date if it makes sense.
let's take employee #3 records at 26-09-2020 for example:
(a) 2020-09-25 15:02:06 (b) 2020-09-26 00:19:21 (c) 2020-09-26 14:52:48 (d) 2020-09-27 05:29:55
see the (b) record is a logout record of day 2020-09-25 and not login record of 2020-09-26, which means if this employee had only one record in the day I must check the time if it's less than or equal to 6 am it means it's logout record for previous day otherwise it's login record for this day.
what I tried is I grab all records from 01-09-2020 00:00:00 to 01-10-2020 06:00:00 so I can catch logout for 30-09 and then I group by attendance_time but how do I check that employee has logout record in the next day when grouping by date.
$start = "2020/09/01 00:00:00";
$end = "2020/10/01 06:00:00";
$branch_id = 1;
$timesheet = 2; // employees who work from 3pm to 00 am
$attendances = Attendance::oldest()
->where([
'timesheet_id' => $timesheet
])
->whereHas('employee', function ($q) use ($branch_id) {
$q->where('branch_id', $branch_id);
})
->whereBetween('attendance_time', [$start, $end])
->where('employee_id', 3)
->get(['employee_id', 'attendance_time']);
$monthly = $attendances->groupBy(function ($item) {
return $item->attendance_time->toDateString();
});
I know it's complicated, if anyone can help I would appreciate that so much.
Replied to Improve My Laravel App Regarding N+1 Problem
yes, here's the whole business in this function
public function getDateDetails($employee, $date)
{
// here I run another sql query in {isAbsentAt} function
$employee['absent'] = !($employee->isAbsentAt($date));
if ($employee['absent']) {
return $employee;
}
// here I get all records in time ranges for this employee in specific date and determine login and logout records
// I calculate login from 00 am to 11 am for timesheet 1
// and from 6:01 am to 6 pm for timesheet 2
$start = Carbon::parse($date);
$end = Carbon::parse($date)->addHours(11);
if((int) $employee->timesheet === 2) {
$start = Carbon::parse($date)->addHours(6)->addMinutes(1);
$end = Carbon::parse($date)->addHours(18);
}
//here I use builder not collection relation to be able to use builder functions
// i think if i use it as collection like this {$employee->attendances} would solve the issue
$attendance = $employee->attendances()
->where(function($q) use ($start, $end) {
$q->where('attendance_time', '>=' , $start)
->where('attendance_time', '<=', $end);
})
->orderBy('attendance_time');
$loginRecords = $attendance->get();
if ($loginCount = $loginRecords->count()) {
$employee['in_time'] = $loginRecords->first()->attendance_time->format('H:i');
$employee['login_late'] = $loginRecords->first()->loginLate();
}
if ($employee['in_time'] === null) {
$employee['absent'] = true;
}
return $employee;
}