These are my requirements:
I have a table(upload_training_files)
The fields are id, organisation_id(foreign), year_id(foreign), created_by, created_at, updated_by, updated_at, file_path.
The organisation_id field refers to id field of organisations. It should be auto_incremented and also should identify with a sequence table(upload_training_file_organisation_id_fk_seq).
I have failed to do this in Laravel after repeated attempts. This is my schema:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUploadTrainingFileTable extends Migration {
public function up()
{
Schema::create('upload_training_file', function(Blueprint $table) {
$table->bigincrements('id');
$table->biginteger('organisation_id_fk')->unsigned()->unique();
$table->foreign('organisation_id_fk')->references('organisation_id')->on('organisations');
$table->biginteger('year_id_fk')->unsigned()->unique();
$table->foreign('year_id_fk')->references('year_id')->on('year_of_performance');
$table->biginteger('created_by')->nullable();
$table->time('created_at')->nullable();
$table->biginteger('updated_by');
$table->time('updated_at')->nullable();
$table->string('file_path')->nullable();
});
}
public function down()
{
Schema::drop('upload_training_file');
}
}
Here's the snapshot of the database table
Solved it. :)
You have to drop the primary keys before assigning every new auto increment field.
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUploadTrainingFileTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('upload_training_file', function(Blueprint $table) {
$table->bigincrements('upload_training_file_id');
});
Schema::table('upload_training_file', function($table)
{
$table->dropPrimary('upload_training_file_upload_training_file_id_primary');
});
Schema::table('upload_training_file', function($table)
{
$table->bigincrements('organisation_id_fk')->unsigned()->after('id');;
$table->foreign('organisation_id_fk')->references('organisation_id')->on('organisation');
});
Schema::table('upload_training_file', function($table)
{
$table->dropPrimary('upload_training_file_organisation_id_fk_primary');
});
Schema::table('upload_training_file', function($table)
{
$table->bigincrements('year_id_fk')->unsigned()->after('organisation_id_fk');;
$table->foreign('year_id_fk')->references('year_id')->on('year_of_performance');
$table->biginteger('created_by')->nullable();
$table->time('create_date')->nullable();
$table->biginteger('updated_by')->nullable;
$table->time('update_date')->nullable();
$table->string('file_path')->nullable();
});
Schema::table('upload_training_file', function($table)
{
$table->dropPrimary('upload_training_file_year_id_fk_primary');
$table->primary('upload_training_file_id');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('upload_training_file');
}
}
Related
How to define this relationship in Laravel ? I tried to develop three primary keys in Laravel. but it doesn't work. how could i resolve this ?
Those Keys may symbolise primary keys, foreign keys, unique columns or indexes.
You cannot have more than one primary key on a table.
Here is what I tried:
Diagram
php .\artisan make:model Employee -m
php .\artisan make:model Title -m
php .\artisan make:model Salary -m
class CreateEmployeesTable extends Migration
{
public function up(): void
{
Schema::create('employees', function (Blueprint $table) {
$table->bigIncrements('emp_no');
$table->string('first_name', 14);
$table->string('last_name', 16);
$table->date('birth_date');
$table->date('hire_date');
});
}
};
class CreateTitlesTable extends Migration
{
public function up(): void
{
Schema::create('titles', function (Blueprint $table) {
$table->unsignedBigInteger('emp_no');
$table->string('title', 50)->index();
$table->date('from_date')->index();
$table->foreign('emp_no')->references('emp_no')->on('employees');
});
}
};
class CreateSalariesTable extends Migration
{
public function up(): void
{
Schema::create('salaries', function (Blueprint $table) {
$table->unsignedBigInteger('emp_no');
$table->integer('salary');
$table->date('from_date')->index();
$table->foreign('emp_no')->references('emp_no')->on('employees');
});
}
};
Edit
Assuming that multiple key icons mean a composite key
class CreateEmployeesTable extends Migration
{
public function up(): void
{
Schema::create('employees', function (Blueprint $table) {
$table->bigIncrements('emp_no');
$table->string('first_name', 14);
$table->string('last_name', 16);
$table->date('birth_date');
$table->date('hire_date');
});
}
};
class CreateTitlesTable extends Migration
{
public function up(): void
{
Schema::create('titles', function (Blueprint $table) {
$table->unsignedBigInteger('emp_no');
$table->string('title', 50);
$table->date('from_date');
$table->foreign('emp_no')->references('emp_no')->on('employees');
$table->primary(['emp_no', 'title', 'from_date']);
});
}
};
class CreateSalariesTable extends Migration
{
public function up(): void
{
Schema::create('salaries', function (Blueprint $table) {
$table->unsignedBigInteger('emp_no');
$table->integer('salary');
$table->date('from_date');
$table->foreign('emp_no')->references('emp_no')->on('employees');
$table->primary(['emp_no', 'from_date']);
});
}
};
I'm new to ZF2. After few days of trying to figure out how all this stuff should work I was unable to figure out how should I call TableGateway Model from Service.
So I have Controller:
class SubscriberController extends AbstractActionController
{
/**
* #var \Subscriber\Service\SubscriberServiceInterface
*/
private $subscriberService;
/**
* #param $subscriberService
*/
public function __construct(SubscriberServiceInterface $subscriberService)
{
$this->subscriberService = $subscriberService;
}
Factroy for this Controller:
class SubscriberControllerFactory implements FactoryInterface
{
/**
* Returns ArchiveController instance.
*
* #param ServiceLocatorInterface $serviceLocator
* #return SubscriberController
* #override
**/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$sm = $serviceLocator->getServiceLocator();
return new SubscriberController(
$sm->get('Subscriber\Service\SubscriberServiceInterface')
);
}
Some SubscriberTable:
class SubscriberTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
And Service in which I want to get SubscriberTable instance and make some logic. But I can't figure out how should I call this instance in SubscriberService and set the DbAdapter for SubscriberTable
First implement servicelocator interface and define get and set locator functions to your service like this.
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class Yourservice implements ServiceLocatorAwareInterface{
function test(){
$this->getSubscriberTable->fetchAll(); // call to subscriber table functions
}
/**
* #table gateway Call
**/
public function getSubscriberTable()
{
if (!$this->SubscriberTable) {
$sm = $this->getServiceLocator();
$this->SubscriberTable = $sm->get('Application\Model\SubscriberTable');
}
return $this->SubscriberTable;
}
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
}
Hope it will help you.
I have two model classes as defined as below:
class Event extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
public function user()
{
return $this->belongsTo('App\User');
}
public function transfers()
{
return $this->hasMany('App\Transfer');
}
}
class Transfers extends Model
{
use SoftDeletes;
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = ['deleted_at'];
public function event()
{
return $this->belongsTo('App\Event');
}
}
I am trying access Transfers from an Event object using following code.
public function filter()
{
$id = request()->input('id');
$event = \App\Event::where([['id', '=', $id],
['deleted_at', '=', NULL],
['user_id', '=', auth()->user()->id]])->first();
echo $event->transfers->count();
}
However, it resulted in an exception as follows
Fatal error: Class 'App\Transfer' not found in
D:\work\HC\hcserver\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php
on line 876
Please advice on how to get rid of this exception
Thanks in advance.
I installed Jenssegers MongoDB follow this
Lumen and MongoDB? answer and it work.
However, I tried to create a new collection using migration schema follow the example (https://github.com/jenssegers/laravel-mongodb#schema) and it not work. My function up:
Schema::create('users', function($collection)
{
$collection->index('name');
$collection->unique('email');
});
I got an error message:
[MongoException] Collection name cannot be empty
Thank you!
very late but you can try
/** Run the migrations.
*
* #return void
*/
public function up()
{
Schema::connection($this->connection)
->table('actions', function (Blueprint $collection)
{
$collection->index('name');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::connection($this->connection)
->table('actions', function (Blueprint $collection)
{
$collection->drop();
});
}
Src: https://github.com/jenssegers/laravel-mongodb/issues/859
I'm playing with Doctrine ODM, trying to make some i18n-able field in my Mongo document. This is what I want to achieve in Mongo:
{
"title": {
"en": "Car",
"eu": "Autoa"
}
}
And the PHP API I want for the Document would be something like this:
$doc->getTitle()->setDefaultLocale('en');
$doc->getTitle(); // "Car"
$doc->getTitle()->get('eu'); // "Autoa"
$doc->getTitle()->set('es', 'Coche');
$doc->getTitle()->setTranslations([
'fr' => 'Voiture',
'eu' => 'Kotxea',
]);
$doc->getTitle()->getTranslations(); // ["en" => "Car", ...]
I have tried two aproaches, both of them with it's own pitfalls. I don't like none of them.
Custom Annotation
I've created a class which will be the middleman between the document and mongo. This class will be placed in the field, in this case in $title.
class Translation
{
protected $default;
protected $translations;
public function __construct(array $translations = array()) { /* ... */ }
public function get($locale) { /* ... */ }
public function getTranslations() { /* ... */ }
public function set($locale, $value) { /* ... */ }
public function setDefaultLocale($default) { /* ... */ }
public function setTranslations(array $translations = array()) { /* ... */ }
}
Then, I've created a custom FieldType, which converts the Mongo array to the Translation middleman object and viceversa (convertTo* methods seem to be ignored by Doctrine and are equal to the closureTo* methods, so I'll omit them):
class TranslationType extends \Doctrine\ODM\MongoDB\Types\Type
{
public function convertToDatabaseValue($value) { /* ... */ }
public function convertToPHPValue($value) { /* ... */ }
public function closureToMongo()
{
return '$return = $value->getTranslations();';
}
public function closureToPHP()
{
return '$return = new \App\TransBundle\MongoDB\Translation($value);';
}
}
Then, I have my annotation:
/** #Annotation */
class Translation extends \Doctrine\ODM\MongoDB\Mapping\Annotations\AbstractField
{
public $type = 'translation';
}
And the document:
use App\TransBundle\MongoDB\Annotations\Translation;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/** #MongoDB\Document */
class Translated
{
/** #MongoDB\Id */
protected $id;
/** #Translation */
protected $title;
public function getId() { /* ... */ }
public function getTitle() { /* ... */ }
}
The GOOD parts:
Easy usage: one use, property declaration, annotation and the getter.
Reads OK from Mongo => Doctrine.
Meets API requirements.
The BAD parts:
Doesn't save to DB, I suppose that it's because the Translation object doesn't dirty the title property on the parent object Translated.
$title doesn't get initialized to the middleman Translation object on object creation.
This would be fixed by initializing the object in the constructor, but if possible I'd like to try to avoid this to keep the usage as lean as possible. I'll have to find a workaround.
EmbedOne
The second approach consists of using an embedded document, this works perfectly, but has it's own small issues. :-)
First, my base Translation class for the embedded document, this class will work directly on the class properties instead of an array property:
class BaseTranslation
{
public function __construct(array $translations = array()) { /* ... */ }
public function get($locale) { /* ... */ }
public function getTranslations() { /* ... */ }
public function set($locale, $value) { /* ... */ }
public function setDefaultLocale($default) { /* ... */ }
public function setTranslations(array $translations = array()) { /* ... */ }
}
Then, the Translation class to be used in my projects, this will be the actual embbeded document:
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/** #MongoDB\EmbeddedDocument */
class Translation extends BaseTranslation
{
/** #MongoDB\String */
protected $en;
/** #MongoDB\String */
protected $es;
/** #MongoDB\String */
protected $fr;
}
Finally the Document
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/** #MongoDB\Document */
class Translated
{
/** #MongoDB\Id */
protected $id;
/** #MongoDB\EmbedOne(targetDocument="Translation") */
protected $title;
public function getId() { /* ... */ }
public function getTitle() { /* ... */ }
}
The GOOD parts:
It just works, reads and writes nicely.
Easy setup.
Can be used with any data type, so it would be easy to add an isTranslated i18n boolean field, just add a new TranslationBoolean class.
The BAD parts:
Not a big problem but the locales are hardcoded in the Translation class, it would be nice to be able to work directly on an array but this would add another level in the schema and type coercion might be lost.
Like in the other approach, the property doesn't get initialized, but it's easy as initializing it in the constructor (like any One2Many relation).
Conclusions
I'm liking more the second approach, which works how it's now. Do you have any idea how to overcome the BAD parts on both approaches?
Thanks!
Regarding the type methods:
closureToMongo() is actually not used.
closureToPHP() is used by the HydratorFactory class.
convertToPHPValue() is used by ClassMetadataInfo, but only for identifiers.
convertToDatabaseValue() is used in a few places, such as UnitOfWork and PersistenceBuilder.
The missing convertToDatabaseValue() implementation could be related to why you're seeing TranslationType fail to persist to the database.
The issue of "hardcoded locales in the Translation class" could be alleviated by storing an object (Hash annotation) within this field, although that would add another layer to the model. An EmbedMany array of objects containing a field each for the language code and value would consume even more space, although the model could make it easier to devise a form to edit the data.
Have you looked into the DoctrineExtensions library? It contains a component for having translatable documents/entities (supports both ODM and ORM). The author has slowed down his own development of it, but there are a healthy amount of pull requests being merged on the project and it is widely used.