Laravel Schema Builder : Creating a binary(16) column - mysql

Using Laravel 5.5 and Mysql (10.1.19-MariaDB)
For a md5 hash I want a binary(16) column.
Let's call the colum url_hash
When using :
$table->binary('url_hash');
it will give me a BLOB column.
source : https://laravel.com/docs/5.5/migrations#creating-columns
I have seen all kind of hacks or plugins around the web for this , but what is the most simple one without any external plugins that could break on the next update?
Cheers

You can just set the character set to binary.
$table->char('url_hash', 16)->charset('binary');
This is actually shown as a real binary column type with a length of 16 in MySQL Workbench.
There shouldn't be any difference: https://stackoverflow.com/a/15335682/5412658

Extend the MySqlGrammar class, e.g. in app/MySqlGrammar.php:
namespace App;
use Illuminate\Support\Fluent;
class MySqlGrammar extends \Illuminate\Database\Schema\Grammars\MySqlGrammar {
protected function typeRealBinary(Fluent $column) {
return "binary({$column->length})";
}
}
Then use a macro to add your own column type:
DB::connection()->setSchemaGrammar(new \App\MySqlGrammar());
Blueprint::macro('realBinary', function($column, $length) {
return $this->addColumn('realBinary', $column, compact('length'));
});
Schema::create('table', function(Blueprint $table) {
$table->realBinary('url_hash', 16);
});

Laravel author recommends to do a DB:statement call and run the raw SQL.
If you are running migration, you could run this raw SQL after Schema::create:
DB::statement('ALTER TABLE table_name ADD url_hash binary(16) AFTER some_column');
Depends on use case, you could need to run this raw SQL to drop the column before dropping the table:
DB::statement('ALTER TABLE table_name DROP url_hash');

Related

Automatically append database name to database table names

Is it possible to automatically append database name to a table name in laravel?
The issue is that I have to join data from multiple databases in single queries and sometime I am having to manually replace template names, which is a lot of hassle.
The only solution that I found is that I can append database name to the table name within a model, i.e.
class User extends Model
{
protected $table = 'database_name.table_name';
}
But with above we are losing support for table prefixes.
Example when database name is not applied:
$userQuery = User::where('id', 1)
->with('settings')
->select('some data');
DB::connection('x')
->table('table-on-different-connection')
->insertUsing(['some columns'], $userQuery);
$userQuery is on a different connection and database_name was not applied to the tables within that part of the query. Hence why insertUsing is trying to perform joins on connection x.
Laravel is not appending database name when generating SQL statements. To resolve that, you need to create your own MySQL wrapper and append the database name to the table name that way.
This is where the issue takes place:
vendor\laravel\framework\src\Illuminate\Database\Query\Grammar.php
public function wrapTable($table)
{
if (! $this->isExpression($table)) {
return $this->wrap($this->tablePrefix.$table, true);
}
return $this->getValue($table);
}
You need to override wrapTable method and append database name to the table that way.
i.e.
public function wrapTable($table)
{
$databaseName = $this->wrap('my_database'); // dynamically defined name here
if (! $this->isExpression($table)) {
$tableName = $this->wrap($this->tablePrefix.$table, true);
return "{$databaseName}.{$tableName}";
}
return $this->getValue("{$databaseName}.{$table}");
}
How you go about extending Grammar and override this method depends on your application and your needs. This can be done globally (i.e. via AppProvider) or for an individual query.

Get table checksum in Laravel 5.4

What do you use to get the checksum of a table in Laravel? Is there something already abstracted for this or you have to use raw commands?
You have to use raw commands, but it is pretty easy, just add this method to your model:
public static function checksum()
{
$tableName = with(new static)->getTable();
$query = sprintf('CHECKSUM TABLE %s', $tableName);
return \DB::select(\DB::raw($query))[0]->Checksum;
}
You can now call this method statically to get the checksum.

Rearrange columns in a Laravel migration file

How do I re-arrange a column in a Laravel migration file for a MySQL database?
So far I have the following:
$table->date('foo')->after('bar')->change();
However, it does not seem to re-arrange the column.
Why not and how can I fix this?
Can't see anything in Laravel Schema API that will allow you to rearrange columns. Your best bet will be to use raw SQL statement as below.
DB::statement("ALTER TABLE table_name MODIFY COLUMN col_name col_definition AFTER another_col");
Try this, hope it help you to find right solution:
public function up()
{
DB::statement("ALTER TABLE example MODIFY COLUMN foo DATE AFTER bar");
}
public function down()
{
DB::statement("ALTER TABLE example MODIFY COLUMN foo DATE AFTER bar");
}
First Run following artisan command
php artisan make:migration reorganize_order_of_column_<col_name> --table=<table_name>
where col_name is name of column which you want to re-order and table_name if the name of your table
and then it will generate on new file in migration folder then update that file as following function
public function up()
{
DB::statement("ALTER TABLE <table_name> MODIFY COLUMN <col_name> <col_description> AFTER <second_col_name>");
}
public function down()
{
DB::statement("ALTER TABLE <table_name> MODIFY COLUMN <col_name> <col_description> AFTER <second_col_name>");
}
table_name is the name of table which you want to modify
col_name is the name of column which you want to re-order
col_description is the type and length of column like VARCHAR(5),DATE
second_col_name is the name of second column by which we are going to reorder

Codeigniter database prefix add in table

I have one database in which all table names like below
configuration_dst,
developer_dst,
application_dst
Now I want to manage my query in which want to add database prefix after table name instead of before.
For example :
{TABLE NAME}{PREFIX}
is it possible to manage using CI 3.0 ?
I have tried like below in Application/configuration/database.php
$db['default']['dbprefix']="_dst";
$db['default']['swap_pre']="{POST}";
Current Query :
$this->db->get('templates');
Current Table Name :
tablename : _dsttemplates
Expected Table Name :
tablename : templates_dst
I need prefix after table Name not before but didn't get any solution.
The only option is to change in driver files. You can do this using the following steps:
Go to /system/database/DB_query_builder.php
Search public function dbprefix
Replace
return $this->dbprefix.$table;
with
return $table.$this->dbprefix;
If it also interferes in any other places in your project then create a new function with replaced code like:
public function dbsuffix($table = '')
{
if ($table === '')
{
$this->display_error('db_table_name_required');
}
return $table.$this->dbprefix;
}
Working with Database prefixes manually
if you use
$this->db->set_dbprefix('newprefix');
$this->db->dbprefix('tablename'); // outputs newprefix_tablename
its always gives the table name as
newprefix_tablename
Because this is Codeigniter pastern.
Codeigniter Prefix

NodeJS - Sequelize updating issue

I have a problem with updating method.
I am doing this:
// Char is outside the object where update method is...
Char = db.define('characters', {}, {
tableName: 'characters',
updatedAt: false,
createdAt: false
});
//... part of the whole object
update: function ( columns, callback ) {
Char.update( columns, { where: { id: this.get('char_id') } } )
.complete( function ( err, res ) {
f.log(res, 'd');
});
},
When I define updatedAt to be false, the updates stop working at all and I don't know how to prevent that, except to add a column in my database. It throws me "Query was empty".
So I tried to define updatedAt as 'created_at' - an existing column in my table and then the updates have worked, but not at all. The query updating only 'created_at' with the timestamp, but not my preferred columns.
Example that I receive in the console:
Executing (default): UPDATE characters SET created_at='2015-02-03 21:03:00' WHERE id='1'
It should be:
Executing (default): UPDATE characters SET health = ..., created_at='2015-02-03 21:03:00' WHERE id='1'
I debug whether the columns parameter is valid parameter. Yes, it is - I send an object and receive an object.
Can someone help me. I tried old ways, new ways, read posts, but nothing.
EDIT:
I found where I'm wrong. I should define all fields which I want to update/insert.
Because of my english I didn't understand right the define function in documentation. I thought that when you define the fields you'll recreate your table structure, but now I realize, that that would happen if run sync() method.
I found where I'm wrong. I should define all fields which I want to update/insert. Because of my english I didn't understand right the define function in documentation. I thought that when you define the fields you'll recreate your table structure, but now I realize, that that would happen if run sync() method.