Symfony PagerFanta GroupBy - mysql

I'm trying to use PagerFanta but got error like this:
Everything is well without PagerFanta, also PagerFanta works on other sites.
Repository code:
public function allMovies(): QueryBuilder
{
return $this->createQueryBuilder('m')
->leftJoin('m.rating', 'rating')
->addSelect('m.slug, m.name, m.filename, m.description, AVG(rating.vote) as votes')
->orderBy('m.releasedAt', 'desc')
->addGroupBy('m.name, m.slug')
;
}
I now that I haven't "GroupBy('rating')" but when I do it the AVG function doesn't work.
Here is my Controller:
#[Route('/movies/{page<\d+>}', name: 'movies')]
public function index(MovieRepository $movieRepository, int $page = 1): Response
{
$queryBuilder = $movieRepository->allMovies();
$pagerfanta = new PagerFanta(
new QueryAdapter($queryBuilder)
);
$pagerfanta->setMaxPerPage(5);
$pagerfanta->setCurrentPage($page);
return $this->render('content/movies.html.twig', [
'pager' => $pagerfanta,
]);
}

Related

How to retrieve data from MySQL to JSON?

I have a Symfony project where I want to store the all the rows from my MySQL table to JSON. Currently there are five rows in my table, but in my browser it only returns five empty values as {"results":[{},{},{},{},{}]}
I guess I have done something right, but not everything. What am I missing in my code?
#[Route('/budget/api', name: 'budget-api')]
public function index(Request $request, BudgetRepository $repository)
{
$results = $repository->findAll();
return $this->json(['results' => $results]);
}
Try createQueryBuilder its usefull.
#[Route('/budget/api', name: 'budget-api')]
public function index(Request $request, BudgetRepository $repository)
{
$qb = $repository->createQueryBuilder("b");
$results = $qb->getQuery()->getArrayResult();
return $this->json(['results' => $results]);
}
You can use the serializer or re-create the array yourself like that
$courses = $doctrine->getRepository(Course::class)->findByLikeTitle($search, $userId);
foreach ($courses as $key => $course) {
$jsonCourses[$key]['title'] = $course->getTitle();
}
```
You can achieve this by Using a Serializer to convert the array of objects into JSON. There are other ways to achieve this like using jsonResponse for example. But the serializer is the most robust way imo.
Example only:
use Symfony\Component\Serializer\SerializerInterface;
#[Route('/budget/api', name: 'budget-api')]
public function index(Request $request, BudgetRepository $repository, SerializerInterface $serializer)
{
$results = $repository->findAll();
$jsonResults = $serializer->serialize($results, 'json');
//If you need to handle any circular references, you can use this..
$jsonResults = $serializer->serialize($results, 'json', array(
'circular_reference_handler' => function ($object) { return $object; },
));
return $jsonResults;
}

How to do in Laravel, subquery with calculated fields on SELECT?

How can I make this query in Laravel eloquent. Please, no DB Record solution.
SELECT slo.batch,
slo.type,
(SELECT Count(sl1.id)
FROM sync_log sl1
WHERE sl1.status = 1
AND sl1.batch = slo.batch) AS success,
(SELECT Count(sl2.id)
FROM sync_log sl2
WHERE sl2.status = 0
AND sl2.batch = slo.batch) AS failed,
slo.created_at
FROM sync_log slo
GROUP BY batch
ORDER BY slo.created_at
Below is the database table.
Try something like :
$result=DB::table('sync_log as slo')
->select('slo.batch','slo.type', 'slo.created_at', DB::raw(('SELECT Count(sl1.id) FROM sync_log sl1 WHERE sl1.status=1 AND sl1.batch = slo.batch) AS success'), DB::raw(('SELECT Count(sl2.id) FROM sync_log sl2 WHERE sl2.status = 0 AND sl2.batch = slo.batch) AS failed')
->groupBy('batch')
->orderBy('slo.created_at')
->get();
Without any idea on your structure or models. guessing a manyToMany relation wetween batch and type where sync_log is the pivot table between them.
$batchs = Batch::withCount([
'types as success' => function ($query) {
$query->where('status', 1);
},
'types as failed' => function ($query) {
$query->where('status', 0);
}])
->get();
Using Eloquent ORM it can be tricky but I guess will work, you can define hasMany relation(s) in same model which will relate to same model using batch attribute/key like
class SyncLog extends Model
{
public function success_batches()
{
return $this->hasMany(SyncLog::class, 'batch', 'batch')->where('status',1);
}
public function failed_batches()
{
return $this->hasMany(SyncLog::class, 'batch', 'batch')->where('status',0);
}
}
Then using your model you can get count for these relations using withCount
$bacthes = SyncLog::withCount(['success_batches','failed_batches'])
->select(['batch','type'])
->distinct()
->orderBy('created_at')
->get();
If you don't want to define it twice based on where clause then you can follow the approach explained in #N69S's answer like
class SyncLog extends Model
{
public function batches()
{
return $this->hasMany(SyncLog::class, 'batch', 'batch');
}
}
$bacthes = SyncLog::withCount([
'batches as success' => function ($query) {
$query->where('status', 1);
},
'batches as failed' => function ($query) {
$query->where('status', 0);
}])
->select(['batch','type'])
->distinct()
->orderBy('created_at')
->get();

Laravel user model not being process in JSON response

I have a Laravel 5.8 API where the JSON response for a user collection works as expected but fails for a model.
namespace App\Traits;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
trait ApiResponder
{
private function successResponse($data, $code)
{
return response()->json($data, $code);
}
protected function errorResponse($message, $code)
{
return response()->json(['error' => $message, 'code' => $code], $code);
}
protected function showAll(Collection $collection, $code = 200)
{
return $this->successResponse(['data' => $collection], $code);
}
protected function showOne(Model $model, $code = 200)
{
return $this->successResponse(['data' => $model], $code);
}
}
Below are the controller methods calling for the response.
public function index()
{
$users = User::all();
return $this->showAll($users);
}
public function update(Request $request, $id)
{
$user = User::findOrFail($id);
$rules = [
'email' => 'email|unique:users,email,' . $user->id,
'password' => 'min:6|confirmed'
];
if ($request->has('name')) {
$user->name = $request->name;
}
if ($request->has('email') && $user->email != $request->email) {
$user->verififed = User::UNVERIFIED_USER;
$user->verififcation_token = User::generateVerificationCode();
$user->email = $request->email;
}
if ($request->has('password')) {
$user->password = bcrypt($request->password);
}
if (!$user->isDirty()) {
return $this->errorResponse('You need to specify a change to update', 422);
}
$user->save();
$this->showOne($user);
}
The index method handle as a collection works perfectly, but the update method using the model returns empty (no content at all). I have confirmed that the $data variable does contain the model information as expected as I can print a JSON encode that displays the result I want. It's just not working in response()->json() for some reason.
Very complex code for what it actually does.
Here you have the problem, needless to say to render the response, you need a return.
$user->save();
$this->showOne($user);
}
should be:
$user->save();
return $this->showOne($user);
}
Bonus: I would look into response transformation for future references see Eloquent Resources or Fractal. Instead of doing to much if logic, you can use FormRequest to validate the input.

autocomplete No Result found in laravel

I have two table "patient" and "booking" table, and there is a relationship "One to Many" between them, I want to set up a search form in an index_booking page where a user can type a patient_name on it and auto complete show all patient_name from patient table according to WHERE Condition.
This is Booking Model
class Booking extends Eloquent
{
public function patient()
{
return $this->belongsTo('App\Patient');
}
public function user()
{
return $this->belongsTo('App\User');
}
}
This is Patient Model
class Patient extends Eloquent
{
public function booking()
{
return $this->hasMany('App\Booking');
}
public function user()
{
return $this->belongsTo('App\User');
}
}
And i used this code in index page of booking
{!! Form::text('search_text', null, array('placeholder' => 'Search Text','class' => 'form-control','id'=>'search_text')) !!}
i used this code in Booking Controller to make autocomplete to show data
from patient table:
public function autoComplete(Request $request)
{
$patients = Patient::where('company_id', Auth::user()->company_id)
->where('patient_name', 'like', "&{$request->get('term')}&")
->get();
if ($patients->isEmpty()) {
return ['value' => 'No Result Found', 'id' => ''];
}
return $patients->map(function ($patient) {
return [
'id' => $patient->id,
'value' => $patient->patient_name,
];
});
}
And this is Route
Route::get('autocomplete',array('as'=>'autocomplete','uses'=>'BookingController#index'));
Route::get('searchajax',array('as'=>'searchajax','uses'=>'BookingController#autoComplete'));
Javascript code is
<script >
$(document).ready(function() {
src = "{{ route('searchajax') }}";
$("#search_text").autocomplete({
source: function(request, response) {
$.ajax({
url: src,
dataType: "json",
data: {
term : request.term
},
success: function(data) {
response(data);
}
});
},
minLength: 3,
});
});
</script>
when i type any patient name in search box i received a message No Result Found
this is the validator in booking controller :
public function store(Request $request)
{
//Validate Data
$this->validate($request, [
'patient_id'=> 'required|integer',
'booking_date'=> 'required|max:255',
'tybe'=> 'required',
'value'=>'required',
'doctor_name',
'patient_history',
'pharma',
'complaint',
'diagnosis',
'recomind',
'prescription',
'notes',
'document',
'by',
]);
//Insert Data to Database
$booking = new Booking;
$booking->patient_id = $request->patient_id;
$booking->booking_date = $request->booking_date;
$booking->tybe = $request->tybe;
$booking->value = $request->value;
$booking->doctor_name = $request->doctor_name;
$booking->patient_history = $request->patient_history;
$booking->pharma = $request->pharma;
$booking->complaint = $request->complaint;
$booking->diagnosis = $request->diagnosis;
$booking->recomind = $request->recomind;
$booking->prescription = $request->prescription;
$booking->notes = $request->notes;
$booking->document = $request->document;
$booking->by = $request->by;
$booking->save();
//to save multi selection Tags ,dont foget to add [] after -> tags in create post page then write this code here
//$post->tags()->sync($request->tags, false);
//Show Flash Message
Session::flash('success','تم حفظ البياانات');
//Redirect to another Page
return redirect()->route('booking.index');
}
SQL's syntax for matching with LIKE operator is:
WHERE `column` LIKE '%needle%'
Your code, on the other hand, produces the following:
WHERE `column` LIKE '&needle&'
Which is virtually the same as if you had typed:
WHERE `column` = '&needle&'
So what you need to do is to replace & with % in the following line:
->where('patient_name', 'like', "&{$request->get('term')}&")

Base Table not found on unique value validation in MongoDB with laravel

I'm using laravel 5.3 with jenssegers/laravel-mongodb package for managing mongodb connections.
I want to check every time a user send a request to register a website in my controller if it's unique then let the user to register his/her website domain.
I wrote below code for validation but What I get in result is :
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'iranad.seat' doesn't exist (SQL: select count(*) as aggregate from `seat` where `domain` = order.org)
my controller code :
public function store(Request $request) {
$seat = new Seat();
$validator = Validator::make($request->all(), [
'domain' => 'required|regex:/^([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/|unique:seat', //validating user is entering correct url like : iranad.ir
'category' => 'required',
]);
if ($validator->fails()) {
return response()->json($validator->messages(), 400);
} else {
try {
$statusCode = 200;
$seat->user_id = Auth::user()->id;
$seat->url = $request->input('domain');
$seat->cats = $request->input('category');
$seat->filter = [];
if($request->input('category') == 'all') {
$obj['cats'] = 'false';
$seat->target = $obj;
} else {
$obj['cats'] = 'true';
$seat->target = $obj;
}
$seat->status = 'Waiting';
$seat->save();
} catch (\Exception $e) {
$statusCode = 400;
} finally {
$response = \Response::json($seat, $statusCode);
return $response;
}
}
}
My Seat Model :
namespace App;
use Moloquent;
use Carbon\Carbon;
class Seat extends Moloquent {
public function getCreatedAtAttribute($value) {
return Carbon::createFromTimestamp(strtotime($value))
->timezone('Asia/Tehran')
->toDateTimeString();
}
}
Obviously The validator is checking if domain is unique in mysql tables which causes this error, How can I change my validation process to check mongodb instead of mysql ?
I solved the problem, The solution is that you should add Moloquent to your model and define database connection :
namespace App\Models;
use Moloquent;
use Carbon\Carbon;
class Seat extends Moloquent
{
protected $collection = 'seat';
protected $connection = 'mongodb';
}