title: CakePHP 3 matching and contain not returning association
body: <p>I'm using CakePHP 3.3.9 and trying to use the <code>friendsofcake/search</code> plugin + pagination to filter a list of <code>AssessmentLogs</code> based on <code>Clients.EmrSystems</code>, in which <code>EmrSystems</code> is a belongsToMany association on <code>Clients</code>. This is all on a SQL Server database if it makes a difference. </p>
  
  <p>My problem is that when I use <code>matching()</code> and <code>contain()</code> I receive the correct results but the <code>Client</code> association is missing from the <code>AssessmentLog</code> record, even though it is explicitly contained. I'm not concerned about getting the <code>EmrSystems</code> for a <code>Client</code> under each <code>AssessmentLog</code>, only the <code>Client</code> that owns it. </p>
  
  <p>The query generated even appears correct, but the ORM just has a null value for the <code>client</code> association on each record. Even <code>_matchingData</code> contains <code>client</code> according to DebugKit, so I know the right info is there. Manually running the generated query even returns the right results.</p>
  
  <p>Here's how the associations are laid out: </p>
  
  <h3>AssessmentLogsTable</h3>
  
  <pre><code>// AssessmentLog belongs to a Client using ClientId field
  $this-&gt;belongsTo('Clients', [
      'foreignKey' =&gt; 'ClientId'
  ]);
  
  // Search plugin
  $this-&gt;searchManager()-&gt;add('EmrSystem', 'Search.Callback', [
      'callback' =&gt; function ($query, $args, $manager) {
          if (!is_array($args['EmrSystem'])) {
              return false;
          }
  
          // Not returning the Client association for some reason :(
          // Should return only assessment logs where the client has a specified EMR system.
          // The AssessmentLog should always contain the Client association
  
          return $query-&gt;contain([
              'Clients',
              'Clients.EmrSystems'
          ])
          -&gt;matching('Clients.EmrSystems', function ($q) use ($args) {
              return $q-&gt;where(function ($exp) use ($args) {
                  return $exp-&gt;in('EmrSystems.ID', $args['EmrSystem']);
              });
          });
      },
      'filterEmpty' =&gt; true
  ]);
  </code></pre>
  
  <h3>ClientsTable</h3>
  
  <pre><code>// Client has many assessment logs - The ID fields aren't named consistently and wasn't my choice or design. The field name is correct.
  $this-&gt;hasMany('AssessmentLogs', [
      'foreignKey' =&gt; 'ClientID'
  ]);
  
  // Client can have multiple EMR (Electronic Medical Record) systems
  $this-&gt;belongsToMany('EmrSystems', [
      'joinTable' =&gt; 'ClientEmrSystem',
      'foreignKey' =&gt; 'ClientId',
      'targetForeignKey' =&gt; 'EmrSystemId',
      'through' =&gt; 'ClientEmrSystems',
      'saveStrategy' =&gt; 'replace'
  ]);
  </code></pre>
  
  <h3>AssessmentLogsController</h3>
  
  <pre><code>// Load other associations
  $this-&gt;paginate['contain'] = [
      'AssessmentTypes' =&gt; function ($q) {
          return $q-&gt;select([
              'AssessmentTypes.AssessmentTypeCd',
              'AssessmentTypes.AssessmentTypeShort'
          ]);
      },
      'Clients' =&gt; function ($q) {
          return $q-&gt;select([
              'Clients.ClientId',
              'Clients.OrganizationName'
          ]);
      },
      'Patients' =&gt; function ($q) {
          return $q-&gt;select([
              'Patients.PatientId',
              'Patients.FirstName',
              'Patients.LastName'
          ]);
      }   
  ];
  
  // Use Search Plugin
  $assessmentLogs = $this-&gt;AssessmentLogs-&gt;find(
      'search', 
      $this-&gt;AssessmentLogs-&gt;filterParams($this-&gt;request-&gt;query)
  );
  
  $this-&gt;set('assessmentLogs', $this-&gt;paginate($assessmentLogs));
  </code></pre>
  
  <h3>Generated Query</h3>
  
  <p>I've included some other associations that are working correctly and returning patient names, types, etc.</p>
  
  <pre><code>SELECT 
    AssessmentLogs.AssessmentLogId AS [AssessmentLogs__AssessmentLogId], 
    AssessmentLogs.ClientID AS [AssessmentLogs__ClientID], 
    AssessmentLogs.PatientID AS [AssessmentLogs__PatientID], 
    AssessmentLogs.AssessmentTypeCd AS [AssessmentLogs__AssessmentTypeCd], 
    Clients.ClientId AS [Clients__ClientId], 
    Clients.OrganizationName AS [Clients__OrganizationName], 
    ClientEmrSystems.ClientId AS [ClientEmrSystems__ClientId], 
    ClientEmrSystems.EmrSystemId AS [ClientEmrSystems__EmrSystemId], 
    ClientEmrSystems.Created AS [ClientEmrSystems__Created], 
    ClientEmrSystems.Modified AS [ClientEmrSystems__Modified], 
    EmrSystems.ID AS [EmrSystems__ID], 
    EmrSystems.Name AS [EmrSystems__Name], 
    EmrSystems.Created AS [EmrSystems__Created], 
    EmrSystems.Modified AS [EmrSystems__Modified], 
    AssessmentTypes.AssessmentTypeCd AS [AssessmentTypes__AssessmentTypeCd], 
    AssessmentTypes.AssessmentTypeShort AS [AssessmentTypes__AssessmentTypeShort], 
    Patients.PatientId AS [Patients__PatientId], 
    Patients.FirstName AS [Patients__FirstName], 
    Patients.LastName AS [Patients__LastName]
  FROM 
    AssessmentLog AssessmentLogs 
    INNER JOIN Client Clients ON Clients.ClientId = (AssessmentLogs.ClientId) 
    INNER JOIN ClientEmrSystem ClientEmrSystems ON Clients.ClientId = (ClientEmrSystems.ClientId) 
    INNER JOIN EmrSystem EmrSystems ON EmrSystems.ID = (ClientEmrSystems.EmrSystemId) 
    LEFT JOIN AssessmentType AssessmentTypes ON AssessmentTypes.AssessmentTypeCd = (
      AssessmentLogs.AssessmentTypeCd
    ) 
    LEFT JOIN Patient Patients ON Patients.PatientId = (AssessmentLogs.PatientId) 
  WHERE 
    (
      EmrSystems.ID in (1) 
      AND (
        AssessmentLogs.Void = 0 
      )
    ) 
  ORDER BY 
    AssessmentLogs.AssessmentLogId OFFSET 0 ROWS FETCH FIRST 40 ROWS ONLY
  </code></pre>
  
  <h3>Schema Sample</h3>
  
  <pre><code>CREATE TABLE [dbo].[Client](
      [ClientId] [int] NOT NULL,
      [OrganizationName] [varchar](max) NULL,
      [Email] [varchar](max) NULL,
      [WorkPhone] [varchar](max) NULL,
      [Fax] [varchar](max) NULL,
      [UpdatedDate] [datetime] NULL,
      [Notes] [text] NULL,
      CONSTRAINT [PK_Clients] PRIMARY KEY CLUSTERED 
      (
          [ClientId] ASC
      )
  );
  
  CREATE TABLE [dbo].[AssessmentLog](
      [AssessmentLogId] [int] IDENTITY(1,1) NOT NULL,
      [ClientID] [int] NOT NULL,
      [PatientID] [int] NOT NULL,
      [AssessmentTypeCd] [int] NOT NULL,
      [Note] [varchar](max) NULL,
      [Void] [bit] NOT NULL,
      [DateInserted] [datetime] NOT NULL,
      [DateCharged] [datetime] NULL,
      CONSTRAINT [PK_AssessmentLog] PRIMARY KEY CLUSTERED 
      (
          [AssessmentLogId] ASC
      )
  );
  
  CREATE TABLE [dbo].[Patient](
      [PatientId] [int] IDENTITY(1,1) NOT NULL,
      [ClientId] [int] NOT NULL,
      [FirstName] [varchar](max) NOT NULL,
      [LastName] [varchar](max) NOT NULL,
      [MedicalRecordNbr] [varchar](max) NOT NULL,
      CONSTRAINT [PK_Patient] PRIMARY KEY CLUSTERED 
      (
          [PatientId] ASC
      )
  );
  
  CREATE TABLE [dbo].[AssessmentType](
      [AssessmentTypeCd] [int] IDENTITY(1,1) NOT NULL,
      [AssessmentTypeShort] [varchar](50) NULL,
      [AssessmentTypeLong] [varchar](max) NULL,
      CONSTRAINT [PK_AssessmentType] PRIMARY KEY CLUSTERED 
      (
          [AssessmentTypeCd] ASC
      )
  );
  
  CREATE TABLE [dbo].[EmrSystem](
      [ID] [int] IDENTITY(1,1) NOT NULL,
      [Name] [varchar](50) NOT NULL,
      [Created] [datetime2](7) NULL,
      [Modified] [datetime2](7) NULL,
      CONSTRAINT [PK_EmrSystem] PRIMARY KEY CLUSTERED 
      (
          [ID] ASC
      )
  );
  
  CREATE TABLE [dbo].[ClientEmrSystem](
      [ClientId] [int] NOT NULL,
      [EmrSystemId] [int] NOT NULL,
      [Created] [datetime2](7) NULL,
      [Modified] [datetime2](7) NULL,
      CONSTRAINT [PK_ClientEmrSystem] PRIMARY KEY CLUSTERED 
      (
          [ClientId] ASC,
          [EmrSystemId] ASC
      )
  );
  </code></pre>
  
  <h3>Sample Records</h3>
  
  <p>Here's sample records. I've specified primary keys even though they're auto-increment/identity columns just for simplicity:</p>
  
  <pre><code>INSERT INTO [dbo].[Client] (
      [ClientId],
      [OrganizationName],
      [Email],
      [WorkPhone],
      [Fax],
      [UpdatedDate],
      [Notes],
  ) VALUES (
      123,
      'Sample Client',
      'sample@sample.com',
      '(555) 555-1234',
      '(555) 555-5678',
      '2016-12-12 12:00:00',
      'Sample notes about sample client.'
  );
  
  INSERT INTO [dbo].[Patient] (
      [PatientId],
      [ClientId], 
      [FirstName],
      [LastName],
      [MedicalRecordNbr]
  ) VALUES (
      1,
      123,
      'Some',
      'Dude',
      'A12345'
  );
  
  INSERT INTO [dbo].[AssessmentType] (
      [AssessmentTypeCd],
      [AssessmentTypeShort],  
      [AssessmentTypeLong]
  ) VALUES (
      1,
      'Sample',
      'Sample Chart'
  );
  
  INSERT INTO [dbo].[EmrSystem] (
      [ID],
      [Name], 
      [Created],
      [Modified]
  ) VALUES (
      1,
      'Some System',
      GETDATE(),
      GETDATE()
  );
  
  INSERT INTO [dbo].[ClientEmrSystem] (
      [ClientId], 
      [EmrSystemId],
      [Created],
      [Modified]
  ) VALUES (
      123,
      1,
      GETDATE(),
      GETDATE()
  );  
  
  INSERT INTO [dbo].[AssessmentLog] (
      [ClientID],
      [PatientID],
      [AssessmentTypeCd],
      [Note],
      [Void],
      [DateInserted],
      [DateCharged]
  ) VALUES (
      123,
      1,
      1,
      'Sample notes',
      0,
      GETDATE(),
      NULL
  );
  </code></pre>
  
  <p>Oddly, when using the EMR System filter, the fields under the <code>Client</code> association are not limited either. It returns everything. I tried adjusting the contain[] array to include the limited fields, but everything is ignored.</p>
  
  <p>I'm assuming I did something wrong and its not Cake's fault, but I can't seem to figure out an elegant solution. Thank you for any help :) It is greatly appreciated. </p>