Laravel9: How to let model's find() work? - laravel

I have service layer. My codes works in Laravel 5.6. Now I'm rewriting in Laravel 9, it doesn't work anymore.
UserController
public function getForm($id = null)
{
...
$user = $this->userService->findIdOrNew($id);
UserService
class UserService
{
public function __construct(Request $request)
{
parent::__construct();
$this->request = $request;
$this->modelName = "\App\Models\User";
$this->model = new $this->modelName;
$this->table = $this->model->getTable();
}
private function newModel()
{
return new $this->modelName;
}
public function findIdOrNew($id = null)
{
if(empty($id)){
$row = new $this->modelName;
}else{
$row = $this->model->find($id);
echo "<pre>", print_r($row, 1), "</pre>";exit;
}
return false;
}
Logic:
If no user id, then new an emtpy user model, return it.
If user id provided, then get the user model, and find the user id.
$this->model only do the new action in __controller.
I have many other functions like this.
public function updateById($data, $id)
{
$row = $this->model->find($id);
$row->email = $data['email'];
$row->name = $data['name'];
...
public function getRows($data = array(), $debug = 0)
{
$query = $this->model->query();
if(!empty($data['filter_ids'])){
$query->whereIn('id', $data['filter_ids']);
}
if(!empty($data['filter_name'])){
$words = explode(' ', trim(preg_replace('/\s+/', ' ', $data['filter_name'])));
$query->where(function ($query) use($words) {
$query->orWhere(function ($query2) use($words) {
foreach ($words as $word) {
$query2->where('name', 'like', "%{$word}%");
}
});
});
}
In this way, I don't use User::find(1), I don't need to say which model I want in functions. Just write it once in __contructor().
It really works in my laravel 5.6. Now it returns empty. No error message.
public function findIdOrNew($id = null)
{
ini_set("display_errors", "On");
error_reporting(E_ALL ^E_NOTICE ^E_DEPRECATED);
$row = $this->model->find($id);
echo "<pre>", print_r($row, 1), "</pre>";exit;
I should get:
App\Models\User Object
(
[fillable:protected] => Array
(
[0] => name
[1] => email
[2] => password
)
[hidden:protected] => Array
(
[0] => password
[1] => remember_token
)
[connection:protected] => mysql
[table:protected] =>
[primaryKey:protected] => id
[keyType:protected] => int
[incrementing] => 1
[with:protected] => Array
(
)
[withCount:protected] => Array
(
)
[perPage:protected] => 15
[exists] => 1
[wasRecentlyCreated] =>
[attributes:protected] => Array
(
[id] => 50
[rcode] => 1971836358
[name] => ooxxooxx
...
Now just a white page. What did I missed ?
I deleted all logs, restart apache server, then reload the page.
Apache/logs/laraocadmin9.test-access.log
127.0.0.1 - - [16/Jun/2022:14:39:46 +0800] "GET /en/admin/system/user/users/49/edit HTTP/1.1" 200 11
127.0.0.1 - - [16/Jun/2022:14:39:48 +0800] "GET /favicon.ico HTTP/1.1" 200 -
Apache/logs/laraocadmin9.test-error.log
(empty)
Apache/logs/access.log
(empty)
Apache/logs/error.log
[Thu Jun 16 14:38:09.392250 2022] [mpm_winnt:notice] [pid 40028:tid 388] AH00455: Apache/2.4.53 (Win64) mod_fcgid/2.3.10-dev configured -- resuming normal operations
[Thu Jun 16 14:38:09.393249 2022] [mpm_winnt:notice] [pid 40028:tid 388] AH00456: Apache Lounge VS16 Server built: Mar 16 2022 11:26:15
[Thu Jun 16 14:38:09.406444 2022] [mpm_winnt:notice] [pid 40028:tid 388] AH00418: Parent: Created child process 20972
[Thu Jun 16 14:38:10.096179 2022] [mpm_winnt:notice] [pid 20972:tid 432] AH00354: Child: Starting 64 worker threads.
Laravel storage\logs
only a file name .gitnore

Sorry, it still works. The user id I passed was wrong. I had two different projects. one is
$this->getForm('edit', $id)
$this->getForm('create', $id)
function getForm($action, $id=null)
another is
$this->getForm($id)
$this->getForm($id)
function getForm($id=null)
I got mixed up, I passed 'edit' to getForm($id)

Related

The Laravel way of separating items in a collection based on user_id

In the Event-model I have this relationship:
public function eventQuestionUsers(){
return $this->hasMany( 'App\EventQuestionUsers' );
}
So when I get an $event in my Controller, I do this:
public function show( $event_id ){
$user = Auth::user();
$event = Event::where( [ 'id', '=', $event_id ] )->get();
if( $user->can( 'manage', $event ) ){
$event->load( 'eventQuestionUsers' );
}
return view( single_event, [
'event' => $event
]);
}
But now I'm I would like the collection to split-up the eventQuestionUsers based on the user_id. So that it would look like this:
$event = [
'name' => 'Blah blah',
'date' => '2021-09-18 20:30:00'
'eventQuestionUsers' => [
15 => [ // 15 is a user_id
$eventQuestionUser,
$eventQuestionUser,
],
16 => [ // 16 is a user_id
$eventQuestionUser,
$eventQuestionUser,
$eventQuestionUser,
$eventQuestionUser,
],
18 => [ // 18 is a user_id
$eventQuestionUser,
$eventQuestionUser,
],
]
Solution attempt
Normally I would just make a public static helper-function, that takes $eventQuestionUsers and an input and returns what I want, by iterating over the whole this, like such:
public static function clusterEventQuestionUsersBasedOnUserId( $eventQuestionUsers ){
$returned = [];
foreach( $eventQuestionUsers as $eventQuestionUser ){
$user_id = $eventQuestionUser->user_id;
if( ! array_key_exists( $user_id, $returned ) ){
$returned[ $user_id ] = [];
}
$returned[ $user_id ][] = $eventQuestionUser;
}
return $returned;
}
I wouldn't use a Collection, since that is immutable, so adding entries like seen above usually is a bit of a pain.
What is 'The Laravel Way' of doing this? Or does it sound fine? It feels very 'un-laravel' like.
By default, $event->eventQuestionUsers is a collection instance and this means you can use laravel collection methods directly on it and in this case, groupBy(). So
public function show( $event_id ){
$user = Auth::user();
$event = Event::where( [ 'id', '=', $event_id ] )->get();
if( $user->can( 'manage', $event ) ){
$event->load( 'eventQuestionUsers' );
$event->eventQuestionUsers->groupBy('user_id');//the only new stuff
}
return view( single_event, [
'event' => $event
]);
}
Im unsure if i understood you correctly, but if you have the user_id in your relation, you can group by your lazy eager load like so
$event->load(['eventQuestionUsers' => function($query) {
$query->groupBy('user_id');
}]);
Laravel Docs

Eloquent trying to get date with time

I'm trying to get all the reservations in a specific date and time and count the guests to find the available seats
What i'm doing in the controller:
public function getSeats() {
$data = request()->validate([
'date' => 'required',
'hours' => 'required',
'place_id' => 'required'
]);
$hours = [];
foreach($data['hours'] as $h) {
$date = $data['date'].' '.$h;
//Carbon date: 2021-08-31 08:00:00 | Database Date: 2021-08-31 08:00:00
$count = Reservation::where('place_id', $data['place_id'])->whereDate('date', Carbon::create($date)->toDateTimeString())->sum('guests');
$object = (object) [
'hour' => $h,
'guests' => $count
];
array_push($hours, $object);
}
}
It returns null, what am i doing wrong?
**Edit
I'm also using 24H in the time selector, so when i create a reservation at 12:00 in the morning eloquent grabs it as 00:00 in the night.
Using where instead of whereDate fixed the issue

Fetch relationship with respective to relationship data in Laravel 5.7

Let me give you a basic overview:
There is an app where people will register their pets and would report when a pet is lost. Also, people who have seen a lost pet would report a sighting for the pet so that the owner of the pet would be notified and he could retrieve his pet.
I have five models:-
Color Model
class Color extends Model
{
public function colorPet()
{
return $this->hasMany('App\Models\Pet');
}
}
Breed Model
class Breed extends Model
{
public function breedPetType()
{
return $this->belongsTo('App\Models\PetType', 'pet_type_id');
}
public function breedPet()
{
return $this->hasMany('App\Models\Pet');
}
}
Pet Type Model
class PetType extends Model
{
public function petTypeBreed()
{
return $this->hasMany('App\Models\Breed');
}
}
Pet Model
class Pet extends Model
{
public function petBreed()
{
return $this->belongsTo('App\Models\Breed', 'breed_id');
}
public function petPetType()
{
return $this->belongsTo('App\Models\PetType', 'pet_type_id');
}
public function petColor()
{
return $this->belongsTo('App\Models\Color', 'color_id');
}
public function petUser()
{
return $this->belongsTo('App\User', 'user_id');
}
}
Lost Report
class LostReport extends Model
{
public function lostReportPet()
{
return $this->belongsTo('App\Models\Pet', 'pet_id');
}
public function lostReportUser()
{
return $this->belongsTo('App\User', 'user_id');
}
public function lostReportPetSighting()
{
return $this->hasMany('App\Models\PetSighting', 'lost_report_id');
}
}
Pet Sighting
class PetSighting extends Model
{
public function petSightingLostReport()
{
return $this->belongsTo('App\Models\LostReport', 'lost_report_id');
}
}
Here is ny query:-
$petSightingRadiusQueryString = "( $unitDistance * acos( cos( radians($latitude) ) * cos( radians( pet_sightings.latitude ) )
* cos( radians( pet_sightings.longitude ) - radians($longitude) ) + sin( radians($latitude) ) * sin(radians(pet_sightings.latitude)) ) )";
$lostPetQuery = LostReport::with('lostReportPet')
->where(array(
'lost_reports.is_found' => Globals::SMALL_CHAR_NO))
->whereHas('lostReportPet', function($queryReportPet) {
$queryReportPet->where(array(
'pets.status' => Globals::SMALL_CHAR_ACTIVE,
'pets.is_delete' => Globals::SMALL_CHAR_NO,
'pets.is_lost' => Globals::SMALL_CHAR_YES
));
});
$lostPetQuery = $lostPetQuery->where(function($orQuery) use($userId, $petTypeArrayForLostPet, $lostPetRadiusQueryString, $lostPetRadius, $petSightingRadiusQueryString, $petSightingRadius){
$orQuery->where('lost_reports.user_id', $userId) // where the post report is by owner
->orWhere(function($lostPetNotificationQuery) use($petTypeArrayForLostPet, $lostPetRadiusQueryString, $lostPetRadius){
$lostPetNotificationQuery->whereIn('pets.pet_type_id', $petTypeArrayForLostPet)
->whereRaw($lostPetRadiusQueryString . ' < ' . $lostPetRadius);
}) // where the lost report is of same pet type
->orWhereHas('lostReportPetSighting', function($petSightingNotificationQuery) use ($petSightingRadiusQueryString, $petSightingRadius){
$petSightingNotificationQuery->whereRaw("pet_sightings.id = (SELECT MAX(pet_sightings.id) FROM pet_sightings WHERE pet_sightings.lost_report_id = lost_reports.id) AND " . $petSightingRadiusQueryString . " < " . $petSightingRadius);
}); // where pet sighting is enabled
});
Here is the result I am getting:-
Array
(
[id] => 1
[pet_id] => 3
[user_id] => 2
[phone] => 6290453837
[latitude] => 22.572645
[longitude] => 88.363892
[missing_date] => 2020-03-03 00:00:00
[found_date] =>
[is_found] => n
[is_delete] => n
[created_date] => 2020-03-03 15:08:03
[modified_date] => 2020-03-03 15:08:03
[created_at] => 2020-03-03 15:08:03
[updated_at] => 2020-03-03 15:08:03
[lost_report_pet] => Array
(
[id] => 3
[name] => Micky
[image] => p-1583228283-3.jpg
[pet_type_id] => 1
[breed_id] => 1
[color_id] => 1
[age] => 2
[weight] => 7
[description] => Very cute doggo
[is_approachable] => y
[user_id] => 2
[status] => a
[is_delete] => n
[is_lost] => y
[created_date] => 2020-03-03 15:08:03
[modified_date] => 2020-03-03 15:08:03
[created_at] => 2020-03-03 15:08:03
[updated_at] => 2020-03-03 15:08:03
)
)
As you can see, the relationship 'lost_report_pet'. How can I get the breed, color and pet_type relationship from lost_report_pet?
I'm pretty sure you could try with the relationship dot notation:
LostReport::with([
'lostReportPet.petBreed',
'lostReportPet.petPetType',
'lostReportPet.petColor'
]);

Error with saved method running migration

In my laravel 5.7 app I use Elasticsearch and in model I use saved and deleted methods of the related Model :
<?php
namespace App;
use DB;
use App\MyAppModel;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
class Vote extends MyAppModel
{
protected $table = 'votes';
protected $elasticsearch_type = 'vote';
protected $primaryKey = 'id';
public $timestamps = false;
public function getTableName(): string
{
return $this->table;
}
protected static function boot() {
parent::boot();
static::deleted(function ($vote ) {
// return; // TO UNCOMMENT
$elastic = app(\App\Elastic\Elastic::class);
$elasticsearch_root_index = config('app.elasticsearch_root_index');
$elasticsearch_type = with(new Vote)->getElasticsearchType();
$elastic->delete([
'index' => $elasticsearch_root_index,
'type' => $elasticsearch_type,
'id' => $vote->id,
]);
});
static::saved(function ($vote) {
// return; // TO UNCOMMENT
$elastic = app(\App\Elastic\Elastic::class);
$elasticsearch_root_index = config('app.elasticsearch_root_index');
$elasticsearch_type = with(new Vote)->getElasticsearchType();
$elastic->delete([
'index' => $elasticsearch_root_index,
'type' => $elasticsearch_type,
'id' => $vote->id,
]);
if ($vote->status == 'A') { // only active votes must be saved in elasticsearch
$elastic->index([
'index' => $elasticsearch_root_index,
'type' => $elasticsearch_type,
'id' => $vote->id,
'body' => [
'id' => $vote->id,
'slug' => $vote->slug,
'name' => $vote->name,
'description' => $vote->description,
]
]);
} // if ($vote->status == 'A') { // only active votes must be saved in elasticsearch
When I modify my data in my editor it works ok, but running seeder command
php artisan migrate:refresh --seed -v
I got error :
...
Migrating: 2018_07_13_150151_create_votes_table
Elasticsearch\Common\Exceptions\Missing404Exception : {"_index":"select_vote","_type":"vote","_id":"2","_version":1,"result":"not_found","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":18,"_primary_term":23}
at /mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Connections/Connection.php:607
603| $exception = new AlreadyExpiredException($responseBody, $statusCode);
604| } elseif ($statusCode === 403) {
605| $exception = new Forbidden403Exception($responseBody, $statusCode);
606| } elseif ($statusCode === 404) {
> 607| $exception = new Missing404Exception($responseBody, $statusCode);
608| } elseif ($statusCode === 409) {
609| $exception = new Conflict409Exception($responseBody, $statusCode);
610| } elseif ($statusCode === 400 && strpos($responseBody, 'script_lang not supported') !== false) {
611| $exception = new ScriptLangNotSupportedException($responseBody. $statusCode);
Exception trace:
1 Elasticsearch\Connections\Connection::process4xxError([])
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Connections/Connection.php:279
2 Elasticsearch\Connections\Connection::Elasticsearch\Connections\{closure}()
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/react/promise/src/FulfilledPromise.php:25
3 React\Promise\FulfilledPromise::then(Object(Closure))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php:55
4 GuzzleHttp\Ring\Future\CompletedFutureValue::then(Object(Closure))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/guzzlehttp/ringphp/src/Core.php:341
5 GuzzleHttp\Ring\Core::proxy(Object(GuzzleHttp\Ring\Future\CompletedFutureArray), Object(Closure))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Connections/Connection.php:299
6 Elasticsearch\Connections\Connection::Elasticsearch\Connections\{closure}(Object(Elasticsearch\Connections\Connection), Object(Elasticsearch\Transport), [])
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Connections/Connection.php:177
7 Elasticsearch\Connections\Connection::performRequest("DELETE", "/select_vote/vote/2", [], [], Object(Elasticsearch\Transport))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Transport.php:110
8 Elasticsearch\Transport::performRequest("DELETE", "/select_vote/vote/2", [], [])
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Client.php:1553
9 Elasticsearch\Client::performRequest(Object(Elasticsearch\Endpoints\Delete))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Client.php:265
10 Elasticsearch\Client::delete([])
/mnt/_work_sdb8/wwwroot/lar/Votes/app/Elastic.php:33
11 App\Elastic\Elastic::delete(["select_vote", "vote"])
/mnt/_work_sdb8/wwwroot/lar/Votes/app/Vote.php:142
12 App\Vote::App\{closure}(Object(App\Vote))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:360
13 Illuminate\Events\Dispatcher::Illuminate\Events\{closure}("eloquent.saved: App\Vote")
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:209
14 Illuminate\Events\Dispatcher::dispatch("eloquent.saved: App\Vote")
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php:162
15 Illuminate\Database\Eloquent\Model::fireModelEvent("saved")
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:692
16 Illuminate\Database\Eloquent\Model::finishSave([])
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:663
17 Illuminate\Database\Eloquent\Model::save()
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:790
18 Illuminate\Database\Eloquent\Builder::Illuminate\Database\Eloquent\{closure}(Object(App\Vote))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Support/helpers.php:1027
19 tap(Object(App\Vote), Object(Closure))
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:791
20 Illuminate\Database\Eloquent\Builder::create()
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php:23
21 Illuminate\Database\Eloquent\Model::forwardCallTo(Object(Illuminate\Database\Eloquent\Builder), "create")
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1608
22 Illuminate\Database\Eloquent\Model::__call("create")
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1620
23 Illuminate\Database\Eloquent\Model::__callStatic("create")
/mnt/_work_sdb8/wwwroot/lar/Votes/database/seeds/votesInitData.php:92
24 votesInitData::run()
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:29
25 call_user_func_array([])
/mnt/_work_sdb8/wwwroot/lar/Votes/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:29
...
If in saved and deleted methods to uncomment return that it works ok (without coping to elasticsearch).
Why Error and how to fix it?
Is there is a way to check that it is called from migration command and exit? Could this salve the problem ?
Thanks!
In similar case I set flag in my settings table in the beginning of Migrations scripts, like
DB::table('settings')->insert([
'name' => 'elastic_automation',
'value' => 'N',
]);
In the last migration script I change the key
Settings::where('name', 'elastic_automation')->update(['value' => 'Y']);
and I check this key in my model events. That works for me!

Display topic at top of list if has new reply

I have a list of my topics by default it will get the topics where the reply_id is 0 And then arrange them by there date_created.
How every if there is a reply to one of the topics then that topic should go to the top of the list.
Question How can I make sure if there is a new reply to a topic then that topic will go to list.
Currently my var dump as you can see have two items how ever the 2nd array item should be at top because it has a new last post time()
Array
(
[0] => Array
(
[title] => How to
[author] => demo
[author_post_time] => Tue Jun 13 , 2017 19:43:01 pm
[last_post_by] => demo
[latest_post_time] => Tue Jun 13 , 2017 19:43:01 pm
)
[1] => Array
(
[title] => How to install codeigniter
[author] => admin
[author_post_time] => Sat Jun 10 , 2017 23:26:48 pm
[last_post_by] => demo
[latest_post_time] => Tue Jun 13 , 2017 20:48:00 pm
)
)
Image of database
Model
<?php
class Topic_model extends CI_Model
{
public function get_active_topics($fid)
{
$data = array();
$this->db->select('t.*, u.username');
$this->db->from('topics t');
$this->db->join('user u', 'u.user_id = t.user_id');
$this->db->where('t.reply_id', '0');
$this->db->order_by('t.date_created', 'desc');
$query = $this->db->get();
foreach ($query->result_array() as $topic_result)
{
$reply = $this->get_reply($topic_result['topic_id']);
// This $date1 just for display only as shown on image
$date1 = date('D M d', $topic_result['date_created']) . ' , ' . date('Y H:i:s a', $topic_result['date_created']);
// This $date2 just for display only as shown on image
$date2 = date('D M d', $reply['date_created']) . ' , ' . date('Y H:i:s a', $reply['date_created']);
$data[] = array(
'title' => $topic_result['title'],
'author' => $topic_result['username'],
'author_post_time' => $date1,
'last_post_by' => isset($reply['username']) ? $reply['username'] : $topic_result['username'],
'latest_post_time' => ($reply['reply_id'] > 0) ? $date2 : $date1,
);
}
return $data;
}
public function get_reply($reply_id)
{
$this->db->select('t.*, u.username');
$this->db->from('topics t');
$this->db->join('user u', 'u.user_id = t.user_id');
$this->db->where('t.reply_id', $reply_id);
$this->db->limit(1);
$query = $this->db->get();
if ($query->num_rows() > 0) {
return $query->row_array();
}
return false;
}
}
Please try to use below mentioned line, I hope this will fix your issue.
Change From
$this->db->order_by('t.date_created', 'desc');
TO
$this->db->order_by('t.reply_id DESC, t.date_created DESC');
Try ordering your table first by date2 and if that doesnt exist (no reply) then date1. You seem to have it implemented already, you're just ordering by date created on the post.

Resources