diff --git a/lib/manager/composer/extract.js b/lib/manager/composer/extract.js
index 7b0fc76580719ffe723c3bf853cd3993de165169..4d62f63cc86f9f56895f095318e982c0ab30721f 100644
--- a/lib/manager/composer/extract.js
+++ b/lib/manager/composer/extract.js
@@ -4,7 +4,7 @@ module.exports = {
   extractDependencies,
 };
 
-function extractDependencies(content, packageFile) {
+async function extractDependencies(content, packageFile) {
   logger.debug('composer.extractDependencies()');
   let packageJson;
   try {
@@ -50,5 +50,14 @@ function extractDependencies(content, packageFile) {
   if (!deps.length) {
     return null;
   }
-  return { deps };
+  let composerLock = false;
+  const filePath = packageFile.replace(/\.json$/, '.lock');
+  if (await platform.getFile(filePath)) {
+    logger.debug(
+      { packageFile: packageFile.packageFile },
+      'Found composer.lock'
+    );
+    composerLock = filePath;
+  }
+  return { deps, composerLock };
 }
diff --git a/lib/manager/composer/index.js b/lib/manager/composer/index.js
index 9fd44f840d937f71850f246879fbcbfc9b91fd34..5d7233f2472d3e7c128fcceb0d15d11f02868449 100644
--- a/lib/manager/composer/index.js
+++ b/lib/manager/composer/index.js
@@ -1,10 +1,12 @@
 const { extractDependencies } = require('./extract');
 const { updateDependency } = require('../npm/update');
+const { getLockFile } = require('./lock-file');
 
 const language = 'php';
 
 module.exports = {
   extractDependencies,
+  getLockFile,
   language,
   updateDependency,
   // TODO: support this
diff --git a/lib/manager/composer/lock-file.js b/lib/manager/composer/lock-file.js
new file mode 100644
index 0000000000000000000000000000000000000000..003fa92e37c1dec447d51c40c5716c5c68c383de
--- /dev/null
+++ b/lib/manager/composer/lock-file.js
@@ -0,0 +1,69 @@
+const { exec } = require('child-process-promise');
+const fs = require('fs-extra');
+const tmp = require('tmp-promise');
+const upath = require('upath');
+
+module.exports = {
+  getLockFile,
+};
+
+async function getLockFile(
+  packageFileName,
+  updatedDeps,
+  newPackageFileContent
+) {
+  logger.debug(`composer.getLockFile(${packageFileName})`);
+  const composerLockPath = packageFileName.replace(/\.json$/, '.lock');
+  const existingComposerLockContent = await platform.getFile(composerLockPath);
+  if (!existingComposerLockContent) {
+    logger.debug('No composer.lock found');
+    return null;
+  }
+  const tmpDir = await tmp.dir({ unsafeCleanup: true });
+  let stdout;
+  let stderr;
+  try {
+    const composerJsonFileName = upath.join(tmpDir.path, 'composer.json');
+    await fs.outputFile(composerJsonFileName, newPackageFileContent);
+    const composerLockFileName = upath.join(tmpDir.path, 'composer.lock');
+    await fs.outputFile(composerLockFileName, existingComposerLockContent);
+    const env = { HOME: process.env.HOME, PATH: process.env.PATH };
+    const startTime = process.hrtime();
+    const cmd = ('composer update ' + updatedDeps.join(' ')).trim();
+    logger.debug({ cmd });
+    ({ stdout, stderr } = await exec(cmd, {
+      cwd: tmpDir.path,
+      shell: true,
+      env,
+    }));
+    logger.debug(`composer stdout:\n${stdout}`);
+    logger.debug(`composer stderr:\n${stderr}`);
+    const duration = process.hrtime(startTime);
+    const seconds = Math.round(duration[0] + duration[1] / 1e9);
+    const newComposerLockContent = await fs.readFile(
+      composerLockFileName,
+      'utf8'
+    );
+    logger.info(
+      { seconds, type: 'composer.lock', stdout, stderr },
+      'Generated lockfile'
+    );
+    if (newComposerLockContent === existingComposerLockContent) {
+      logger.debug('composer.lock is unchanged');
+      return null;
+    }
+    logger.debug('Returning updated composer.lock');
+    return {
+      name: composerLockPath,
+      contents: newComposerLockContent,
+    };
+  } catch (err) {
+    logger.warn(
+      { err, message: err.message },
+      'Failed to generate composer.lock'
+    );
+    return null;
+  } finally {
+    tmpDir.cleanup();
+  }
+}
diff --git a/lib/workers/branch/get-updated.js b/lib/workers/branch/get-updated.js
index cf26300da395fc8a6ae27c11f21f6628d543a7bd..bb58f945470d6e381a72e267975fd71a466c0bbb 100644
--- a/lib/workers/branch/get-updated.js
+++ b/lib/workers/branch/get-updated.js
@@ -8,9 +8,15 @@ async function getUpdatedPackageFiles(config) {
   logger.debug('manager.getUpdatedPackageFiles()');
   logger.trace({ config });
   const updatedFileContents = {};
+  const packageFileManagers = {};
+  const packageFileUpdatedDeps = {};
 
   for (const upgrade of config.upgrades) {
-    const { manager, packageFile } = upgrade;
+    const { manager, packageFile, depName } = upgrade;
+    packageFileManagers[packageFile] = manager;
+    packageFileUpdatedDeps[packageFile] =
+      packageFileUpdatedDeps[packageFile] || [];
+    packageFileUpdatedDeps[packageFile].push(depName);
     if (upgrade.updateType !== 'lockFileMaintenance') {
       const existingContent =
         updatedFileContents[packageFile] ||
@@ -46,8 +52,25 @@ async function getUpdatedPackageFiles(config) {
     name,
     contents: updatedFileContents[name],
   }));
+  const updatedLockFiles = [];
+  for (const packageFile of updatedPackageFiles) {
+    const manager = packageFileManagers[packageFile.name];
+    const updatedDeps = packageFileUpdatedDeps[packageFile.name];
+    const getLockFile = get(manager, 'getLockFile');
+    if (getLockFile) {
+      const updatedLockFile = await getLockFile(
+        packageFile.name,
+        updatedDeps,
+        packageFile.contents
+      );
+      if (updatedLockFile) {
+        updatedLockFiles.push(updatedLockFile);
+      }
+    }
+  }
   return {
     parentBranch: config.parentBranch, // Need to overwrite original config
     updatedPackageFiles,
+    updatedLockFiles,
   };
 }
diff --git a/test/manager/composer/__snapshots__/extract.spec.js.snap b/test/manager/composer/__snapshots__/extract.spec.js.snap
index 0ca7e75d761eb8addc22ed6e187f2b69ab9325e0..1cc39fd69b4abfe1abca5ef06299cf36f0fe1585 100644
--- a/test/manager/composer/__snapshots__/extract.spec.js.snap
+++ b/test/manager/composer/__snapshots__/extract.spec.js.snap
@@ -1,7 +1,258 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`lib/manager/pip_requirements/extract extractDependencies() extracts dependencies 1`] = `
+exports[`lib/manager/composer/extract extractDependencies() extracts dependencies with lock file 1`] = `
 Object {
+  "composerLock": "composer.lock",
+  "deps": Array [
+    Object {
+      "currentValue": ">=5.3.2",
+      "depName": "php",
+      "depType": "require",
+      "purl": "pkg:packagist/php",
+      "skipReason": "unsupported",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "symfony/assetic-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/symfony/assetic-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "symfony/monolog-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/symfony/monolog-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "symfony/swiftmailer-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/symfony/swiftmailer-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "2.1.*",
+      "depName": "symfony/symfony",
+      "depType": "require",
+      "purl": "pkg:packagist/symfony/symfony",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "2.2.2",
+      "depName": "doctrine/common",
+      "depType": "require",
+      "purl": "pkg:packagist/doctrine/common",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "doctrine/doctrine-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/doctrine/doctrine-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "doctrine/doctrine-fixtures-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/doctrine/doctrine-fixtures-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "2.2.x-dev",
+      "depName": "doctrine/orm",
+      "depType": "require",
+      "purl": "pkg:packagist/doctrine/orm",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "exercise/elastica-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/exercise/elastica-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "friendsofsymfony/rest-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/friendsofsymfony/rest-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "*",
+      "depName": "friendsofsymfony/user-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/friendsofsymfony/user-bundle",
+      "skipReason": "any-version",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "*",
+      "depName": "fzaninotto/faker",
+      "depType": "require",
+      "purl": "pkg:packagist/fzaninotto/faker",
+      "skipReason": "any-version",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "1.0.1",
+      "depName": "jms/di-extra-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/jms/di-extra-bundle",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "*",
+      "depName": "jms/payment-core-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/jms/payment-core-bundle",
+      "skipReason": "any-version",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "1.1.0",
+      "depName": "jms/security-extra-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/jms/security-extra-bundle",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "knplabs/knp-menu-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/knplabs/knp-menu-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "knplabs/knp-paginator-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/knplabs/knp-paginator-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "liip/imagine-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/liip/imagine-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "merk/dough-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/merk/dough-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "sensio/distribution-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/sensio/distribution-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "sensio/framework-extra-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/sensio/framework-extra-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "sensio/generator-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/sensio/generator-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "simplethings/entity-audit-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/simplethings/entity-audit-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "stof/doctrine-extensions-bundle",
+      "depType": "require",
+      "purl": "pkg:packagist/stof/doctrine-extensions-bundle",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "dev-master",
+      "depName": "twig/extensions",
+      "depType": "require",
+      "purl": "pkg:packagist/twig/extensions",
+      "skipReason": "unsupported-constraint",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "2.3.*",
+      "depName": "behat/behat",
+      "depType": "require-dev",
+      "purl": "pkg:packagist/behat/behat",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "*",
+      "depName": "behat/behat-bundle",
+      "depType": "require-dev",
+      "purl": "pkg:packagist/behat/behat-bundle",
+      "skipReason": "any-version",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "*",
+      "depName": "behat/mink-bundle",
+      "depType": "require-dev",
+      "purl": "pkg:packagist/behat/mink-bundle",
+      "skipReason": "any-version",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "*",
+      "depName": "behat/sahi-client",
+      "depType": "require-dev",
+      "purl": "pkg:packagist/behat/sahi-client",
+      "skipReason": "any-version",
+      "versionScheme": "semverComposer",
+    },
+    Object {
+      "currentValue": "*",
+      "depName": "behat/common-contexts",
+      "depType": "require-dev",
+      "purl": "pkg:packagist/behat/common-contexts",
+      "skipReason": "any-version",
+      "versionScheme": "semverComposer",
+    },
+  ],
+}
+`;
+
+exports[`lib/manager/composer/extract extractDependencies() extracts dependencies with no lock file 1`] = `
+Object {
+  "composerLock": false,
   "deps": Array [
     Object {
       "currentValue": ">=5.3.2",
diff --git a/test/manager/composer/extract.spec.js b/test/manager/composer/extract.spec.js
index 62869a20549afacfc6d2e370f37b8c1980e3625f..cf4a7e5e01155255ac1a6ee57262ac5246699ab2 100644
--- a/test/manager/composer/extract.spec.js
+++ b/test/manager/composer/extract.spec.js
@@ -8,20 +8,25 @@ const requirements1 = fs.readFileSync(
   'utf8'
 );
 
-describe('lib/manager/pip_requirements/extract', () => {
+describe('lib/manager/composer/extract', () => {
   describe('extractDependencies()', () => {
-    let config;
+    let packageFile;
     beforeEach(() => {
-      config = {};
+      packageFile = 'composer.json';
     });
-    it('returns null for invalid json', () => {
-      expect(extractDependencies('nothing here', config)).toBe(null);
+    it('returns null for invalid json', async () => {
+      expect(await extractDependencies('nothing here', packageFile)).toBe(null);
     });
-    it('returns null for empty deps', () => {
-      expect(extractDependencies('{}', config)).toBe(null);
+    it('returns null for empty deps', async () => {
+      expect(await extractDependencies('{}', packageFile)).toBe(null);
     });
-    it('extracts dependencies', () => {
-      const res = extractDependencies(requirements1, config);
+    it('extracts dependencies with no lock file', async () => {
+      const res = await extractDependencies(requirements1, packageFile);
+      expect(res).toMatchSnapshot();
+    });
+    it('extracts dependencies with lock file', async () => {
+      platform.getFile.mockReturnValueOnce('some content');
+      const res = await extractDependencies(requirements1, packageFile);
       expect(res).toMatchSnapshot();
     });
   });
diff --git a/test/manager/composer/lock-file.spec.js b/test/manager/composer/lock-file.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..95d52b4cf919f252e4b5a563d976fe655768f749
--- /dev/null
+++ b/test/manager/composer/lock-file.spec.js
@@ -0,0 +1,42 @@
+jest.mock('fs-extra');
+jest.mock('child-process-promise');
+
+const fs = require('fs-extra');
+const { exec } = require('child-process-promise');
+const composer = require('../../../lib/manager/composer/lock-file');
+
+describe('.getLockFile()', () => {
+  beforeEach(() => {
+    jest.resetAllMocks();
+  });
+  it('returns if no composer.lock found', async () => {
+    expect(await composer.getLockFile('composer.json', [], '{}')).toBeNull();
+  });
+  it('returns null if unchanged', async () => {
+    platform.getFile.mockReturnValueOnce('Current composer.lock');
+    exec.mockReturnValueOnce({
+      stdout: '',
+      stderror: '',
+    });
+    fs.readFile = jest.fn(() => 'Current composer.lock');
+    expect(await composer.getLockFile('composer.json', [], '{}')).toBeNull();
+  });
+  it('returns updated composer.lock', async () => {
+    platform.getFile.mockReturnValueOnce('Current composer.lock');
+    exec.mockReturnValueOnce({
+      stdout: '',
+      stderror: '',
+    });
+    fs.readFile = jest.fn(() => 'New composer.lock');
+    expect(
+      await composer.getLockFile('composer.json', [], '{}')
+    ).not.toBeNull();
+  });
+  it('catches errors', async () => {
+    platform.getFile.mockReturnValueOnce('Current composer.lock');
+    fs.outputFile = jest.fn(() => {
+      throw new Error('not found');
+    });
+    expect(await composer.getLockFile('composer.json', [], '{}')).toBeNull();
+  });
+});
diff --git a/test/workers/branch/__snapshots__/get-updated.spec.js.snap b/test/workers/branch/__snapshots__/get-updated.spec.js.snap
index 6cb392e1064cffd86f9ff85e1e145d4212bf910c..8ac0c1c993f472ce5e6caccccbebfe61b7f3c3e4 100644
--- a/test/workers/branch/__snapshots__/get-updated.spec.js.snap
+++ b/test/workers/branch/__snapshots__/get-updated.spec.js.snap
@@ -3,6 +3,7 @@
 exports[`workers/branch/get-updated getUpdatedPackageFiles() handles content change 1`] = `
 Object {
   "parentBranch": undefined,
+  "updatedLockFiles": Array [],
   "updatedPackageFiles": Array [
     Object {
       "contents": "some new content",
@@ -15,6 +16,25 @@ Object {
 exports[`workers/branch/get-updated getUpdatedPackageFiles() handles empty 1`] = `
 Object {
   "parentBranch": undefined,
+  "updatedLockFiles": Array [],
   "updatedPackageFiles": Array [],
 }
 `;
+
+exports[`workers/branch/get-updated getUpdatedPackageFiles() handles lock files 1`] = `
+Object {
+  "parentBranch": undefined,
+  "updatedLockFiles": Array [
+    Object {
+      "contents": "some contents",
+      "name": "composer.json",
+    },
+  ],
+  "updatedPackageFiles": Array [
+    Object {
+      "contents": "some new content",
+      "name": "undefined",
+    },
+  ],
+}
+`;
diff --git a/test/workers/branch/get-updated.spec.js b/test/workers/branch/get-updated.spec.js
index 744ea0f1d5905e4b4fce335a483b3ae94713ec24..859380b14f8e6a7711aae4f619b1e31b67d89a75 100644
--- a/test/workers/branch/get-updated.spec.js
+++ b/test/workers/branch/get-updated.spec.js
@@ -1,3 +1,4 @@
+const composer = require('../../../lib/manager/composer');
 const npm = require('../../../lib/manager/npm');
 const {
   getUpdatedPackageFiles,
@@ -12,6 +13,8 @@ describe('workers/branch/get-updated', () => {
         ...defaultConfig,
         upgrades: [],
       };
+      composer.updateDependency = jest.fn();
+      composer.getLockFile = jest.fn();
       npm.updateDependency = jest.fn();
     });
     it('handles empty', async () => {
@@ -40,5 +43,18 @@ describe('workers/branch/get-updated', () => {
       const res = await getUpdatedPackageFiles(config);
       expect(res).toMatchSnapshot();
     });
+    it('handles lock files', async () => {
+      config.parentBranch = 'some-branch';
+      config.upgrades.push({
+        manager: 'composer',
+      });
+      composer.updateDependency.mockReturnValue('some new content');
+      composer.getLockFile.mockReturnValue({
+        name: 'composer.json',
+        contents: 'some contents',
+      });
+      const res = await getUpdatedPackageFiles(config);
+      expect(res).toMatchSnapshot();
+    });
   });
 });