├── tests
└── .gitkeep
├── .gitignore
├── .travis.yml
├── provides.json
├── src
├── Doctrine2Bridge
│ ├── Exception
│ │ ├── Configuration.php
│ │ └── ImplementationNotFound.php
│ ├── Support
│ │ ├── Facades
│ │ │ ├── Doctrine2.php
│ │ │ ├── Doctrine2Cache.php
│ │ │ └── Doctrine2Repository.php
│ │ └── Repository.php
│ ├── Console
│ │ ├── Generators
│ │ │ ├── All.php
│ │ │ ├── Proxies.php
│ │ │ ├── Repositories.php
│ │ │ └── Entities.php
│ │ └── Schema
│ │ │ ├── Create.php
│ │ │ ├── Drop.php
│ │ │ ├── Validate.php
│ │ │ └── Update.php
│ ├── EventListeners
│ │ └── TablePrefix.php
│ ├── Logger
│ │ └── Laravel.php
│ ├── Doctrine2CacheBridgeServiceProvider.php
│ ├── Auth
│ │ └── Doctrine2UserProvider.php
│ ├── Utils
│ │ └── JsonSerializer.php
│ └── Doctrine2BridgeServiceProvider.php
└── config
│ ├── d2bcache.php
│ └── d2bdoctrine.php
├── examples
└── auth
│ ├── doctrine2bridge-auth-closure.php
│ ├── Entities.User.dcm.xml
│ └── User.php
├── phpunit.xml
├── composer.json
├── LICENSE
├── bin
└── d2b-doctrine2
└── README.md
/tests/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | composer.phar
3 | composer.lock
4 | .DS_Store
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.3
5 | - 5.4
6 | - 5.5
7 |
8 | before_script:
9 | - curl -s http://getcomposer.org/installer | php
10 | - php composer.phar install --dev
11 |
12 | script: phpunit
--------------------------------------------------------------------------------
/provides.json:
--------------------------------------------------------------------------------
1 | {
2 | "providers": [
3 | "Doctrine2Bridge\Doctrine2CacheBridgeServiceProvider",
4 | "Doctrine2Bridge\Doctrine2BridgeServiceProvider"
5 | ]
6 | // aliases are set uo automatically by the service providers as follows:
7 | //
8 | // D2Cache -> Doctrine2Bridge\Support\Facades\Doctrine2Cache
9 | // D2EM -> Doctrine2Bridge\Support\Facades\Doctrine2
10 | }
11 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Exception/Configuration.php:
--------------------------------------------------------------------------------
1 |
9 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
10 | * @license MIT
11 | */
12 | class Configuration extends \Exception {
13 |
14 | public function __construct( $message = null, $code = 0, Exception $previous = null )
15 | {
16 | return parent::__construct(
17 | $message, $code, $previous
18 | );
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/examples/auth/doctrine2bridge-auth-closure.php:
--------------------------------------------------------------------------------
1 | 'doctrine2bridge'
6 |
7 | // this assumes no namespace:
8 |
9 | Auth::extend( 'doctrine2bridge', function()
10 | {
11 | return new \Illuminate\Auth\Guard(
12 | new \Doctrine2Bridge\Auth\Doctrine2UserProvider(
13 | D2EM::getRepository( '\Entities\User' ),
14 | new \Illuminate\Hashing\BcryptHasher
15 | ),
16 | App::make('session.store')
17 | );
18 | });
19 |
20 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 | ./tests/
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Exception/ImplementationNotFound.php:
--------------------------------------------------------------------------------
1 |
9 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
10 | * @license MIT
11 | */
12 | class ImplementationNotFound extends \Exception {
13 |
14 | public function __construct( $message = null, $code = 0, Exception $previous = null )
15 | {
16 | return parent::__construct(
17 | "No class / implementation found for {$message}", $code, $previous
18 | );
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Support/Facades/Doctrine2.php:
--------------------------------------------------------------------------------
1 |
12 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
13 | * @license MIT
14 | */
15 | class Doctrine2 extends Facade {
16 |
17 | /**
18 | * Get the registered name of the component.
19 | *
20 | * @return string
21 | */
22 | protected static function getFacadeAccessor() { return \Doctrine\ORM\EntityManagerInterface::class; }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Support/Facades/Doctrine2Cache.php:
--------------------------------------------------------------------------------
1 |
12 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
13 | * @license MIT
14 | */
15 | class Doctrine2Cache extends Facade {
16 |
17 | /**
18 | * Get the registered name of the component.
19 | *
20 | * @return string
21 | */
22 | protected static function getFacadeAccessor() { return \Doctrine\Common\Cache\Cache::class; }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Support/Facades/Doctrine2Repository.php:
--------------------------------------------------------------------------------
1 |
12 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
13 | * @license MIT
14 | */
15 | class Doctrine2Repository extends Facade {
16 |
17 | /**
18 | * Get the registered name of the component.
19 | *
20 | * @return string
21 | */
22 | protected static function getFacadeAccessor() { return '\Doctrine2Bridge\Support\Repository'; }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/examples/auth/Entities.User.dcm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "opensolutions/doctrine2bridge-l5",
3 | "description": "Adds the the power of Doctrine2 to Laravel 5 (with support for SQL logging and authentication)",
4 | "homepage": "https://github.com/opensolutions/doctrine2bridge-l5",
5 | "keywords": [ "laravel", "doctrine2" ],
6 | "license": "MIT",
7 | "authors": [
8 | {
9 | "name": "Barry O'Donovan",
10 | "email": "barry@opensolutions.ie",
11 | "homepage": "http://www.barryodonovan.com/",
12 | "role": "Developer"
13 | }
14 | ],
15 | "support": {
16 | "issues": "https://github.com/opensolutions/doctrine2bridge-l5/issues",
17 | "source": "https://github.com/opensolutions/doctrine2bridge-l5"
18 | },
19 | "require": {
20 | "php": ">=5.5.0",
21 | "doctrine/orm": ">=2.4.0"
22 | },
23 | "autoload": {
24 | "psr-0": {
25 | "Doctrine2Bridge": "src/"
26 | }
27 | },
28 | "bin": [ "bin/d2b-doctrine2" ]
29 | }
30 |
--------------------------------------------------------------------------------
/src/config/d2bcache.php:
--------------------------------------------------------------------------------
1 | 'Doctrine2',
30 |
31 | ];
32 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Support/Repository.php:
--------------------------------------------------------------------------------
1 |
13 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
14 | * @license MIT
15 | */
16 | class Repository {
17 |
18 | /**
19 | * The entity manager
20 | */
21 | private $d2em = null;
22 |
23 | public function __construct( \Doctrine\ORM\EntityManagerInterface $d2em )
24 | {
25 | $this->d2em = $d2em;
26 | }
27 |
28 | public function r( $repository, $namespace = null )
29 | {
30 | if( $namespace == null ) {
31 | if( strpos( $repository, '\\' ) === false )
32 | $repository = Config::get( 'd2bdoctrine.namespaces.models' ) . '\\' . $repository;
33 | } else {
34 | $repository = $namespace . '\\' . $repository;
35 | }
36 |
37 | return $this->d2em->getRepository( $repository );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Open Source Solutions Limited
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Console/Generators/All.php:
--------------------------------------------------------------------------------
1 |
19 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
20 | * @license MIT
21 | */
22 | class All extends LaravelCommand
23 | {
24 | /**
25 | * The console command name.
26 | *
27 | * @var string
28 | */
29 | protected $name = 'd2b:generate:all';
30 |
31 | /**
32 | * The console command description.
33 | *
34 | * @var string
35 | */
36 | protected $description = 'Generate all Doctrine2 entities, proxies and repositoies';
37 |
38 | public function fire()
39 | {
40 | $this->call( 'd2b:generate:entities' );
41 | $this->call( 'd2b:generate:proxies' );
42 | $this->call( 'd2b:generate:repositories' );
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/EventListeners/TablePrefix.php:
--------------------------------------------------------------------------------
1 |
12 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
13 | * @license MIT
14 | *
15 | * From https://github.com/mitchellvanw/laravel-doctrine/tree/master/src/EventListeners (MIT)
16 | */
17 | class TablePrefix
18 | {
19 | protected $prefix = '';
20 |
21 | /**
22 | * __construct
23 | *
24 | * @param string $prefix
25 | */
26 | public function __construct($prefix)
27 | {
28 | $this->prefix = (string) $prefix;
29 | }
30 |
31 | /**
32 | * loadClassMetadata
33 | *
34 | * @link http://doctrine-orm.readthedocs.org/en/latest/cookbook/sql-table-prefixes.html
35 | * @param LoadClassMetadataEventArgs $eventArgs
36 | */
37 | public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
38 | {
39 | $classMetadata = $eventArgs->getClassMetadata();
40 | $classMetadata->setTableName($this->prefix . $classMetadata->getTableName());
41 | //if we use sequences, also prefix the sequence name
42 | if($classMetadata->isIdGeneratorSequence()) {
43 | $sequenceDefinition = $classMetadata->sequenceGeneratorDefinition;
44 | $sequenceDefinition['sequenceName'] = $this->prefix . $sequenceDefinition['sequenceName'];
45 | $classMetadata->setSequenceGeneratorDefinition($sequenceDefinition);
46 | }
47 | foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
48 | if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY) {
49 | $mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
50 | $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName;
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/config/d2bdoctrine.php:
--------------------------------------------------------------------------------
1 | array(
20 | 'models' => app()->databasePath(), // entity namespace added by default
21 | 'proxies' => app()->databasePath() . '/Proxies',
22 | 'repositories' => app()->databasePath(), // repository namespace added by default
23 | 'xml_schema' => app()->databasePath() . '/xml'
24 | ),
25 |
26 | // set to true to have Doctrine2 generate proxies on the fly. Not recommended in a production system.
27 | 'autogen_proxies' => env('APP_DEBUG'),
28 |
29 | // Namespaces for entities, proxies and repositories.
30 | 'namespaces' => array(
31 | 'models' => 'Entities',
32 | 'proxies' => 'Proxies',
33 | 'repositories' => 'Repositories'
34 | ),
35 |
36 | // Doctrine2Bridge includes an implementation of Doctrine\DBAL\Logging\SQLLogger which
37 | // just calls the Laravel Log facade. If you wish to log your SQL queries (and execution
38 | // time), just set enabled in the following to true.
39 | 'sqllogger' => array(
40 | 'enabled' => env('APP_DEBUG'),
41 | 'level' => 'debug' // one of debug, info, notice, warning, error, critical, alert
42 | ),
43 |
44 | // use Doctrine2bridge with Laravel's authentication menchanism
45 | // see: https://github.com/opensolutions/doctrine2bridge/wiki/Auth
46 | 'auth' => array(
47 | 'enabled' => false,
48 | 'entity' => '\Entities\User' // the Doctrine2 entity representing the user
49 | )
50 | ];
51 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Logger/Laravel.php:
--------------------------------------------------------------------------------
1 |
7 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
8 | * @license MIT
9 | */
10 |
11 | namespace Doctrine2Bridge\Logger;
12 |
13 | /**
14 | * Includes executed SQLs in a Debug Stack.
15 | *
16 | * @link www.doctrine-project.org
17 | * @since 2.0
18 | * @author Benjamin Eberlei
19 | * @author Guilherme Blanco
20 | * @author Jonathan Wage
21 | * @author Roman Borschel
22 | */
23 | class Laravel implements \Doctrine\DBAL\Logging\SQLLogger
24 | {
25 | /**
26 | * If the logger is enabled (log queries) or not.
27 | *
28 | * @var boolean
29 | */
30 | public $enabled = true;
31 |
32 | /**
33 | * For timing queries:
34 | * @var float|null
35 | */
36 | public $start = null;
37 |
38 | /**
39 | * Query
40 | */
41 | public $query = null;
42 |
43 | /**
44 | * Logging level.
45 | *
46 | * Available: debug, info, notice, warning, error, critical, and alert
47 | *
48 | * @see http://laravel.com/docs/errors#logging
49 | */
50 | public $level = 'debug';
51 |
52 | /**
53 | * {@inheritdoc}
54 | */
55 | public function startQuery($sql, array $params = null, array $types = null)
56 | {
57 | if( $this->enabled )
58 | {
59 | $this->start = microtime(true);
60 |
61 | $this->query = array( 'sql' => $sql, 'params' => $params, 'types' => $types );
62 | }
63 | }
64 |
65 | /**
66 | * {@inheritdoc}
67 | */
68 | public function stopQuery()
69 | {
70 | if( $this->enabled )
71 | {
72 | $level = $this->level;
73 |
74 | \Log::$level(
75 | 'D2 SQL: '
76 | . $this->query['sql']
77 | . " [Executed in " . ( microtime(true) - $this->start ) . "secs.] ",
78 | array( 'params' => $this->query['params'], 'types' => $this->query['types'] )
79 | );
80 | }
81 | }
82 |
83 | /**
84 | * Set the debugging level
85 | *
86 | * @param string $level One of: debug, info, notice, warning, error, critical, and alert
87 | */
88 | public function setLevel( $level )
89 | {
90 | $this->level = $level;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Console/Schema/Create.php:
--------------------------------------------------------------------------------
1 |
21 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
22 | * @license MIT
23 | */
24 | class Create extends LaravelCommand
25 | {
26 | /**
27 | * The console command name.
28 | *
29 | * @var string
30 | */
31 | protected $name = 'd2b:schema:create';
32 |
33 | /**
34 | * The console command description.
35 | *
36 | * @var string
37 | */
38 | protected $description = 'Create the database schema from models';
39 |
40 |
41 | /**
42 | * The schema tool.
43 | *
44 | * @var \Doctrine\ORM\Tools\SchemaTool
45 | */
46 | private $tool;
47 |
48 | /**
49 | * The class metadata factory
50 | *
51 | * @var \Doctrine\ORM\Tools\SchemaTool
52 | */
53 | private $metadata;
54 |
55 | public function __construct(SchemaTool $tool, ClassMetadataFactory $metadata)
56 | {
57 | parent::__construct();
58 | $this->tool = $tool;
59 | $this->metadata = $metadata;
60 | }
61 |
62 |
63 | public function fire()
64 | {
65 | if( $this->option('sql') ) {
66 | $this->info('Outputting create query:' . PHP_EOL);
67 |
68 | $sql = $this->tool->getCreateSchemaSql($this->metadata->getAllMetadata());
69 | $this->info(implode(';'.PHP_EOL, $sql) . ';');
70 |
71 | } else if( $this->option('commit') ) {
72 | $this->info('Creating database schema...');
73 | $this->tool->createSchema($this->metadata->getAllMetadata());
74 | $this->info('Schema has been created!');
75 | } else {
76 | $this->comment( "Warning: this command can cause data loss. Run with --sql or --commit." );
77 | }
78 | }
79 |
80 | protected function getOptions()
81 | {
82 | return [
83 | ['sql', false, InputOption::VALUE_NONE, 'Dumps SQL query and does not execute creation.'],
84 | ['commit', false, InputOption::VALUE_NONE, 'Executes database schema creation.']
85 | ];
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Console/Schema/Drop.php:
--------------------------------------------------------------------------------
1 |
21 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
22 | * @license MIT
23 | */
24 | class Drop extends LaravelCommand
25 | {
26 | /**
27 | * The console command name.
28 | *
29 | * @var string
30 | */
31 | protected $name = 'd2b:schema:drop';
32 |
33 | /**
34 | * The console command description.
35 | *
36 | * @var string
37 | */
38 | protected $description = 'Drop the database schema';
39 |
40 |
41 | /**
42 | * The schema tool.
43 | *
44 | * @var \Doctrine\ORM\Tools\SchemaTool
45 | */
46 | private $tool;
47 |
48 | /**
49 | * The class metadata factory
50 | *
51 | * @var \Doctrine\ORM\Tools\SchemaTool
52 | */
53 | private $metadata;
54 |
55 | public function __construct(SchemaTool $tool, ClassMetadataFactory $metadata)
56 | {
57 | parent::__construct();
58 | $this->tool = $tool;
59 | $this->metadata = $metadata;
60 | }
61 |
62 |
63 | public function fire()
64 | {
65 | $sql = $this->tool->getDropSchemaSQL($this->metadata->getAllMetadata());
66 |
67 | if( empty($sql) ) {
68 | $this->error('Current models do not exist in schema.');
69 | return;
70 | }
71 |
72 | if( $this->option('sql') ) {
73 | $this->info('Outputting drop query:'.PHP_EOL);
74 | $this->line(implode(';' . PHP_EOL, $sql) . ';');
75 | } else if( $this->option('commit') ) {
76 | $this->info('Dropping database schema....');
77 | $this->tool->dropSchema($this->metadata->getAllMetadata());
78 | $this->info('Schema has been dropped!');
79 | } else {
80 | $this->comment( "Warning: this command can cause data loss. Run with --sql or --commit." );
81 | }
82 | }
83 |
84 | protected function getOptions()
85 | {
86 | return [
87 | ['sql', false, InputOption::VALUE_NONE, 'Dumps SQL query and does not execute drop.'],
88 | ['commit', false, InputOption::VALUE_NONE, 'Executes database schema drop.']
89 | ];
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/bin/d2b-doctrine2:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
8 | * @copyright Copyright (c) 2014 Open Source Solutions Limited
9 | * @license MIT
10 | */
11 |
12 |
13 | mb_internal_encoding('UTF-8');
14 | mb_language('uni');
15 |
16 | require __DIR__.'/../../../../bootstrap/autoload.php';
17 | $app = require_once __DIR__.'/../../../../bootstrap/app.php';
18 | $kernel = $app->make('Illuminate\Contracts\Console\Kernel');
19 | $kernel->bootstrap();
20 |
21 | use Symfony\Component\Console\Helper\DialogHelper;
22 | use Symfony\Component\Console\Helper\HelperSet;
23 | use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper;
24 | use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
25 | use Doctrine\ORM\Tools\Console\ConsoleRunner;
26 |
27 | use Doctrine\DBAL\Migrations\Configuration\Configuration;
28 | use Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand;
29 | use Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand;
30 | use Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand;
31 | use Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand;
32 | use Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand;
33 | use Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand;
34 |
35 | $d2cache = $app->make( Doctrine\Common\Cache\Cache::class );
36 | $d2em = $app->make( Doctrine\ORM\EntityManagerInterface::class );
37 |
38 | $helperSet = new HelperSet( array(
39 | 'db' => new ConnectionHelper( $d2em->getConnection() ),
40 | 'em' => new EntityManagerHelper( $d2em ),
41 | 'dialog' => new DialogHelper(),
42 | ));
43 |
44 | $cli = new \Symfony\Component\Console\Application( 'Doctrine Command Line Interface', Doctrine\Common\Version::VERSION );
45 | $cli->setCatchExceptions(true);
46 |
47 | // from http://docs.doctrine-project.org/projects/doctrine-migrations/en/latest/reference/introduction.html
48 | $cli->addCommands( array(
49 | // Migrations Commands
50 | new \Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand(),
51 | new \Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand(),
52 | new \Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand(),
53 | new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand(),
54 | new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand(),
55 | new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand()
56 | ));
57 |
58 | Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands( $cli );
59 |
60 | $helpers = $cli->getHelperSet();
61 | foreach ($helperSet as $name => $helper) {
62 | $helpers->set($helper, $name);
63 | }
64 |
65 | D2Cache::flushAll();
66 |
67 | $cli->run();
68 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Console/Generators/Proxies.php:
--------------------------------------------------------------------------------
1 |
22 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
23 | * @license MIT
24 | */
25 | class Proxies extends LaravelCommand
26 | {
27 | /**
28 | * The console command name.
29 | *
30 | * @var string
31 | */
32 | protected $name = 'd2b:generate:proxies';
33 |
34 | /**
35 | * The console command description.
36 | *
37 | * @var string
38 | */
39 | protected $description = 'Generate Doctrine2 proxies for entities.';
40 |
41 | /**
42 | * The Entity Manager
43 | *
44 | * @var \Doctrine\ORM\EntityManagerInterface
45 | */
46 | private $d2em;
47 |
48 | public function __construct(\Doctrine\ORM\EntityManagerInterface $d2em)
49 | {
50 | parent::__construct();
51 |
52 | $this->d2em = $d2em;
53 | }
54 |
55 | public function fire()
56 | {
57 | $this->info('Starting proxy generation....');
58 |
59 | // flush all generated and cached entities, etc
60 | \D2Cache::flushAll();
61 |
62 | try {
63 | $metadata = $this->d2em->getMetadataFactory()->getAllMetadata();
64 | } catch( \Doctrine\Common\Persistence\Mapping\MappingException $e ) {
65 | if( $this->option( 'verbose' ) == 3 )
66 | throw $e;
67 |
68 | $this->error( "Caught Doctrine\Common\Persistence\Mapping\MappingException: " . $e->getMessage() );
69 | $this->info( "Re-optimizing:" );
70 | $this->call( 'optimize' );
71 | $this->comment( "*** You must now rerun this artisan command ***" );
72 | exit(-1);
73 | }
74 |
75 | if( empty($metadata) ) {
76 | $this->error('No metadata found to generate entities.');
77 | return -1;
78 | }
79 |
80 | $directory = Config::get( 'd2bdoctrine.paths.proxies' );
81 |
82 | if( !$directory ) {
83 | $this->error('The proxy directory has not been set.');
84 | return -1;
85 | }
86 |
87 | $this->info('Processing entities:');
88 | foreach ($metadata as $item) {
89 | $this->line($item->name);
90 | }
91 |
92 | $this->d2em->getProxyFactory()->generateProxyClasses($metadata, $directory);
93 | $this->info('Proxies have been created.');
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Console/Schema/Validate.php:
--------------------------------------------------------------------------------
1 |
21 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
22 | * @license MIT
23 | */
24 | class Validate extends LaravelCommand
25 | {
26 | /**
27 | * The console command name.
28 | *
29 | * @var string
30 | */
31 | protected $name = 'd2b:schema:validate';
32 |
33 | /**
34 | * The console command description.
35 | *
36 | * @var string
37 | */
38 | protected $description = 'Validate the database schema';
39 |
40 | public function fire( \Doctrine\ORM\EntityManagerInterface $d2em )
41 | {
42 | $validator = new SchemaValidator($d2em);
43 | $exit = 0;
44 |
45 | if( $this->option('skip-mapping') )
46 | {
47 | $this->comment( '[Mapping] Skipped mapping check.' );
48 | }
49 | elseif( $errors = $validator->validateMapping() )
50 | {
51 | foreach( $errors as $className => $errorMessages )
52 | {
53 | $this->error( "[Mapping] FAIL - The entity-class '" . $className . "' mapping is invalid:" );
54 |
55 | foreach( $errorMessages as $errorMessage ) {
56 | $this->line( '* ' . $errorMessage );
57 | }
58 |
59 | $this->line();
60 | }
61 |
62 | $exit += 1;
63 | }
64 | else
65 | {
66 | $this->info( "[Mapping] OK - The mapping files are correct." );
67 | }
68 |
69 | if( $this->option( 'skip-sync' ) )
70 | {
71 | $this->comment( "[Database] SKIPPED - The database was not checked for synchronicity." );
72 | }
73 | elseif( !$validator->schemaInSyncWithMetadata() )
74 | {
75 | $this->error( "[Database] FAIL - The database schema is not in sync with the current mapping file." );
76 | $exit += 2;
77 | }
78 | else
79 | {
80 | $this->info( "[Database] OK - The database schema is in sync with the mapping files." );
81 | }
82 | }
83 |
84 | protected function getOptions()
85 | {
86 | return [
87 | [ 'skip-mapping', false, InputOption::VALUE_NONE, 'Skip the mapping validation check' ],
88 | [ 'skip-sync', false, InputOption::VALUE_NONE, 'Skip checking if the mapping is in sync with the database' ],
89 | ];
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Console/Schema/Update.php:
--------------------------------------------------------------------------------
1 |
21 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
22 | * @license MIT
23 | */
24 | class Update extends LaravelCommand
25 | {
26 | /**
27 | * The console command name.
28 | *
29 | * @var string
30 | */
31 | protected $name = 'd2b:schema:update';
32 |
33 | /**
34 | * The console command description.
35 | *
36 | * @var string
37 | */
38 | protected $description = 'Update the database schema';
39 |
40 |
41 | /**
42 | * The schema tool.
43 | *
44 | * @var \Doctrine\ORM\Tools\SchemaTool
45 | */
46 | private $tool;
47 |
48 | /**
49 | * The class metadata factory
50 | *
51 | * @var \Doctrine\ORM\Tools\SchemaTool
52 | */
53 | private $metadata;
54 |
55 | public function __construct(SchemaTool $tool, ClassMetadataFactory $metadata)
56 | {
57 | parent::__construct();
58 | $this->tool = $tool;
59 | $this->metadata = $metadata;
60 | }
61 |
62 |
63 | public function fire()
64 | {
65 |
66 | $this->info('Checking if database needs updating....');
67 |
68 | $sql = $this->tool->getUpdateSchemaSql( $this->metadata->getAllMetadata(), $this->option('clean') );
69 |
70 | if( empty($sql) ) {
71 | $this->info('No updates found.');
72 | return;
73 | }
74 |
75 | if( $this->option( 'sql' ) ) {
76 | $this->info('Outputting update query:');
77 | $this->info(implode(';' . PHP_EOL, $sql) .';');
78 | } else if( $this->option( 'commit' ) ) {
79 | $this->info('Updating database schema....');
80 | $this->tool->updateSchema($this->metadata->getAllMetadata());
81 | $this->info('Schema has been updated!');
82 | } else {
83 | $this->comment( "Warning: this command can cause data loss. Run with --sql or --commit." );
84 | }
85 | }
86 |
87 | protected function getOptions()
88 | {
89 | return [
90 | ['sql', false, InputOption::VALUE_NONE, 'Dumps SQL query and does not execute creation.'],
91 | ['commit', false, InputOption::VALUE_NONE, 'Executes database schema creation.'],
92 | ['clean', null, InputOption::VALUE_OPTIONAL, 'When using clean, models all non-relevant to current metadata will be cleared.']
93 |
94 | ];
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/examples/auth/User.php:
--------------------------------------------------------------------------------
1 | username = $username;
36 |
37 | return $this;
38 | }
39 |
40 | /**
41 | * Get username
42 | *
43 | * @return string
44 | */
45 | public function getUsername()
46 | {
47 | return $this->username;
48 | }
49 |
50 | /**
51 | * Set password
52 | *
53 | * @param string $password
54 | *
55 | * @return User
56 | */
57 | public function setPassword($password)
58 | {
59 | $this->password = $password;
60 |
61 | return $this;
62 | }
63 |
64 | /**
65 | * Get password
66 | *
67 | * @return string
68 | */
69 | public function getPassword()
70 | {
71 | return $this->password;
72 | }
73 |
74 | /**
75 | * Get id
76 | *
77 | * @return integer
78 | */
79 | public function getId()
80 | {
81 | return $this->id;
82 | }
83 |
84 |
85 |
86 | /**
87 | * Get the unique identifier for the user.
88 | *
89 | * Required as we implement `\Illuminate\Auth\UserInterface`
90 | *
91 | * @return mixed
92 | */
93 | public function getAuthIdentifier()
94 | {
95 | return $this->getId();
96 | }
97 |
98 | /**
99 | * Get the password for the user.
100 | *
101 | * Required as we implement `\Illuminate\Auth\UserInterface`
102 | *
103 | * @return string
104 | */
105 | public function getAuthPassword()
106 | {
107 | return $this->getPassword();
108 | }
109 |
110 |
111 | /**
112 | * Get the token value for the "remember me" session.
113 | *
114 | * @return string
115 | */
116 | public function getRememberToken()
117 | {
118 | return $this->remember_token;
119 | }
120 |
121 | /**
122 | * Set the token value for the "remember me" session.
123 | *
124 | * @param string $value
125 | * @return void
126 | */
127 | public function setRememberToken($value)
128 | {
129 | $this->remember_token = $value;
130 | }
131 |
132 | /**
133 | * Get the column name for the "remember me" token.
134 | *
135 | * @return string
136 | */
137 | public function getRememberTokenName()
138 | {
139 | return 'remember_token';
140 | }
141 |
142 |
143 | }
144 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Console/Generators/Repositories.php:
--------------------------------------------------------------------------------
1 |
26 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
27 | * @license MIT
28 | */
29 | class Repositories extends LaravelCommand
30 | {
31 | /**
32 | * The console command name.
33 | *
34 | * @var string
35 | */
36 | protected $name = 'd2b:generate:repositories';
37 |
38 | /**
39 | * The console command description.
40 | *
41 | * @var string
42 | */
43 | protected $description = 'Generate Doctrine2 repositories for the entities';
44 |
45 | /**
46 | * The Entity Manager
47 | *
48 | * @var \Doctrine\ORM\EntityManagerInterface
49 | */
50 | private $d2em;
51 |
52 | public function __construct(\Doctrine\ORM\EntityManagerInterface $d2em)
53 | {
54 | parent::__construct();
55 |
56 | $this->d2em = $d2em;
57 | }
58 |
59 | public function fire()
60 | {
61 | $this->info('Starting repository generation....');
62 |
63 | // flush all generated and cached entities, etc
64 | \D2Cache::flushAll();
65 |
66 | try {
67 | $metadatas = $this->d2em->getMetadataFactory()->getAllMetadata();
68 | } catch( \Doctrine\Common\Persistence\Mapping\MappingException $e ) {
69 | if( $this->option( 'verbose' ) == 3 )
70 | throw $e;
71 |
72 | $this->error( "Caught Doctrine\Common\Persistence\Mapping\MappingException: " . $e->getMessage() );
73 |
74 | $this->info( "Re-optimizing:" );
75 | $this->call( 'optimize' );
76 | $this->comment( "*** You must now rerun this artisan command ***" );
77 | exit(-1);
78 | }
79 |
80 | if( empty($metadatas) ) {
81 | $this->error('No metadata found to generate entities.');
82 | return -1;
83 | }
84 |
85 | $directory = Config::get( 'd2bdoctrine.paths.repositories' );
86 |
87 | if( !$directory ) {
88 | $this->error('The entity directory has not been set.');
89 | return -1;
90 | }
91 |
92 | $numRepositories = 0;
93 | $generator = new EntityRepositoryGenerator();
94 |
95 | foreach ($metadatas as $metadata) {
96 | if ($metadata->customRepositoryClassName) {
97 | $this->line( sprintf('Processing repository "%s"', $metadata->customRepositoryClassName) );
98 | $generator->writeEntityRepositoryClass($metadata->customRepositoryClassName, $directory);
99 | $numRepositories++;
100 | }
101 | }
102 |
103 | if ($numRepositories) {
104 | $this->info( 'Repositories have been created.');
105 | } else {
106 | $this->info('No Repository classes were found to be processed.' );
107 | }
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Doctrine2CacheBridgeServiceProvider.php:
--------------------------------------------------------------------------------
1 |
13 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
14 | * @license MIT
15 | */
16 | class Doctrine2CacheBridgeServiceProvider extends \Illuminate\Support\ServiceProvider
17 | {
18 |
19 | /**
20 | * Bootstrap the application events.
21 | *
22 | * @return void
23 | */
24 | public function boot()
25 | {
26 | // handle the publishing of configuration file
27 | $this->handleConfigs();
28 | }
29 |
30 |
31 | /**
32 | * Register the service provider.
33 | *
34 | * @return void
35 | */
36 | public function register()
37 | {
38 | $this->registerCache();
39 |
40 | // Shortcut so developers don't need to add an Alias in app/config/app.php
41 | \App::booting( function() {
42 | $loader = \Illuminate\Foundation\AliasLoader::getInstance();
43 | $loader->alias( 'D2Cache', 'Doctrine2Bridge\Support\Facades\Doctrine2Cache' );
44 | });
45 |
46 | }
47 |
48 |
49 | private function registerCache()
50 | {
51 | $this->app->singleton( Cache::class, function ($app) {
52 |
53 | $config = $this->laravelToDoctrineConfigMapper();
54 |
55 | $cacheClass = "\Doctrine\Common\Cache\\" . $config['type'];
56 |
57 | if(!class_exists($cacheClass))
58 | throw new Exception\ImplementationNotFound( $cacheClass );
59 |
60 | switch( $config['type'] )
61 | {
62 | case 'ArrayCache':
63 | $cache = new $cacheClass();
64 | break;
65 |
66 | case 'FilesystemCache':
67 | $cache = new $cacheClass( $config['dir'] );
68 | break;
69 |
70 | case 'MemcacheCache':
71 | $cache = new $cacheClass;
72 | $cache->setMemcache( $this->setupMemcache( $config ) );
73 | break;
74 | }
75 |
76 | if( Config::has( 'd2bcache.namespace') )
77 | $cache->setNamespace( Config::get( 'd2bcache.namespace') );
78 |
79 | return $cache;
80 | });
81 | }
82 |
83 | /**
84 | * Setup the standard PHP memcache object implementation
85 | */
86 | private function setupMemcache( $config )
87 | {
88 | $memcache = new \Memcache;
89 |
90 | if( !isset( $config['servers'] ) || !count( $config['servers'] ) )
91 | throw new Exception\Configuration( 'No servers defined for Memcache in config/cache.php' );
92 |
93 | foreach( $config['servers'] as $server )
94 | {
95 | $memcache->addServer(
96 | $server['host'],
97 | isset( $server['port'] ) ? $server['port'] : 11211,
98 | isset( $server['persistent'] ) ? $server['persistent'] : false,
99 | isset( $server['weight'] ) ? $server['weight'] : 1,
100 | isset( $server['timeout'] ) ? $server['timeout'] : 1,
101 | isset( $server['retry_int'] ) ? $server['retry_int'] : 15
102 | );
103 | }
104 |
105 | return $memcache;
106 | }
107 |
108 | /**
109 | * Publish the configuration file
110 | */
111 | private function handleConfigs() {
112 | $configPath = __DIR__ . '/../config/d2bcache.php';
113 | $this->publishes( [ $configPath => config_path('d2bcache.php') ] );
114 | $this->mergeConfigFrom( $configPath, 'd2bcache' );
115 | }
116 |
117 | /**
118 | * Convert Laravel5's cache configuration to something what Doctrine2's
119 | * cache providers can use.
120 | *
121 | * @return array
122 | */
123 | private function laravelToDoctrineConfigMapper()
124 | {
125 | switch( Config::get( 'cache.default' ) ) {
126 | case 'file':
127 | return [
128 | 'type' => 'FilesystemCache',
129 | 'dir' => Config::get( 'cache.stores.file.path' ) . DIRECTORY_SEPARATOR . 'doctine2.cache'
130 | ];
131 | break;
132 |
133 | case 'array':
134 | return [
135 | 'type' => 'ArrayCache',
136 | ];
137 | break;
138 |
139 | case 'memcached':
140 | return [
141 | 'type' => 'MemcacheCache',
142 | 'servers' => Config::get( 'cache.stores.memcached.servers' )
143 | ];
144 | break;
145 |
146 | default:
147 | throw new Exception\ImplementationNotFound( Config::get( 'cache.default' ) );
148 |
149 | }
150 | }
151 |
152 | }
153 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Auth/Doctrine2UserProvider.php:
--------------------------------------------------------------------------------
1 |
7 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
8 | * @license MIT
9 | */
10 |
11 | namespace Doctrine2Bridge\Auth;
12 |
13 | /**
14 | * Class to provide a Doctrine2 user object for Laravel authentication.
15 | */
16 | class Doctrine2UserProvider implements \Illuminate\Contracts\Auth\UserProvider
17 | {
18 | /**
19 | * The hasher implementation.
20 | *
21 | * @var \Illuminate\Hashing\HasherInterface
22 | */
23 | protected $hasher;
24 |
25 | /**
26 | * The repository (table) containing the users.
27 | *
28 | * @var \Doctrine\ORM\EntityRepository
29 | */
30 | protected $d2repository;
31 |
32 | /**
33 | * Create a new database user provider.
34 | *
35 | * @param \Doctrine\ORM\EntityRepository $d2repository The Doctrine2 repository (table) containing the users.
36 | * @param \Illuminate\Hashing\HasherInterface $hasher The hasher implementation
37 | * @return void
38 | */
39 | public function __construct( \Doctrine\ORM\EntityRepository $d2repository, \Illuminate\Contracts\Hashing\Hasher $hasher )
40 | {
41 | $this->d2repository = $d2repository;
42 | $this->hasher = $hasher;
43 | }
44 |
45 | /**
46 | * Retrieve a user by their unique identifier.
47 | *
48 | * @param mixed $identifier
49 | * @return \Illuminate\Auth\UserInterface|null
50 | */
51 | public function retrieveById( $identifier )
52 | {
53 | return $this->d2repository->find( $identifier );
54 | }
55 |
56 | /**
57 | * Retrieve a user by the given credentials.
58 | *
59 | * @param array $credentials
60 | * @return \Illuminate\Auth\UserInterface|null
61 | */
62 | public function retrieveByCredentials(array $credentials)
63 | {
64 | // First we will add each credential element to the query as a where clause.
65 | // Then we can execute the query and, if we found a user, return it in a
66 | // Doctrine2 "user" entity object that will be utilised by the Guard instances.
67 | $qb = $this->d2repository->createQueryBuilder( 'u' )
68 | ->select( 'u' )
69 | ->setMaxResults( 1 );
70 |
71 | $i = 1;
72 | foreach( $credentials as $key => $value )
73 | {
74 | if( !str_contains( $key, 'password' ) )
75 | {
76 | $qb->andWhere( "u.{$key} = ?{$i}" )
77 | ->setParameter( $i++, $value );
78 | }
79 | }
80 |
81 | // Now we are ready to execute the query to see if we have an user matching
82 | // the given credentials. If not, we will just return nulls and indicate
83 | // that there are no matching users for these given credential arrays.
84 | try
85 | {
86 | return $qb->getQuery()->getSingleResult();
87 | }
88 | catch( \Doctrine\ORM\NoResultException $e )
89 | {
90 | return null;
91 | }
92 | }
93 |
94 | /**
95 | * Validate a user against the given credentials.
96 | *
97 | * @param \Illuminate\Auth\UserInterface $user
98 | * @param array $credentials
99 | * @return bool
100 | */
101 | public function validateCredentials( \Illuminate\Contracts\Auth\Authenticatable $user, array $credentials )
102 | {
103 | $plain = $credentials['password'];
104 |
105 | return $this->hasher->check( $plain, $user->getAuthPassword() );
106 | }
107 |
108 |
109 | /**
110 | * Retrieve a user by their unique "remember me" token.
111 | *
112 | * @param mixed $identifier
113 | * @param string $token
114 | * @return \Illuminate\Auth\UserInterface|null
115 | */
116 | public function retrieveByToken( $identifier, $token )
117 | {
118 | try {
119 | return $this->d2repository
120 | ->createQueryBuilder( 'u' )
121 | ->setMaxResults( 1 )
122 | ->select( 'u' )
123 | ->andWhere( 'u.id = :id' )->setParameter( 'id', $identifier )
124 | ->andWhere( 'u.remember_token = :token' )->setParameter( 'token', $token )
125 | ->getQuery()
126 | ->getSingleResult();
127 | }
128 | catch( \Doctrine\ORM\NoResultException $e ) {
129 | return null;
130 | }
131 | }
132 |
133 |
134 | /**
135 | * Updates the "remember me" token for the given user in storage.
136 | *
137 | * @param \Illuminate\Auth\UserInterface $user
138 | * @param string $token
139 | * @return void
140 | */
141 | public function updateRememberToken( \Illuminate\Contracts\Auth\Authenticatable $user, $token )
142 | {
143 |
144 | $user->setRememberToken( $token );
145 | $this->d2repository->createQueryBuilder( 'u' )->getEntityManager()->flush();
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Console/Generators/Entities.php:
--------------------------------------------------------------------------------
1 |
26 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
27 | * @license MIT
28 | */
29 | class Entities extends LaravelCommand
30 | {
31 | /**
32 | * The console command name.
33 | *
34 | * @var string
35 | */
36 | protected $name = 'd2b:generate:entities';
37 |
38 | /**
39 | * The console command description.
40 | *
41 | * @var string
42 | */
43 | protected $description = 'Generate Doctrine2 entities';
44 |
45 | /**
46 | * The Entity Manager
47 | *
48 | * @var \Doctrine\ORM\EntityManagerInterface
49 | */
50 | private $d2em;
51 |
52 | public function __construct(\Doctrine\ORM\EntityManagerInterface $d2em)
53 | {
54 | parent::__construct();
55 |
56 | $this->d2em = $d2em;
57 | }
58 |
59 | public function fire()
60 | {
61 | $this->info('Starting entities generation....');
62 |
63 | // flush all generated and cached entities, etc
64 | \D2Cache::flushAll();
65 |
66 | $cmf = new DisconnectedClassMetadataFactory();
67 | $cmf->setEntityManager($this->d2em);
68 | $metadata = $cmf->getAllMetadata();
69 |
70 | if( empty($metadata) ) {
71 | $this->error('No metadata found to generate entities.');
72 | return -1;
73 | }
74 |
75 | $directory = Config::get( 'd2bdoctrine.paths.models' );
76 |
77 | if( !$directory ) {
78 | $this->error('The entity directory has not been set.');
79 | return -1;
80 | }
81 |
82 | $entityGenerator = new EntityGenerator();
83 |
84 | $entityGenerator->setGenerateAnnotations($this->option('generate-annotations'));
85 | $entityGenerator->setGenerateStubMethods($this->option('generate-methods'));
86 | $entityGenerator->setRegenerateEntityIfExists($this->option('regenerate-entities'));
87 | $entityGenerator->setUpdateEntityIfExists($this->option('update-entities'));
88 | $entityGenerator->setNumSpaces($this->option('num-spaces'));
89 | $entityGenerator->setBackupExisting(!$this->option('no-backup'));
90 |
91 | $this->info('Processing entities:');
92 | foreach ($metadata as $item) {
93 | $this->line($item->name);
94 | }
95 |
96 | try {
97 | $entityGenerator->generate($metadata, $directory);
98 | $this->info('Entities have been created.');
99 | } catch ( \ErrorException $e ) {
100 | if( $this->option( 'verbose' ) == 3 )
101 | throw $e;
102 |
103 | $this->error( "Caught ErrorException: " . $e->getMessage() );
104 | $this->info( "Re-optimizing:" );
105 | $this->call( 'optimize' );
106 | $this->comment( "*** You must now rerun this artisan command ***" );
107 | exit(-1);
108 | }
109 | }
110 |
111 |
112 | protected function getOptions()
113 | {
114 | return [
115 | [
116 | 'generate-annotations', null, InputOption::VALUE_OPTIONAL,
117 | 'Flag to define if generator should generate annotation metadata on entities.', false
118 | ],
119 | [
120 | 'generate-methods', null, InputOption::VALUE_OPTIONAL,
121 | 'Flag to define if generator should generate stub methods on entities.', true
122 | ],
123 | [
124 | 'regenerate-entities', null, InputOption::VALUE_OPTIONAL,
125 | 'Flag to define if generator should regenerate entity if it exists.', false
126 | ],
127 | [
128 | 'update-entities', null, InputOption::VALUE_OPTIONAL,
129 | 'Flag to define if generator should only update entity if it exists.', true
130 | ],
131 | [
132 | 'extend', null, InputOption::VALUE_REQUIRED,
133 | 'Defines a base class to be extended by generated entity classes.'
134 | ],
135 | [
136 | 'num-spaces', null, InputOption::VALUE_REQUIRED,
137 | 'Defines the number of indentation spaces', 4
138 | ],
139 | [
140 | 'no-backup', null, InputOption::VALUE_NONE,
141 | 'Flag to define if generator should avoid backuping existing entity file if it exists.'
142 | ]
143 | ];
144 | }
145 |
146 |
147 | }
148 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Utils/JsonSerializer.php:
--------------------------------------------------------------------------------
1 | array(parameters) to convert
15 | * @param array $blacklist List of entity=>array(parameters) to skip
16 | * @return string
17 | */
18 | public static function json_encode($object, $depth=1, $whitelist=array(), $blacklist=array()){
19 | return json_encode(self::toArray($object, $depth, $whitelist, $blacklist));
20 | }
21 |
22 | /**
23 | * Serializes our Doctrine Entities
24 | *
25 | * This is the primary entry point, because it assists with handling collections
26 | * as the primary Object
27 | *
28 | * @param object $object The Object (Typically a Doctrine Entity) to convert to an array
29 | * @param integer $depth The Depth of the object graph to pursue
30 | * @param array $whitelist List of entity=>array(parameters) to convert
31 | * @param array $blacklist List of entity=>array(parameters) to skip
32 | * @return NULL|Array
33 | *
34 | */
35 | public static function toArray($object, $depth = 1,$whitelist=array(), $blacklist=array()){
36 |
37 | // If we drop below depth 0, just return NULL
38 | if ($depth < 0){
39 | return NULL;
40 | }
41 |
42 | // If this is an array, we need to loop through the values
43 | if (is_array($object)){
44 | // Somthing to Hold Return Values
45 | $anArray = array();
46 |
47 | // The Loop
48 | foreach ($object as $value){
49 | // Store the results
50 | $anArray[] = self::arrayizor($value, $depth, $whitelist, $blacklist);
51 | }
52 | // Return it
53 | return $anArray;
54 | }else{
55 | // Just return it
56 | return self::arrayizor($object, $depth, $whitelist, $blacklist);
57 | }
58 | }
59 |
60 | /**
61 | * This does all the heavy lifting of actually converting to an array
62 | *
63 | * @param object $object The Object (Typically a Doctrine Entity) to convert to an array
64 | * @param integer $depth The Depth of the object graph to pursue
65 | * @param array $whitelist List of entity=>array(parameters) to convert
66 | * @param array $blacklist List of entity=>array(parameters) to skip
67 | * @return NULL|Array
68 | */
69 | private static function arrayizor($anObject, $depth, $whitelist=array(), $blacklist=array()){
70 | // Determine the next depth to use
71 | $nextDepth = $depth - 1;
72 |
73 | // Lets get our Class Name
74 | // @TODO: Making some assumptions that only objects get passed in, need error checking
75 | $clazzName = get_class($anObject);
76 |
77 | // Now get our reflection class for this class name
78 | $reflectionClass = new \ReflectionClass($clazzName);
79 |
80 | // Then grap the class properites
81 | $clazzProps = $reflectionClass->getProperties();
82 |
83 | if (is_a($anObject, 'Doctrine\ORM\Proxy\Proxy')){
84 | $parent = $reflectionClass->getParentClass();
85 | $clazzName = $parent->getName();
86 | $clazzProps = $parent->getProperties();
87 | }
88 | // A new array to hold things for us
89 | $anArray = array();
90 |
91 | // Lets loop through those class properties now
92 | foreach ($clazzProps as $prop){
93 |
94 | // If a Whitelist exists
95 | if (@count($whitelist[$clazzName]) > 0){
96 | // And this class property is not in it
97 | if (! @in_array($prop->name, $whitelist[$clazzName])){
98 | // lets skip it.
99 | continue;
100 | }
101 | // Otherwise, if a blacklist exists
102 | }elseif (@count($blacklist[$clazzName] > 0)){
103 | // And this class property is in it
104 | if (@in_array($prop->name, $blacklist[$clazzName])){
105 | // lets skip it.
106 | continue;
107 | }
108 | }
109 |
110 | // We know the property, lets craft a getProperty method
111 | // $method_name = 'get' . ucfirst($prop->name) ;
112 | $method_name = 'get' . preg_replace_callback(
113 | '/_[a-zA-Z]/',
114 | function ($match) {
115 | $s = $match[0];
116 | return strtoupper($s[1]);
117 | },
118 | ucfirst( $prop->name )
119 | );
120 |
121 | // And check to see that it exists for this object
122 | if (! method_exists($anObject, $method_name)){
123 | continue;
124 | }
125 | // It did, so lets call it!
126 | $aValue = $anObject->$method_name();
127 |
128 | // If it is an object, we need to handle that
129 | if (is_object($aValue)){
130 | // If it is a datetime, lets make it a string
131 | if (get_class($aValue) === 'DateTime'){
132 | $anArray[$prop->name] = $aValue->format('Y-m-d H:i:s');
133 |
134 | // If it is a Doctrine Collection, we need to loop through it
135 | }elseif(get_class($aValue) ==='Doctrine\ORM\PersistentCollection'){
136 | $collect = array();
137 | foreach ($aValue as $val){
138 | $collect[] = self::toArray($val, $nextDepth, $whitelist, $blacklist);
139 | }
140 | $anArray[$prop->name] = $collect;
141 |
142 | // Otherwise, we can simply make it an array
143 | }else{
144 | $anArray[$prop->name] = self::toArray($aValue, $nextDepth, $whitelist, $blacklist);
145 | }
146 | // Otherwise, we just use the base value
147 | }else{
148 |
149 | $anArray[$prop->name] = $val;
150 | }
151 | }
152 | // All done, send it back!
153 | return $anArray;
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NB: You are advised to use this project from here on in: http://laraveldoctrine.org/
2 |
3 | # Doctrine2Bridge for Laravel 5
4 |
5 | Adds the power of Doctrine2 to Laraval 5 (including authentication and SQL query logging support).
6 |
7 | For Laravel4, see [opensolutions/doctrine2bridge](https://github.com/opensolutions/doctrine2bridge)
8 |
9 | Laravel's Eloquent ORM is nice for rapid development and the active model pattern. However there's little out
10 | there that can beat Doctrine2 when you need a more full-featured ORM.
11 |
12 | This is an integration of Doctrine 2.x to Laravel 5.x as a composer package. Doctrine's EntityManager instance is accessible through a facade named `D2EM` and the cache is directly available via `D2Cache`.
13 |
14 | Metadata is currently obtained via the [XML driver](http://docs.doctrine-project.org/en/latest/reference/xml-mapping.html). It should be easy to add additional drivers to this.
15 |
16 | Authentication support is also included via a `Auth/Doctrine2UserProvider` class. Documentation on integrating this with Laravel's own authentication system [can be found here](https://github.com/opensolutions/doctrine2bridge/wiki/Auth).
17 |
18 | ## Installation
19 |
20 | Installation is the usual for Laravel packages. You can find a detailed worked version of [how to install and test in the wiki](https://github.com/opensolutions/doctrine2bridge-l5/wiki/Install-from-Scratch).
21 |
22 | Insert the following in the packages (`require`) section of your composer.json file and run an update (`composer update`):
23 |
24 | "opensolutions/doctrine2bridge-l5": "2.4.*",
25 |
26 | Generally speaking, we'll try and match our minor versions (2.4.x) with Doctrine's but you should always use the latest `x` version of this.
27 |
28 | Add the service providers to your Laravel application in `app/config/app.php`. In the `'providers'` array add:
29 |
30 | 'Doctrine2Bridge\Doctrine2CacheBridgeServiceProvider',
31 | 'Doctrine2Bridge\Doctrine2BridgeServiceProvider',
32 |
33 | You'll need to publish and edit the configuration files:
34 |
35 | ./artisan vendor:publish --provider "Doctrine2Bridge\Doctrine2CacheBridgeServiceProvider"
36 | ./artisan vendor:publish --provider "Doctrine2Bridge\Doctrine2BridgeServiceProvider"
37 |
38 | This should get you a fresh copy of the configuration files (`d2bcache.php` and `db2doctrine.php`) in the configs directory.
39 |
40 | Now, edit these as well as setting Laravel5's own `cache.php` and `database.php` appropriately.
41 |
42 | The default directory for Doctrine2's xml schema is `database/xml`. This can be configured in `config/d2bdoctrine.php`.
43 |
44 | Documentation on integrating this with Laravel's own authentication system [can be found here](https://github.com/opensolutions/doctrine2bridge-l5/wiki/Auth).
45 |
46 | ## Usage
47 |
48 | Four bindings are created which can be injected via Laravel's IoC in the standard manner:
49 |
50 | * `Doctrine\ORM\EntityManagerInterface` (which is an instance of Doctrine\ORM\EntityManager)
51 | * `Doctrine\Common\Cache\Cache` (which is an instance of the appropriate cache provider)
52 | * `Doctrine\ORM\Mapping\ClassMetadataFactory` (used in this package by the console generator commands)
53 | * `Doctrine2Bridge\Support\Repository` (used by the `D2R` facade, see below)
54 |
55 | Three facades are provided - for the Doctrine2 cache, the entity manager and a convenience repository generator. These can be used as follows:
56 |
57 | D2Cache::save( $key, $value );
58 | D2Cache::fetch( $key );
59 |
60 | D2EM::persist( $object );
61 | D2EM::flush();
62 | $users = D2EM::getRepository( 'Entities\User' )->findAll();
63 |
64 | Typically we'd create and use a repository as follows:
65 |
66 | $sample = D2EM::getRepository( '\Entities\SampleEntity' )->find(5);
67 |
68 | Assuming `d2bdoctrine.namespaces.models => 'Entities'`, then we can use the `D2R` facade in any of the following ways to achieve the same result:
69 |
70 | $sample = D2R::r( 'SampleEntity' )->find(5);
71 | $sample = D2R::r( 'Entities\SampleEntity' )->find(5);
72 | $sample = D2R::r( 'SampleEntity', 'Entities' )->find(5);
73 |
74 | ## More Detailed Usage
75 |
76 | The configuration file by default expects to find XML schema definitions under `database/xml`. Let's say for example we have a single schema file called `database/xml/Entities.SampleEntity.dcm.xml` containing:
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | Assuming you've configured your database connection parameters in the config file and you're positioned in the base directory of your project, we can create the entities, proxies and repositories with:
89 |
90 | ./artisan d2b:generate:entities
91 | ./artisan d2b:generate:proxies
92 | ./artisan d2b:generate:repositories
93 |
94 | There is also a handy shortcut for this:
95 |
96 | ./artisan d2b:generate:all
97 |
98 | Read the output of these commands as they may need to be run twice.
99 |
100 | We also bundle a full Doctrine2 CLI utilty so the above could also be done via:
101 |
102 | ./vendor/bin/d2b-doctrine2 orm:generate-entities database/
103 | ./vendor/bin/d2b-doctrine2 orm:generate-proxies
104 | ./vendor/bin/d2b-doctrine2 orm:generate-repositories database/
105 |
106 | You can also (drop) and create the database with:
107 |
108 | ./artisan d2b:schema:drop --commit
109 | ./artisan d2b:schema:create --commit
110 |
111 | And you can update and validate via:
112 |
113 | ./artisan d2b:schema:update --commit
114 | ./artisan d2b:schema:validate
115 |
116 |
117 | Now you can add some data to the database:
118 |
119 | $se = new Entities\SampleEntity;
120 | $se->setName( rand( 0, 100 ) );
121 | D2EM::persist( $se );
122 | D2EM::flush();
123 |
124 | And query it:
125 |
126 | echo count( D2EM::getRepository( 'Entities\SampleEntity' )->findAll() );
127 |
128 | I use the excellent [Skipper](http://www.skipper18.com/) to create and manage my XML schema files.
129 |
130 | ## Convenience Function for Repositories
131 |
132 |
133 | ## SQL Query Logging
134 |
135 | This package includes an implementation of `Doctrine\DBAL\Logging\SQLLlogger` which times the queries and calls the Laravel [Log](http://laravel.com/docs/errors#logging) facade to log the query execution times and the SQL queries.
136 |
137 | This logger can be enabled in the configuration file.
138 |
139 | ## License
140 |
141 | Like the Laravel framework itself, this project is open-sourced under the [MIT license](http://opensource.org/licenses/MIT).
142 |
143 | ## Inspiration
144 |
145 | Based on my original package [opensolutions/doctrine2bridge](https://github.com/opensolutions/doctrine2bridge) for Laravel4. Some additional inspiration when porting to Laravel5 from [mitchellvanw/laravel-doctrine](https://github.com/mitchellvanw/laravel-doctrine).
146 |
147 |
--------------------------------------------------------------------------------
/src/Doctrine2Bridge/Doctrine2BridgeServiceProvider.php:
--------------------------------------------------------------------------------
1 |
22 | * @copyright Copyright (c) 2015 Open Source Solutions Limited
23 | * @license MIT
24 | */
25 | class Doctrine2BridgeServiceProvider extends \Illuminate\Support\ServiceProvider
26 | {
27 | /**
28 | * Have we been configured?
29 | */
30 | private $configured = true;
31 |
32 | /**
33 | * Bootstrap the application events.
34 | *
35 | * @return void
36 | */
37 | public function boot( \Doctrine\Common\Cache\Cache $d2cache )
38 | {
39 | // handle publishing of config file:
40 | $this->handleConfigs();
41 |
42 | if( !$this->configured ) {
43 | if( isset( $_SERVER['argv'][1] ) && $_SERVER['argv'][1] != 'vendor:publish' )
44 | echo "You must pubish the configuration files first: artisan vendor:publish\n";
45 | return;
46 | }
47 |
48 | $d2em = $this->app->make( \Doctrine\ORM\EntityManagerInterface::class );
49 | $d2em->getConfiguration()->setMetadataCacheImpl( $d2cache );
50 | $d2em->getConfiguration()->setQueryCacheImpl( $d2cache );
51 | $d2em->getConnection()->getConfiguration()->setResultCacheImpl( $d2cache );
52 |
53 | if( Config::get( 'd2bdoctrine.sqllogger.enabled' ) )
54 | $this->attachLogger( $d2em );
55 | }
56 |
57 |
58 |
59 | /**
60 | * Register the service provider.
61 | *
62 | * @return void
63 | */
64 | public function register()
65 | {
66 | if( !Config::get( 'd2bdoctrine' ) ) {
67 | if( isset( $_SERVER['argv'][1] ) && $_SERVER['argv'][1] != 'vendor:publish' )
68 | echo "You must pubish the configuration files first: artisan vendor:publish\n";
69 | $this->configured = false;
70 | return;
71 | }
72 |
73 | $this->registerEntityManager();
74 | $this->registerClassMetadataFactory();
75 | $this->registerConsoleCommands();
76 | $this->registerRepositoryFacade();
77 | $this->registerFacades();
78 |
79 | if( Config::get( 'd2bdoctrine.auth.enabled' ) )
80 | $this->setupAuth();
81 | }
82 |
83 | /**
84 | * The Entity Manager - why we're all here!
85 | */
86 | private function registerEntityManager()
87 | {
88 | $this->app->singleton( EntityManagerInterface::class, function( $app ) {
89 |
90 | $dconfig = new \Doctrine\ORM\Configuration;
91 |
92 | $driver = new \Doctrine\ORM\Mapping\Driver\XmlDriver(
93 | array( Config::get( 'd2bdoctrine.paths.xml_schema' ) )
94 | );
95 |
96 | $dconfig->setMetadataDriverImpl( $driver );
97 |
98 | $dconfig->setProxyDir( Config::get( 'd2bdoctrine.paths.proxies' ) );
99 | $dconfig->setProxyNamespace( Config::get( 'd2bdoctrine.namespaces.proxies' ) );
100 | $dconfig->setAutoGenerateProxyClasses( Config::get( 'd2bdoctrine.autogen_proxies' ) );
101 |
102 | $lconfig = $this->laravelToDoctrineConfigMapper();
103 |
104 | //load prefix listener
105 | if( isset($lconfig['prefix']) && $lconfig['prefix'] && $lconfig['prefix'] !== '' ) {
106 | $tablePrefix = new TablePrefix( $lconfig['prefix']);
107 | $eventManager->addEventListener(Events::loadClassMetadata, $tablePrefix);
108 | }
109 |
110 | return EntityManager::create( $lconfig, $dconfig );
111 | });
112 |
113 | }
114 |
115 | /**
116 | * Register Facades to make developers' lives easier
117 | */
118 | private function registerFacades()
119 | {
120 | // Shortcut so developers don't need to add an Alias in app/config/app.php
121 | \App::booting( function() {
122 | $loader = \Illuminate\Foundation\AliasLoader::getInstance();
123 | $loader->alias( 'D2EM', 'Doctrine2Bridge\Support\Facades\Doctrine2' );
124 | $loader->alias( 'D2R', 'Doctrine2Bridge\Support\Facades\Doctrine2Repository' );
125 | });
126 | }
127 |
128 | /**
129 | * Register Laravel console commands
130 | */
131 | private function registerConsoleCommands()
132 | {
133 | $this->commands([
134 | "\Doctrine2Bridge\Console\Generators\All",
135 | "\Doctrine2Bridge\Console\Generators\Entities",
136 | "\Doctrine2Bridge\Console\Generators\Proxies",
137 | "\Doctrine2Bridge\Console\Generators\Repositories",
138 |
139 | "\Doctrine2Bridge\Console\Schema\Create",
140 | "\Doctrine2Bridge\Console\Schema\Drop",
141 | "\Doctrine2Bridge\Console\Schema\Update",
142 | "\Doctrine2Bridge\Console\Schema\Validate",
143 | ]);
144 | }
145 |
146 | /**
147 | * Metadata Factory - mainly used by schema console commands
148 | */
149 | private function registerClassMetadataFactory()
150 | {
151 | $this->app->singleton( ClassMetadataFactory::class, function( $app ) {
152 | return $app[EntityManagerInterface::class]->getMetadataFactory();
153 | });
154 | }
155 |
156 |
157 | private function registerRepositoryFacade()
158 | {
159 | $this->app->bind( D2Repository::class, function( $app ) {
160 | return new D2Repository;
161 | });
162 |
163 | \App::booting( function() {
164 | $loader = \Illuminate\Foundation\AliasLoader::getInstance();
165 | $loader->alias( 'D2R', 'Doctrine2Bridge\Support\Facades\Doctrine2Repository' );
166 | });
167 |
168 | }
169 |
170 | /**
171 | * Attach Laravel logging to Doctrine for debugging / profiling
172 | */
173 | private function attachLogger( $d2em )
174 | {
175 | $logger = new Logger\Laravel;
176 | if( Config::has( 'd2bdoctrine.sqllogger.level' ) )
177 | $logger->setLevel( Config::get( 'd2bdoctrine.sqllogger.level' ) );
178 |
179 | $d2em->getConnection()->getConfiguration()->setSQLLogger( $logger );
180 | }
181 |
182 | /**
183 | * Set up Laravel authentication via Doctrine2 provider
184 | */
185 | private function setupAuth()
186 | {
187 | Auth::extend( 'doctrine2bridge', function() {
188 | return new \Illuminate\Auth\Guard(
189 | new \Doctrine2Bridge\Auth\Doctrine2UserProvider(
190 | \D2EM::getRepository( Config::get( 'd2bdoctrine.auth.entity' ) ),
191 | new \Illuminate\Hashing\BcryptHasher
192 | ),
193 | \App::make('session.store')
194 | );
195 | });
196 | }
197 |
198 |
199 | /**
200 | * Publish configuration file
201 | */
202 | private function handleConfigs() {
203 | $configPath = __DIR__ . '/../config/d2bdoctrine.php';
204 | $this->publishes( [ $configPath => config_path('d2bdoctrine.php') ] );
205 | $this->mergeConfigFrom( $configPath, 'd2bdoctrine' );
206 | }
207 |
208 |
209 | /**
210 | * Convert Laravel5's database configuration to something what Doctrine2's
211 | * DBAL providers can use.
212 | *
213 | * @return array
214 | */
215 | private function laravelToDoctrineConfigMapper()
216 | {
217 | switch( Config::get( 'database.default' ) ) {
218 | case 'mysql':
219 | return [
220 | 'driver' => 'pdo_mysql',
221 | 'dbname' => Config::get( 'database.connections.mysql.database' ),
222 | 'user' => Config::get( 'database.connections.mysql.username' ),
223 | 'password' => Config::get( 'database.connections.mysql.password' ),
224 | 'host' => Config::get( 'database.connections.mysql.host' ),
225 | 'charset' => Config::get( 'database.connections.mysql.charset' ),
226 | 'prefix' => Config::get( 'database.connections.mysql.prefix' ),
227 | ];
228 | break;
229 |
230 | case 'pgsql':
231 | return [
232 | 'driver' => 'pdo_pgsql',
233 | 'dbname' => Config::get( 'database.connections.pgsql.database' ),
234 | 'user' => Config::get( 'database.connections.pgsql.username' ),
235 | 'password' => Config::get( 'database.connections.pgsql.password' ),
236 | 'host' => Config::get( 'database.connections.pgsql.host' ),
237 | 'charset' => Config::get( 'database.connections.pgsql.charset' ),
238 | 'prefix' => Config::get( 'database.connections.pgsql.prefix' ),
239 | ];
240 | break;
241 |
242 | case 'sqlite':
243 | return [
244 | 'driver' => 'pdo_sqlite',
245 | 'path' => Config::get( 'database.connections.sqlite.database' ),
246 | 'user' => Config::get( 'database.connections.sqlite.username' ),
247 | 'password' => Config::get( 'database.connections.sqlite.password' ),
248 | 'prefix' => Config::get( 'database.connections.sqlite.prefix' ),
249 | ];
250 | break;
251 |
252 | default:
253 | throw new Doctrine2Bridge\Exception\ImplementationNotFound( Config::get( 'database.default' ) );
254 | }
255 | }
256 | }
257 |
--------------------------------------------------------------------------------