I'm developing two projects with Symfony2, and I began to code the second project and I'm facing some problems with Custom functions to search in my tables.
This is my Sites Entity
namespace Ad\SisBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Sites
*
* #ORM\Table(name="sites")
* #ORM\Entity(repositoryClass="Ad\SisBundle\Entity\SitesRepository")
*/
class Sites
{
This is my SitesRepository Entity
namespace Ad\SisBundle\Entity;
use Doctrine\ORM\EntityRepository;
class SitesRepository extends EntityRepository
{
The problem is that I can't access any function that I create in my SitesRepository
I was dumping the doctrine EntityRepository Class and I saw this.
EntityRepository {#309 ▼
#_entityName: "Ad\SisBundle\Entity\Sites"
#_em: EntityManager {#289 …10}
#_class: ClassMetadata {#298 ▼
+name: "Ad\SisBundle\Entity\Sites"
+namespace: "Ad\SisBundle\Entity"
+rootEntityName: "Ad\SisBundle\Entity\Sites"
+customGeneratorDefinition: null
+customRepositoryClassName: null
+isMappedSuperclass: false
+parentClasses: []
+subClasses: []
+namedQueries: []
+namedNativeQueries: []
+sqlResultSetMappings: []
+identifier: array:1 [▶]
+inheritanceType: 1
+generatorType: 4
+fieldMappings: array:5 [▶]
+fieldNames: array:5 [▶]
+columnNames: array:5 [▶]
+discriminatorValue: null
+discriminatorMap: []
+discriminatorColumn: null
+table: array:1 [▶]
+lifecycleCallbacks: []
+entityListeners: []
+associationMappings: []
+isIdentifierComposite: false
+containsForeignIdentifier: false
+idGenerator: IdentityGenerator {#306 ▶}
+sequenceGeneratorDefinition: null
+tableGeneratorDefinition: null
+changeTrackingPolicy: 1
+isVersioned: null
+versionField: null
+reflClass: ReflectionClass {#307 ▶}
+isReadOnly: false
#namingStrategy: DefaultNamingStrategy {#276}
+reflFields: array:5 [▶]
-_prototype: null
}
}
So I went to my first project, that is working perfectly, and did the same thing.
ScheduleRepository {#1931 ▼
#_entityName: "ApplicationBundle\Entity\Schedule"
#_em: EntityManager {#137 …10}
#_class: ClassMetadata {#1825 ▼
+name: "ApplicationBundle\Entity\Schedule"
+namespace: "ApplicationBundle\Entity"
+rootEntityName: "ApplicationBundle\Entity\Schedule"
+customGeneratorDefinition: null
+customRepositoryClassName: "ApplicationBundle\Entity\ScheduleRepository"
+isMappedSuperclass: false
+parentClasses: []
+subClasses: []
+namedQueries: []
+namedNativeQueries: []
+sqlResultSetMappings: []
+identifier: array:1 [▶]
+inheritanceType: 1
+generatorType: 4
+fieldMappings: array:3 [▶]
+fieldNames: array:3 [▶]
+columnNames: array:3 [▶]
+discriminatorValue: null
+discriminatorMap: []
+discriminatorColumn: null
+table: array:2 [▶]
+lifecycleCallbacks: array:2 [▶]
+entityListeners: []
+associationMappings: array:2 [▶]
+isIdentifierComposite: false
+containsForeignIdentifier: false
+idGenerator: IdentityGenerator {#1852 ▶}
+sequenceGeneratorDefinition: null
+tableGeneratorDefinition: null
+changeTrackingPolicy: 1
+isVersioned: null
+versionField: null
+reflClass: ReflectionClass {#1840 ▶}
+isReadOnly: false
#namingStrategy: DefaultNamingStrategy {#119}
+reflFields: array:5 [▶]
-_prototype: null
}
}
In my Schedule Entity from project #1 I have the customRepositoryClassName filled, but in my Sites Entity not. Why? The both use the same version of doctrine and symfony.
I saw that the dump in project #1 is dumping ScheduleRepository and project #2 is dumping EntityRepository. Maybe this is the problem?
Project #1 dump:
$em = $this->getDoctrine()->getManager();
dump( $em->getRepository( "ApplicationBundle:Schedule" ) );exit;
Project #2 dump:
$em = $this->getDoctrine()->getManager();
dump( $em->getRepository( "AdSisBundle:Sites" ) );exit;
The entities from project #2 was created using: http://symfony.com/doc/current/cookbook/doctrine/reverse_engineering.html
That is the only difference between the both projects.
Thank you for the help.
Related
I used eloquent method in my controller to collect data from my database, but something weird happened. If i use this code below,
$female_old_visitors = Treatment::with('diseases', 'patient', 'insurance', 'referer')
->leftJoin('patients', 'treatments.patient_id', 'patients.id')
->where('treatments.visit_status', 'old')
->where('patients.gender', 'female')
->whereBetween('treatments.date', $date_range)
->get();
i can get all the data that i want include diseases and referer
Collection {#3053 ▼
#items: array:25 [▼
0 => Treatment {#2799 ▼
...
#relations: array:4 [▼
"diseases" => Collection {#3346 ▼
#dates: array:1 [▶]
#cascadeDeletes: array:1 [▶]
#guarded: []
#connection: "mysql"
#table: "diseases"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:32 [▶]
#original: array:32 [▶]
#changes: []
#casts: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#forceDeleting: false
}
"patient" => Patient {#3328 ▶}
"insurance" => Insurance {#3346 ▶}
"referer" => TreatmentReferer {#3138 ▶}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#forceDeleting: false
}
but when i use other code like this
$common_insurance_old_visitors = Treatment::with('diseases', 'patient', 'insurance', 'referer')
->leftJoin('insurances', 'treatments.insurance_id', 'insurances.id')
->where('treatments.visit_status', 'old')
->where('insurances.id', 1)
->whereBetween('treatments.date', $date_range)
->get();
all the data has been selected or collected except disease and referer
Collection {#3053 ▼
#items: array:25 [▼
0 => Treatment {#2799 ▼
...
#relations: array:4 [▼
"diseases" => Collection {#3246 ▼
#items: []
}
"patient" => Patient {#3328 ▶}
"insurance" => Insurance {#3346 ▶}
"referer" => null
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#forceDeleting: false
}
i have been checking in my database, that the data is still there and the column is not empty, it should be collected just like the code i use first. Is it because i use left join uncorrectly? i am still new for laravel, thanks for anyone who giving me a solution for this problem
this is my model for Treatment
<?php
namespace App;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Iatstuti\Database\Support\CascadeSoftDeletes;
class Treatment extends Model
{
use SoftDeletes, CascadeSoftDeletes;
protected $dates = ['deleted_at'];
protected $cascadeDeletes = ['medicines', 'actions', 'referer', 'diseases', 'queues'];
protected $guarded = [];
public function queues(){
return $this->hasMany(TreatmentQueue::class);
}
public function treatmentType(){
return $this->belongsTo(TreatmentType::class);
}
public function medicines(){
return $this->hasMany(TreatmentMedicine::class)->with('medicine', 'recu');
}
public function actions(){
return $this->hasMany(TreatmentAction::class)->with('action', 'doctor', 'nurse', 'recu', 'teeth', 'therapy', 'treatmentDisease');
}
public function insurance(){
return $this->belongsTo(Insurance::class);
}
public function referer(){
return $this->hasOne(TreatmentReferer::class)->with('puskesmas', 'disease');
}
public function diseases(){
return $this->hasMany(TreatmentDisease::class)->with('disease', 'doctor', 'teeth');
}
public function patient(){
return $this->belongsTo(Patient::class);
}
}
with() is for eager loading. That basically means, along the main model, Laravel will preload the relationship(s) you specify. This is especially helpful if you have a collection of models and you want to load a relation for all of them. Because with eager loading you run only one additional DB query instead of one for every model in the collection.
In your example.
you're using left join why? it already contain in with() you use with('patient') it means you join treatments to left join with patient
$female_old_visitors = Treatment::with('diseases', 'insurance', 'referer')
->with(['patient' => function ($q) {
$q->where('gender', 'female');
}])
->where('visit_status', 'old')
->whereBetween('treatments.date', $date_range)
->get();
eager-loads
**** UPDATE *******************************************************
I'm not sure why, but moving everything into the controllers index() method rather than having it in the show() method solved the problem. Don't know why it works, but it does.
Original Question:
Cant figure out what is wrong here, i have followed the docs, tried variations, etc... still no luck making this work correctly.
Model A: (Slide)
public function carousels() {
return $this->belongsToMany(Carousel::class)->withTimestamp()
}
Model B: (Carousel)
public function slides() {
return $this->belongsToMany(Slide::class)->withTimestamp()
}
Pivot Table
--------------------------------------------------
|carousel_id | slide_id | created_at | updated_at|
--------------------------------------------------
From Controller:
public function show(Carosuel $carousels) {
$carousels = $carousel->with('slides)->get();
return view('myView', compact(['carousels']));
}
In the following dump, the "slides" are not in the attributes object of the collection; however, they are in the relations object. Im not sure if this is normal behavior or if the slides array should be in the attributes object. If the latter is the case, then how does one go about making that happen?
$caousels dump:
Collection {#1320 ▼
#items: array:20 [▼
0 => Carousel {#798 ▼
#fillable: array:4 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:7 [▼
"id" => 1
"name" => "Prof. Andre Gerlach"
"category" => "Dr."
"active" => 0
"deleted_at" => null
"created_at" => "2018-04-07 21:10:52"
"updated_at" => "2018-04-07 21:10:52"
]
#original: array:7 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [▼
"slides" => Collection {#1300 ▼
#items: array:5 [▼
0 => Slide {#1023 ▶}
1 => Slide {#1024 ▶}
2 => Slide {#1025 ▶}
3 => Slide {#1026 ▶}
4 => Slide {#1027 ▶}
]
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
1 => Carousel {#799 ▶}
2 => Carousel {#800 ▶}
In the View:
foreach($carousels as $carousel){
echo $carousel->name;
foreach($carousel->slides as $slide){
echo $slide->tag;
}
}
This throws the E_ERROR Invalid argument supplied for foreach() in view
If, however, I cast this to an array, it works. Problem is that i also need to paginate the results. Once i do, the slides array is again inaccessible.
public function show(Carosuel $carousels) {
// This works - slides are available to me in the view
$carousels = $carousel->with('slides)->get()->toarray();
// This DOESN'T work - slides are not available to me in the view
$carousels = $carousel->with('slides)->paginate(6)->toarray();
return view('myView', compact(['carousels']));
}
dump as array:
array:12 [▼
"current_page" => 1
"data" => array:6 [▼
0 => array:8 [▼
"id" => 1
"name" => "Prof. Andre Gerlach"
"category" => "Dr."
"active" => 0
"deleted_at" => null
"created_at" => "Apr 07 2018"
"updated_at" => "2018-04-07 21:10:52"
"slides" => array:5 [▼
0 => array:11 [▶]
1 => array:11 [▶]
2 => array:11 [▶]
3 => array:11 [▶]
4 => array:11 [▶]
]
]
1 => array:8 [▶]
2 => array:8 [▶]
3 => array:8 [▶]
4 => array:8 [▶]
5 => array:8 [▶]
]
"first_page_url" => "//localhost:3000/admin/carousel/show?page=1"
"from" => 1
"last_page" => 4
"last_page_url" => "//localhost:3000/admin/carousel/show?page=4"
"next_page_url" => "//localhost:3000/admin/carousel/show?page=2"
"path" => "//localhost:3000/admin/carousel/show"
"per_page" => 6
"prev_page_url" => null
"to" => 6
"total" => 20
The problem here is that, in the view, the slides key is no longer accessible. Throws following error (only if I use ->paginate()).
E_ERROR Trying to get property 'slides' of non-object
Everything I have read in the docs and from other sources show this to be a pretty basic operation. For the live of me, i cant figure out why its causing such an issue. I should be able to access this in the view by simply nesting a foreach.
Any help with this would be greatly appreciated.
In the following dump, the "slides" are not in the attributes object of the collection; however, they are in the relations object.
Yes this is normal.
This is where you have a problem:
public function show(Carosuel $carousels) {
// ...
return view('myView', compact(['carousels']));
}
Typehinting a model in a function is reserved for model binding. Which is not what you're doing here since you don't have an {id} or some other parameter in your route.
Remove the typehinting and call the model instead:
public function show() {
$carousels = Carousel::with('slides')->get();
return view('myView', compact(['carousels']));
}
If you'd like to remove the dependency from the method, you should do it in the constructor instead.
Edit:
While I don't see any other problem and the above solution should work, if it's true that ->toArray() works for you (but you still need pagination), you could just convert the underlying collection:
public function show() {
$carousels = Carousel::with('slides')->paginate();
$carousels->setCollection(collect($carousels->getCollection()->toArray()));
return view('myView', compact(['carousels']));
}
Can you try this?
Model B: (Carousel)
public function slides() {
return $this->hasMany(Slide::class)->withTimestamp();
}
I've encountered a silly problem this morning and I struggle to find a decent solution. Maybe you can tip me...
I've this simple function in a entity repository, with a simple query:
public function findAvailabilityByDr($delivery_round_id) {
$qb = $this->_em->createQueryBuilder()
->select('partial dro.{id},
partial drp.{id, maxDeliveries, countDeliveries},
partial zdd.{id, day},
partial rer.{id, maxOrders, countOrders}')
->from($this->_entityName, 'dro')
->leftJoin('dro.parts', 'drp')
->leftJoin('drp.day', 'zdd')
->leftJoin('drp.relayRounds', 'rer')
->where('dro.id = :delivery_round_id')
->setParameters(array(
'delivery_round_id' => $delivery_round_id,
));
dump($qb->getQuery()->getOneOrNullResult());
die();
}
At the first load (with no session cookie created), I got an incomplete result:
DeliveryRound {#342 ▼
-id: 117
-endOfOrdersDate: DateTime {#346 ▶}
-parts: PersistentCollection {#428 ▼
-snapshot: array:2 [ …2]
-owner: DeliveryRound {#342}
-association: array:15 [ …15]
-em: EntityManager {#695 …11}
-backRefFieldName: "deliveryRound"
-typeClass: ClassMetadata {#373 …}
-isDirty: false
#collection: ArrayCollection {#412 ▼
-elements: array:2 [▼
0 => DeliveryRoundPart {#425 ▼
-id: 134
-deliveryDate: DateTime {#347 ▶}
-deliveryHourStart: null
-deliveryHourEnd: null
-maxDeliveries: null <------ HERE !!!!!!!!!!!
-countDeliveries: null
-deliveryRound: DeliveryRound {#342}
-day: ZoneDeliveryDay {#1302 ▶}
-ordersCustomers: PersistentCollection {#358 ▶}
-ordersProviders: PersistentCollection {#410 ▶}
-relayRounds: PersistentCollection {#637 ▶}
-roadSheetOptimizationData: null
}
1 => DeliveryRoundPart {#1444 ▶}
]
}
#initialized: true
}
-ordersProvidersGenDate: null
-roadSheetPath: null
-roadSheetGenDate: null
-preparationSheetPath: null
-preparationSheetGenDate: null
-deliveryMailNotificationsSendingDate: null
-deliveryNotificationsSendingDate: null
#translations: PersistentCollection {#420 ▶}
#newTranslations: null
#currentLocale: "fr"
#defaultLocale: "fr"
}
And at the second call (refresh), the session cookie is created and the result is correct (maxDeliveries: 30 is a correct value):
DeliveryRound {#1657 ▼
-id: 117
-endOfOrdersDate: null
-parts: PersistentCollection {#1794 ▼
-snapshot: array:2 [ …2]
-owner: DeliveryRound {#1657}
-association: array:15 [ …15]
-em: EntityManager {#695 …11}
-backRefFieldName: "deliveryRound"
-typeClass: ClassMetadata {#1673 …}
-isDirty: false
#collection: ArrayCollection {#1795 ▼
-elements: array:2 [▼
0 => DeliveryRoundPart {#1747 ▼
-id: 134
-deliveryDate: null
-deliveryHourStart: null
-deliveryHourEnd: null
-maxDeliveries: 30 <------ HERE !!!!!!!!!!!
-countDeliveries: 0
-deliveryRound: DeliveryRound {#1657}
-day: ZoneDeliveryDay {#2063 ▶}
-ordersCustomers: PersistentCollection {#1904 ▶}
-ordersProviders: PersistentCollection {#1896 ▶}
-relayRounds: PersistentCollection {#2187 ▶}
-roadSheetOptimizationData: null
}
1 => DeliveryRoundPart {#2188 ▶}
]
}
#initialized: true
}
-ordersProvidersGenDate: null
-roadSheetPath: null
-roadSheetGenDate: null
-preparationSheetPath: null
-preparationSheetGenDate: null
-deliveryMailNotificationsSendingDate: null
-deliveryNotificationsSendingDate: null
#translations: PersistentCollection {#1799 ▶}
#newTranslations: null
#currentLocale: "fr"
#defaultLocale: "fr"
}
And when I use $qb->getQuery()->getArrayResult()
the results are correct in both cases.
WTF ? Is it bug ?
Thanks for your help !
EDIT
If I reduce it to its simplest expression, with no partial and a call from a controller, the bug is still there...
Repository:
public function findAvailabilityByDr($delivery_round_id) {
$qb = $this->_em->createQueryBuilder()
->select('dro,
drp')
->from($this->_entityName, 'dro')
->leftJoin('dro.parts', 'drp')
->where('dro.id = :delivery_round_id')
->setParameters(array(
'delivery_round_id' => $delivery_round_id,
));
return $qb->getQuery()->getOneOrNullResult();
}
Controller:
class StructureController extends BasePublicCommonController
{
public function indexAction()
{
$delivery_round = $this->getDoctrine()->getManager()->getRepository('ProxymartDeliveryBundle:DeliveryRound')->findAvailabilityByDr(117);
dump($delivery_round);
die();
}
}
This is for things like this I hate programming sometimes :)
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/partial-objects.html
I don't know about the cookie, but I know for arrayResult():
The partial object problem in general does not apply to methods or queries where you do not retrieve the query result as objects. Examples are: Query#getArrayResult() [...]
In my Laravel App, a poll has many poll options. I can create a collection of those options by simply running:
$result = Poll::find(1)->options()->get();
This query returns:
Collection {#387 ▼
#items: array:6 [▼
0 => PollOption {#388 ▼
#table: "poll_options"
#connection: null
#primaryKey: "id"
#keyType: "int"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:8 [▼
"id" => 1
"poll_id" => 1
"option_text" => "Never"
"responses" => 54
"is_public" => 0
"created_at" => null
"updated_at" => null
"deleted_at" => null
]
#original: array:8 [▶]
#relations: []
#hidden: []
#visible: []
#appends: []
#fillable: []
#guarded: array:1 [▶]
#dates: []
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
+wasRecentlyCreated: false
}
1 => PollOption {#389 ▶}
2 => PollOption {#390 ▶}
3 => PollOption {#391 ▶}
]
}
Within my poll option, there is a column called responses, which returns an integer. I need to take the collection above and isolate the responses key/value pair.
Collection {#385 ▼
#items: array:6 [▼
"responses" => 54
"responses" => 20
"responses" => 10
"responses" => 123
"responses" => 33
"responses" => 11
]
}
The only() collection method does exactly what I need, but I can't figure out how to structure the query when working with Eloquent models:
$options = Poll::find(1)->options()->get();
$responses = $options->only('responses');
dd($responses->all());
Returns an empty collection because the responses value is nested within the PollOption object.
I've also tried flatten(), but that seems to have no effect in this scenario.
Is there an easier way to return a single key/value pair within an Eloquent model collection?
It's not actually possible to assign the same key to multiple values within a collection. I knew this, but I wasn't thinking the problem through properly.
For future devs: the pluck() method takes two arguments: the value you want to pluck, and a second value that gets assigned to the key. Using the scenario above, I was able to write:
$result = $poll->options()->pluck('responses', 'option_text'); //Value and corresponding key
This results in something like:
Collection {#386 ▼
#items: array:6 [▼
"Never" => 54
"Occasionally" => 21
"2–3 times a week" => 80
"4–5 times per week" => 33
"Daily" => 11
]
}
Which ultimately did what I need it to do. Amit Gupta's mapWithKeys() answer is also correct, and will land you in the same place.
I have some nested query in my application such as example follow.
$arrData = DB::table('service as tsv')
->select($afields)
->join('shops as ts', 'ts.id', '=', 'tsv.shop_id')
->where('ts.name','like','%'.$searchstring.'%');
if(!empty($type) && $type == 'individual')
$arrData->where('ts.type','=', '1');
$arrData->groupBy('tsv.id')->get();
This query not returning the exact output it display the content like
Builder {#351 ▼
#connection: MySqlConnection {#336 ▶}
#grammar: MySqlGrammar {#347 ▶}
#processor: MySqlProcessor {#348}
#bindings: array:5 [▶]
+aggregate: null
+columns: array:7 [▶]
+distinct: false
+from: "service as tsv"
+joins: array:3 [▶]
+wheres: array:3 [▶]
+groups: array:1 [▶]
+havings: null
+orders: array:1 [▶]
+limit: 4
+offset: 0
+unions: null
+unionLimit: null
+unionOffset: null
+unionOrders: null
+lock: null
#backups: []
#operators: array:26 [▶]
#useWritePdo: false
}
I want to display the data how should I access the data from this situation.