i'm trying to learn Drupal 8, i've been following the official guide to create a custom module (this tutorial), but when i go to the /hello route i get a page not found error, the module is active, maybe an error with the routing?
here's part of the code:
hello_world.routing.yml
hello_world.content:
path: '/hello'
defaults:
_controller: '\Drupal\hello_world\Controller\HelloController::content'
_title: 'Hello World'
requirements:
_permission: 'access content'
this is the HelloController.php
<?php
namespace Drupal\hello_world\Controller;
use Drupal\Core\Controller\ControllerBase;
/**
* Defines HelloController class.
*/
class HelloController extends ControllerBase {
/**
* Display the markup.
*
* #return array
* Return markup array.
*/
public function content() {
return [
'#type' => 'markup',
'#markup' => $this->t('Hello, World!'),
];
}
}
And this is the directory structure
I'm new with drupal so it is really posible that i made a rookie mistake, any help would be helpful, thanks
Your routing file says hello_worl, it is a typo. Correct that and clear caches.
Related
I am working on a SilverStripe project. I am trying to write functional tests for my application following this documentation, https://docs.silverstripe.org/en/4/developer_guides/testing/functional_testing/. I am testing a POST request. But it is not working. You can see my code below.
I have a controller class called CustomFormPageController with the following code.
class CustomFormPageController extends PageController
{
private static $allowed_actions = [
'testPostRequest',
];
private static $url_handlers = [
'testPostRequest' => 'testPostRequest',
];
public function testPostRequest(HTTPRequest $request)
{
if (! $request->isPOST()) {
return "Bad request";
}
return "Request successfully processed";
}
}
I also have a page class for that controller called, CustomFormPage. Following is the implementation of the class.
class CustomFormPage extends Page
{
}
What I am trying to test is that I am trying to test testPostRequest method returns the correct value.
Following is my test class
class CustomFormPageTest extends FunctionalTest
{
protected static $fixture_file = 'fixtures.yml';
public function testTestingPost()
{
$formPage = $this->objFromFixture(CustomFormPage::class, 'form_page');
$response = $this->post($formPage->URLSegment . '/testPostRequest', [
'name' => 'testing'
]);
var_dump($response);
}
}
Following is my fixtures.yml file.
SilverStripe\CMS\Model\SiteTree:
sitetree_page_one:
ID: 1
ClassName: CustomFormPage
Title: Page Title 1
URLSegment: custom-form-page
CustomFormPage:
form_page:
ID: 1
Title: Page Title 1
URLSegment: custom-form-page
When I run the test, it is always returning 404 not found status even though the page is created in the database. What is missing in my code and how can I fix it?
I just found the solution. We need to publish the page in the test as follows.
$formPage->publish("Stage", "Live");
I need to be able test my component (methods, computed properties, data, ...). However, when I import my vue component in my unit test:
import Pagination from 'src/components/shared/pagination.vue'
import { newComponent } from '../component-factory'
describe('pagination.vue', () => {
const propsData = {
metadata: {
page: 2,
records: 155,
total: 11,
},
perPage: 15,
}
it('should have correct number of records', () => {
const ctor = Vue.extend(Pagination)
const vm = new ctor({propsData}).$mount()
expect(vm.firstRecord).toBe(16)
expect(vm.lastRecord).toBe(30)
})
...
vm is of type Vue, and thus does not have the firstRecord/lastRecord properties. Running the test with karma shows a success, but the typescript compiler spits out Errors:
ERROR in ./tests/shared/pagination.spec.ts
(16,19): error TS2339: Property 'firstRecord' does not exist on type 'Vue'.
ERROR in ./tests/shared/pagination.spec.ts
(17,19): error TS2339: Property 'lastRecord' does not exist on type 'Vue'.
I tried casting:
...
const vm = new ctor({propsData}).$mount() as Pagination
...
But that results in a warning in VSCode:
[ts] Cannot find name 'Pagination'.
And has the effect of treating vm as type any which is totally counterproductive.
I think this all stems from the fact that when using .vue files you have to add the declaration:
declare module '*.vue' {
import Vue from 'vue'
export default typeof Vue
}
Which clearly sets the type of all .vue files to Vue, which isn't exactly a lie, but isn't helpful either... Any suggestions? What am I doing wrong?
For future reference, I have attempted to use vuetype which generates .d.ts files for each .vue file, but ran into this issue. Also, there is a request to make .vue a first class citizen in the typescript ecosystem, which would eliminate this problem. And, I just added a request for a vue language service extension
Up until Vue 2.5, their TypeScript documentation page recommended exporting an interface that extends Vue if you were not going to use vue-class-component. You can export this interface to use in your tests, to cast your component instance. The recommendation has been removed from the docs, but I have not been able to figure out how to change my tests to not need the interface.
It looks like vuetype could generate these interfaces for you, but I've just been creating them manually.
Here is a greatly simplified example, but you can define anything in your interface that you would reference on vm, ie data, props, methods:
// NOTE: Make sure your interface extends `Vue`!
export interface PaginationComponent extends Vue {
firstRecord: number,
lastRecord: number
}
export default {
name: 'Pagination',
data: function() {
return {
firstRecord: 16,
lastRecord: 30,
}
}
}
For your test, you can cast the component instance to the type of your exported interface:
import Pagination, {PaginationComponent} from 'src/components/shared/pagination.vue'
describe('pagination', () => {
it('should know about component data fields', () => {
const ctor = Vue.extend(Pagination)
const vm : PaginationComponent = new ctor().$mount()
expect(vm.firstRecord).toBe(16)
expect(vm.lastRecord).toBe(30)
})
})
Please help to understand.
In the standard application CRUD, at connection of Service: /src/App/Panel/Service/CategoriesService.php in Action: /src/App/Panel/Action/PanelCategoriesAction.php happens 500 error
link to repository: https://github.com/drakulitka/expressive.loc.git
Zend Expressive + Doctrine
Sorry for my English
You are mixing a few things up here. This should be your entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="categories")
* #ORM\Entity(repositoryClass="App\Entity\Repository\CategoriesRepository")
*/
class Categories
{
}
In the doc comment annotation it tells Doctrine where to find the custom repository class. Doctrine loads it for you.
The repositry doesn't need a constructor. Doctrine takes care of this for you.
<?php
namespace App\Entity\Repository;
use App\Entity\Categories;
use Doctrine\ORM\EntityRepository;
class CategoriesRepository extends EntityRepository implements CategoriesRepositoryInterface
{
// No constructor here
public function fetchAll()
{
// ...
}
}
And then your factory looks like this:
<?php
namespace App\Panel\Factory;
use Doctrine\ORM\EntityManager;
use Interop\Container\ContainerInterface;
use App\Entity\Categories;
class CategoriesRepositoryFactory
{
/**
* #param ContainerInterface $container
* #return CategoriesRepository
*/
public function __invoke(ContainerInterface $container)
{
// Get the entitymanager and load the repository for the categories entity
return $container->get(EntityManager::class)->getRepository(Categories::class);
}
}
In the config you use this:
<?php
return [
'dependencies' => [
'invokables' => [
],
'abstract_factories' => [
],
'factories' => [
App\Entity\Repository\CategoriesRepositoryInterface::class => App\Panel\Factory\CategoriesRepositoryFactory::class,
],
],
];
I am preparing SPA website containing hundreds of article-like pages (apart from eCommerce, login etc.). Every article has its own URL. I want to realize it using Angular2.
The only solution I found so far is:
1. to prepare hundreds of Agular2 components, one component for every article...
...with templateUrl pointing to article markup. So I will need hundreds of components similar to:
#core.Component({
selector: 'article-1',
templateUrl: 'article1.html'
})
export class Article1 {}
2. to display an article using AsyncRoute
see Lazy Loading of Route Components in Angular2
#core.Component({
selector: 'article-wrapper',
template: '<router-outlet></router-outlet>'
})
#router.RouteConfig([
new router.AsyncRoute({
path: '/article/:id',
loader: () => {
switch (id) {
case 1: return Article1;
case 2: return Article2;
//... repeat it hundreds of times
}
},
name: 'article'
})
])
class ArticleWrapper { }
In Angular1 there was ngInclude directive, which is missing in Angular2 due to the security issues (see here).
[Edit 1] There is not only problem with the code itself. Problem is also with static nature of this solution. If I need website with sitemap and dynamic page structure - adding a single page needs recompilation of the whole ES6 JavaScript module.
[Edit 2] The concept "markup x html as data" (where markup is not only static HTML but also HTML with active components) is basic concept of whole web (every CMS has its markup data in database). If there does not exist Angular2 solution for it, it denies this basic concept. I believe that there must exist some trick.
All following solutions are tricky. Official Angular team support issue is here.
Thanks to #EricMartinez for pointing me to #alexpods solution:
this.laoder.loadIntoLocation(
toComponent(template, directives),
this.elementRef,
'container'
);
function toComponent(template, directives = []) {
#Component({ selector: 'fake-component' })
#View({ template, directives })
class FakeComponent {}
return FakeComponent;
}
And another similar (from #jpleclerc):
#RouteConfig([
new AsyncRoute({
path: '/article/:id',
component: ArticleComponent,
name: 'article'
})
])
...
#Component({ selector: 'base-article', template: '<div id="here"></div>', ... })
class ArticleComponent {
public constructor(private params: RouteParams, private loader: DynamicComponentLoader, private injector: Injector){
}
ngOnInit() {
var id = this.params.get('id');
#Component({ selector: 'article-' + id, templateUrl: 'article-' + id + '.html' })
class ArticleFakeComponent{}
this.loader.loadAsRoot(
ArticleFakeComponent,
'#here'
injector
);
}
}
A bit different (from #peter-svintsitskyi):
// Faking class declaration by creating new instance each time I need.
var component = new (<Type>Function)();
var annotations = [
new Component({
selector: "foo"
}),
new View({
template: text,
directives: [WordDirective]
})
];
// I know this will not work everywhere
Reflect.defineMetadata("annotations", annotations, component);
// compile the component
this.compiler.compileInHost(<Type>component).then((protoViewRef: ProtoViewRef) => {
this.viewContainer.createHostView(protoViewRef);
});
I have a simple Ionic2 component using the following directives:
#View({
templateUrl: 'build/components/checkinDateInput/checkinDateInput.html',
directives: [ FocusDirective, Item, Label, TextInput ],
})
When testing this I'm getting an error: No provider for Form! (Item -> Form)
I have tried adding the provider to my spec:
beforeEachProviders(() => [Form]);
However, Form is private in Ionic and as such I don't seem to be able to import it (ionic-framework/util/form.d.ts):
/**
* #private
*/
export declare class Form {
private _blur;
...
error TS2305: Module '".../node_modules/ionic-framework/ionic"' has no exported member 'Form'.
As it can't be imported, I can't mock it out in the beforeEachProviders, because Form would be undefined.
beforeEachProviders(() => [
provide(Form, {useClass: MockForm})
]);
Should I be able to import Form or am I going about this the wrong way?
Issue with Ionic2, fixed in the next release
https://github.com/driftyco/ionic/commit/d27bb628fce40c644422016d054acd5c0317810d