I'll assume you have two models setup : CanvasTopic and CanvasPostsTopic (based on Laravel table name conventions).
In your query you are have a implicit join, by listing both tables in the FROM clause and later filtering their relationship in the WHERE clause.
But the WHERE filter seems to filter by the relationship constraint, and the only column from canvas_posts_topics you retrieve is the foregin key.
Depending on the records on both tables the query above will yield a lot of duplicated records, as the other columns are from the derived table.
From my understanding you could simplify the query to this:
SELECT id, name FROM canvas_topics
Or, if you need the "duplicated" id column
SELECT id AS topic_id, id, name FROM canvas_topics
Note that I say "duplicated", because due to the WHERE condition all the records would have the same value for t.topic_id and ti.id
This simplified query could be translated to Eloquent as:
$records = CanvasTopic::get(['id', 'name']);
Or with the duplicated column:
$records = CanvasTopic::select(DB::raw('id AS topic_id'), 'id', 'name'])->get();
Where DB is the DB façade (\Illuminate\Support\Facades\DB).
If you need to perform the join anyhow you can try this:
$records = CanvasTopic::select([
DB::raw('canvas_posts_topics.topic_id'),
'canvas_topics.id',
'canvas_topics.name',
])
->join('canvas_posts_topics', 'canvas_posts_topics.topic_id', '=', 'canvas_topics.id')
->get();
Or if you want to stick with the implicit join:
$records = CanvasTopic::select([
DB::raw('canvas_posts_topics.topic_id'),
'canvas_topics.id',
'canvas_topics.name',
])
->from(DB::raw('canvas_posts_topics, canvas_topics')
->whereColumn('canvas_posts_topics.topic_id', 'canvas_topics.id')
->get();
If you find too much code, there is a not weel knowm method that let you populate a model from a raw query:
$records = CanvasTopic::fromQuery('SELECT t.topic_id, ti.id, ti.name FROM canvas_posts_topics AS t, canvas_topics AS ti WHERE t.topic_id = ti.id');
This is useful when you have a quite complex query